1.创建和编译一个着色器
- 使用着色器对象的第一步是创建着色器,用glCreateShader完成
GLuint glCreateShader(GLenum type)
type | Value | 对象 |
---|---|---|
type | GL_VERTEX_SHADER | 顶点着色器 |
type | GL_FRAGMENT_SHADER | 片段着色器 |
返回值 | 指向新着色器对象的句柄 |
当完成着色器对象时,可以用glDeleteShader删除
void glDeleteShader(GLuint shader)
shader 要删除的着色器对象的句柄
如果一个着色器连接到一个程序对象,那么调用glDeleteShader不会立刻删除着色器,而是将着色器标记为删除,在着色器不再连接到任何程序对象时,它的内存将被释放
2.一旦创建了着色器对象,下一件事通常是用glShaderSource提供着色器源代码。
void glShaderSource(GLuint shader,GLsizei count,
const GLchar * const * string, const GLint * length)
shader | 指向着色器对象的句柄 |
---|---|
count | 着色器源字符串的数量 |
string | 指向保存数量为count的着色器源字符串的数组指针 |
length | 指向保存每个着色器字符串大小且元素数量为count的整数数组指针 |
3.指定着色器源代码之后,下一步是用glCompileShader编译着色器
void glCompileShader(GLuint shader)
shader | 需要编译的着色器对象句柄 |
---|
调用glCompileShader将编译已经保存在着色器对象的着色器源代码。
glGetShaderiv查询这一信息和其他有关着色器对象的信息。
GLuint LoadShader( GLenum type,const char *shaderSrc){
GLuint shader;
GLint compiled;
shader = glCreateShader(type);
if(shader == 0){
return 0;
}
//Load the shader source
glShaderSource(shader,1,&shaderSrc,NULL);
//Compile the shader
glCompileShader(shader);
//Check the compile status
glGetShaderiv(shader,GL_COMPILE_STATUS,&compiled);
if(!compiled){
GLint infoLen = 0;
glGetShaderiv(shader,GL_INFO_LOG_LENGTH,&inforLen);
if(infoLen > 1){
char* infoLog = malloc(sizeof()*infoLen);
glGetShaderInfoLog(shader,infoLen,NULL,infoLog);
esLogMessage("Error comiling shader:\n%s\n",infoLog);
}
glDeleteShader();
return 0;
}
return shader;
}
2 创建和链接程序
程序对象时一个容器对象,可以将着色器与之连接,并链接一个最终的可执行程序》
函数 | 说明 |
---|---|
GLuint glCreateProgram() | 创建一个程序对象 |
void glDeleteProgram(GLuint program) | 删除一个程序对象 |
void glAttachShader(GLuint program, GLuint shader) | 连接着色器和程序 |
void glLinkProgram(GLuint program) | 生成最终的可执行文件 |
void glUseProgram(GLuint program) | 将程序对象设置为活动程序 |
在OpenGL ES 3.0中,每个程序对象必须连接一个顶点着色器和一个片段着色器。
着色器可以在任何时候连接,在连接到程序之前不一定需要编译,甚至可以没有源代码。唯一的要求是,每个程序对象必须有且只有一个顶点着色器和片段着色器与之连接。除了连接着色器之外,你还可以用glDetachShader断开着色器的连接。
一旦连接了着色器(并且着色器已经成功编译),就最终为链接着色器做好了准备。程序对象的链接用glLinkProgram完成。
链接操作负责生成最终的可执行程序。链接程序将检查各种对象的数量,确保成功链接。
链接程序之后,必须检查链接是否成功,可以使用glGetProgramiv检查链接状态
void glGetProgramiv(GLuint program,GLenum pname,GLint *params)
void glGetProgramInfoLog(GLuint program,GLsizei maxLength,
GLsizei * length,GLchar *infoLog )
在渲染之前,用glUseProgram将程序对象设置为活动程序
//Create the program object
programObject = glCreateProgram();
if(programObject == 0){
return 0;
}
glAttachShader(programObject,vertexShader);
glAttachShader(programObject,fragmentShader);
//Link the program
glLinkProgram(programObject);
//Check the link status
glGetProgramiv(programObject,GL_LINK_STATUS,&linked);
if(!linked){
//Retrieve compiler error messages when linking fails
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;
}
//Use the program object
glUseProgram(programObject);
着色器编译器
编译器代码通常解析成某种中间表现形式。编译器必须将抽象表示形式转化为硬件的机器指令。理想状态下,这个编译器还应该进行大量的优化,如无用代码删除,常量传播等。
程序二进制码
程序二进制码是完全编译和链接的程序的二进制表现形式。因为可以保存到文件系统供以后使用,从而避免在线编译的代价,使用程序二进制码,就没有必要在实现中分发着色器源代码
OpenGL ES 规范不强制使用任何特定的二进制格式,相反,二进制格式完全取决于供应商。这意味着程序的可移植性较差。