美文网首页
(四)着色器和程序

(四)着色器和程序

作者: YongtaoHuang | 来源:发表于2019-10-10 23:08 被阅读0次

上一篇:(三)EGL简介:https://www.jianshu.com/p/bb6a13c6066f
下一篇:(五)OpenGL ES着色语言:https://www.jianshu.com/p/5712ec080cc2

渲染一个三角形需要以下3部分:
1、顶点着色器对象
2、片元着色器对象
3、一个程序对象

着色器和程序

需要创建两个基本对象才能用着色器进行渲染:着色器对象程序对象
着色器对象可视为C语言的编译器。
程序对象可视为C语言的链接程序。
再OpenGL ES中,每个程序对象必须链接一个顶点着色器和一个着色器对象。而程序对象被链接为用于渲染的最后“可执行程序”。

创建和编译一个着色器

主要函数有:

// 创建着色器对象
GLuint glCreateShader(GLenum type)
// 删除着色器
void glDeleteShader(GLuint shader)
// 加载着色器源码
void glShaderSource(GLuint shader, GLsizei count,
    const GLchar* const *string,
    const GLint *length)
// 编译着色器
void glCompileShader(GLuint shader)

加载着色器源码:

GLuint LoadShader ( GLenum type, const char *shaderSrc ) {
    GLuint shader;
    GLint compiled;
    // 创建着色器对象
    shader = glCreateShader ( type );
    if ( shader == 0 ) {
        return 0;
    }
    // 加载着色器源码
    glShaderSource ( shader, 1, &shaderSrc, NULL );
    // 编译着色器
    glCompileShader ( shader );
    // 确认编译状态
    glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
    if ( !compiled ) {
        // 编译失败时检索编译消息
        GLint infoLen = 0;
        glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
        if ( infoLen > 1 ) {
            char* infoLog = malloc ( sizeof ( char ) * infoLen );
            // 检索信息日志
            glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
            esLogMessage(“Error compiling shader:\n%s\n”, infoLog);
            free ( infoLog );
        }
        // 删除着色器
        glDeleteShader ( shader );
        return 0;
    }
    return shader;
}

创建和链接程序

主要函数有:

// 创建一个程序对象
GLuint glCreateProgram()
// 删除一个程序对象
Void glDeleteProgram(GLuint program)
// 连接一个着色器
void glAttachShader(GLuint program, GLuint shader)
// 链接到程序
void glLinkProgram(GLuint program)
// 使用这个程序对象
void glUseProgram(GLuint program)

创建程序、连接着色器并链接程序

// 创建一个程序对象
programObject = glCreateProgram ( );
if ( programObject == 0 ) {
    return 0;
}
// 连接一个顶点着色器
glAttachShader ( programObject, vertexShader );
// 连接一个片元着色器
glAttachShader ( programObject, fragmentShader );
// 链接到程序
glLinkProgram ( programObject );
// 检查链接状态
glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
if ( !linked ) {
    // 编译失败时检索编译消息
    GLint infoLen = 0;
    glGetProgramiv( programObject, GL_INFO_LOG_LENGTH, &infoLen);
    if ( infoLen > 1 ) {
        char* infoLog = malloc ( sizeof ( char ) * infoLen );
        // 检索信息日志
        glGetProgramInfoLog ( programObject, infoLen, NULL,
        infoLog );
        esLogMessage ( “Error linking program:\n%s\n”, infoLog );
        free ( infoLog );
    }
    // 删除一个程序对象
    glDeleteProgram ( programObject );
    return FALSE;
}
// 使用这个程序对象
glUseProgram ( programObject );

统一变量和属性

统一变量(uniform)是存储应用程序通过OpenGL ES 3.0 API传递给着色器的只读常数值得变量。分两类:
1、统一变量块:

uniform TransformBlock {
    mat4 matViewProj;
    mat3 matNormal;
    mat3 matTexGen;
};

2、统一变量:

uniform mat4 matViewProj;
uniform mat3 matNormal;
uniform mat3 matTexGen;

获取和设置统一变量

主要函数有:

// 获取每一个统一变量的细节
void glGetActiveUniform(GLuint program, 
    GLuint index,
    GLsizei bufSize, 
    GLsizei *length,
    GLint *size, 
    GLenum *type,
    GLchar *name)
 // 获取统一变量值的位置
GLint glGetUniformLocation(GLuint program,
    const GLchar* name)

查询活动统一变量:

GLint maxUniformLen;
GLint numUniforms;
char *uniformName;
GLint index;
// 获取程序中活动统一变量的数量
glGetProgramiv ( progObj, GL_ACTIVE_UNIFORMS, &numUniforms );
// 获取程序中活动统一变量的最大长度
glGetProgramiv ( progObj, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen );
uniformName = malloc ( sizeof ( char ) * maxUniformLen );
for ( index = 0; index < numUniforms; index++ ) {
    GLint size;
    GLenum type;
    GLint location;
    // 获取每一个统一变量的细节
    glGetActiveUniform ( progObj, index, maxUniformLen, NULL, &size, &type, uniformName );
    // 获取统一变量值的位置
    location = glGetUniformLocation ( progObj, uniformName );
    switch ( type ) {
        case GL_FLOAT:
            //
            break;
        case GL_FLOAT_VEC2:
            //
            break;
        case GL_FLOAT_VEC3:
            //
            break;
        case GL_FLOAT_VEC4:
            //
            break;
        case GL_INT:
            //
            break;
            // ... Check for all the types ...
        default:
            // Unknown type
            break;
    }
}

统一变量缓冲区对象

主要函数有:

// 检索统一块索引
GLuint glGetUniformBlockIndex(GLuint program,
    const GLchar *blockName)
// 将统一块索引与绑定点关联
void glUniformBlockBinding(GLuint program,
    GLuint blockIndex,
    GLuint blockBinding)
// 获取lightData的大小
void glGetActiveUniformBlockiv( GLuint program,
    GLuint index,
    GLenum pname,
    GLint *params)

使用命名统一变量块LightTransform建立一个系统变量缓冲区对象:

GLuint blockId, bufferId;
GLint blockSize;
GLuint bindingPoint = 1;
GLfloat lightData[] = {
    // 光照方向 
    1.0f, 0.0f, 0.0f, 0.0f,
    // 光照位置
    0.0f, 0.0f, 0.0f, 1.0f
};
// 检索统一块索引
blockId = glGetUniformBlockIndex ( program, “LightBlock” );
// 将统一块索引与绑定点关联
glUniformBlockBinding ( program, blockId, bindingPoint );
// 获取lightData的大小
glGetActiveUniformBlockiv ( program, blockId, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize );
// 创建并填充缓冲区对象
glGenBuffers ( 1, &bufferId );
glBindBuffer ( GL_UNIFORM_BUFFER, bufferId );
glBufferData ( GL_UNIFORM_BUFFER, blockSize, lightData, GL_DYNAMIC_DRAW);
// 将缓冲区对象绑定到统一块绑定点
glBindBufferBase ( GL_UNIFORM_BUFFER, bindingPoint, buffer );

获取和设置属性

对顶点属性的查询,可以用GL_ACTIVE_ATTRIBUTES查询找到活动属性列表,也可以
glGetActiveAttrib()找到某个属性的特性。

着色器编译器

编译器必须将抽象表现形式转化为硬件的机器指令。这段工作主要代价为CPU时间和内存。
OpenGL ES 3.0实现必须支持在线着色器编译。注意,一旦完成了应用程序中着色器的编译,记得调用glReleaseShaderCompiler释放资源。

// 释放着色器编译器
void glReleaseShaderCompiler (void)

程序二进制码

程序二进制码是完全编译和链接的程序的二进制表现形式。可以波窜再文件系统,避免重复再次编译。
glGetProgramBinary用于检索程序二进制码:

void glGetProgramBinary( GLuint program,     
    GLsizei bufSize,
    GLsizei *length, 
    GLenum binaryFormat,
    GLvoid *binary)

当检索到程序二进制码之后,可以用glProgramBinary将器保存到文件系统:

void glProgramBinary( GLuint program, 
    GLenum binaryFormat,
    const GLvoid *binary, 
    GLsizei length)

小结

本章主要内容包括创建、编译和链接着色器对象到程序对象的方法。

上一篇:(三)EGL简介:https://www.jianshu.com/p/bb6a13c6066f
下一篇:(五)OpenGL ES着色语言:https://www.jianshu.com/p/5712ec080cc2

相关文章

网友评论

      本文标题:(四)着色器和程序

      本文链接:https://www.haomeiwen.com/subject/fyagpctx.html