博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OpenGL ES2 学习教程2——HelloOpenGLES2.0
阅读量:6124 次
发布时间:2019-06-21

本文共 6659 字,大约阅读时间需要 22 分钟。

Hello GLES2

和ES1.0不同,ES2.0引入了可编程管线,如下图中,可编程阶段为VertexShader,FragmentShader顶点和片段着色器阶段。

图片描述

顶点着色器被使用在传统的基于顶点的操作,例如位移矩阵、计算光照方程、产生贴图

坐标。顶点着色器被应用指定,应用于客户端的顶点转化。顶点着色器需要一个位置和颜色数据作为输入属性,输入位置数据是 4×4 的矩阵,输出是变换后的位置和颜色。
片段着色器不需定义输出,这是因为片段着色器仅仅的输出是gl_FragColor。

现在我们用上一节的Android入口渲染一个三角形。这里借用NDK包里的例子hello-gl2。看里面的lesson2的tag

宏文件

#ifndef _APPMACROS_H__#define _APPMACROS_H__#include 
#include
#include
#include
#include
#define LOG_TAG "GLES-Tutorial"#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__)#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)static void printGLString(const char *name, GLenum s) { const char *v = (const char *) glGetString(s); LOGI("GL %s = %s\n", name, v);}static void checkGlError(const char* op) { for (GLint error = glGetError(); error; error = glGetError()) { LOGI("after %s() glError (0x%x)\n", op, error); }}#endif

这里除了android里的Log外添加了gl2.h, gl2ext.h头文件,这两个文件可以在NDK包(platforms/android-19/)中找到,这里使用了android里的libGLESv2.so库。printGLString可以获取到OpenGL属性的状态,checkGlError可以检测OpenGL状态是否有错误。

使用OpenGLES2

先给Director添加成员变量:

GLProgram *_glProgram;    // opengl状态机    GLuint _vPositionHandle;  // 获取到的顶点位置属性
#include "Director.h"#include "AppMacros.h"// 顶点着色器static const char gVertexShader[] =     "attribute vec4 vPosition;\n"    "void main() {\n"    "  gl_Position = vPosition;\n"    "}\n";// 片段着色器static const char gFragmentShader[] =     "precision mediump float;\n"    "void main() {\n"    "  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"    "}\n";// 三角形顶点数据const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f,                                     -0.5f, 0.5f, -0.5f };// ... 省略掉一些void Director::setFrameSize(float width, float height){    LOGI("Director::setFrameSize(%lf, %lf)", width, height);    _fFrameWidth = width;    _fFrameHeight = height;    // 创建一个空源的OpenGL状态机    _glProgram = new GLProgram();    // 将着色器装载和编译    _glProgram->initWithVertexShaderByteArray(gVertexShader, gFragmentShader);    // 链接着色器    _glProgram->link();    // 使用此状态机,着色器将能运用上    _glProgram->use();    // 获取到位置属性,以便用来绘制图形;顶点着色器里的vPosition属性    _vPositionHandle = _glProgram->getAttribLocation("vPosition");    // 设置OpenGL视口,一个2D的长方形区域(Android里GLSurfaceView窗体的大小)    glViewport(0, 0, width, height);    checkGlError("glViewport");}void Director::mainLoop(){    // 每一帧都让灰度值叠加    static float grey;    grey += 0.01f;    if (grey > 1.0f) {        grey = 0.0f;    }    // 用颜色来填充清除深度和颜色缓冲区    glClearColor(grey, grey, grey, 1.0f);    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);    // 将顶点位置属性获取到    glVertexAttribPointer(_vPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);    checkGlError("glVertexAttribPointer");    glEnableVertexAttribArray(_vPositionHandle); // 并将三角形顶点设置进顶点矩阵    checkGlError("glEnableVertexAttribArray");    glDrawArrays(GL_TRIANGLES, 0, 3);  // 绘制三角形图元    checkGlError("glDrawArrays");}

GLProgram是我包装了OpenGL的一些操作,便于使用:

class GLProgram{public:    GLProgram();    ~GLProgram();    /*     * init GLProgram with vertex shader array data and fragment shader array data     */    bool initWithVertexShaderByteArray(const GLchar* vShaderByteArray, const GLchar* fShaderByteArray);    /*     * link shader     */    bool link();    /*     * use this opengl program     */    void use();    /*     * get location attrib     */    GLuint getAttribLocation(const GLchar* attrib);private:    GLuint loadShader(GLenum shaderType, const GLchar* shaderSrc);    GLuint _uProgram;    GLuint _uVertShader;    GLuint _uFragShader;};
bool GLProgram::initWithVertexShaderByteArray(const GLchar* vShaderByteArray, const GLchar* fShaderByteArray){    _uVertShader = loadShader(GL_VERTEX_SHADER, vShaderByteArray);    if (!_uVertShader) {        return false;    }    _uFragShader = loadShader(GL_FRAGMENT_SHADER, fShaderByteArray);    if (!_uFragShader) {        return false;    }    _uProgram = glCreateProgram();    if (!_uProgram) {        return false;    }        glAttachShader(_uProgram, _uVertShader);    checkGlError("glAttachShader");    glAttachShader(_uProgram, _uFragShader);    checkGlError("glAttachShader");        return true;}bool GLProgram::link(){    glLinkProgram(_uProgram);    GLint linkStatus = GL_FALSE;    glGetProgramiv(_uProgram, GL_LINK_STATUS, &linkStatus);    if (linkStatus != GL_TRUE) {        GLint bufLength = 0;        glGetProgramiv(_uProgram, GL_INFO_LOG_LENGTH, &bufLength);        if (bufLength) {            char* buf = (char*) malloc(bufLength);            if (buf) {                glGetProgramInfoLog(_uProgram, bufLength, NULL, buf);                LOGE("Could not link _uProgram:\n%s\n", buf);                free(buf);            }        }        glDeleteProgram(_uProgram);        _uProgram = 0;        return false;    }    return true;}void GLProgram::use(){    glUseProgram(_uProgram);    checkGlError("glUseProgram");}GLuint GLProgram::loadShader(GLenum shaderType, const char* shaderSrc){    GLuint shader = glCreateShader(shaderType);    if (shader) {        glShaderSource(shader, 1, &shaderSrc, NULL);        glCompileShader(shader);        GLint compiled = 0;        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); // check compile information        if (!compiled) {            GLint infoLen = 0;            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);            if (infoLen) {                char* infoLog = (char*) malloc(infoLen);                if (infoLog) {                    glGetShaderInfoLog(shader, infoLen, NULL, infoLog); // seek infor log                     LOGE("Could not compile shader %d:\n%s\n",                            shaderType, infoLog);                    free(infoLog);                }                glDeleteShader(shader);                shader = 0;            }        }    }    return shader;}GLuint GLProgram::getAttribLocation(const GLchar* attrib){    GLuint retAtt = glGetAttribLocation(_uProgram, attrib);    checkGlError("glGetAttribLocation");    LOGI("glGetAttribLocation(\"%s\") = %d\n", attrib, retAtt);    return retAtt;}

OpenGL ES提供了一套运行期动态编译的流程:

  • 1.创建着色器:glCreateShader

  • 2.指定着色器源代码字符串:glShaderSource

  • 3.编译着色器:glCompileShader

  • 4.创建着色器可执行程序:glCompileShader

  • 5.向可执行程序中添加着色器:glAttachShader

  • 6.链接可执行程序:glLinkProgram

Run

编译之前,需要修改下Android.mk

LOCAL_SRC_FILES := \com_richard_glestutorial_GLRenderer.cpp \../core/Director.cpp \../core/GLProgram.cpp                LOCAL_C_INCLUDES := \$(LOCAL_PATH)
$ndk-build  && ant debug  && adb install -r bin/GlesTutorial-debug.apk

运行脚本,将可以看一个绿色的三角形,并且背景在不断变化。

图片描述

转载地址:http://vibua.baihongyu.com/

你可能感兴趣的文章
【Web API系列教程】2.1 — ASP.NET Web API中的路由机制
查看>>
ListView在ScrollView中不显示全部的问题
查看>>
JS-原生代码或方法实现特定效果总结(更新中...)
查看>>
day05_MySQL学习笔记_02
查看>>
二次函数三点式
查看>>
《JavaScript 高级程序设计》第四章:变量、作用域和内存问题
查看>>
拒不承认违法?Uber就无人车上路问题与加州政府展开会谈
查看>>
学习汉语和学习编程的异同点
查看>>
自定义(带属性)标签学习笔记
查看>>
NET Core-学习笔记(四)
查看>>
Veeam 助力 Trend Micro 解决数据保护和灾难恢复挑战
查看>>
WebService就是这么简单
查看>>
Python对字典分别按键(key)和值(value)进行排序
查看>>
Java,Python,Scala比较(三)wordcount
查看>>
python爬虫学习:爬虫QQ说说并生成词云图,回忆满满
查看>>
《Java语言程序设计》大作业报告 九宫格游戏
查看>>
JS-检测浏览器类型及版本
查看>>
[20180316]异步IO和共享服务模式.txt
查看>>
nginx服务器架构(一):基本部署与启动
查看>>
1001号云制造现身2017 MWC,它可以远程操作国内3D打印设备集群
查看>>