上一篇:(三)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
网友评论