最近在学OpenGL,看到shader,比较难记。后来找到一篇博主写的步骤非常通俗易懂,本来只是想收藏的,但是有几个函数想补充一下,所以还是自己写了一篇。
在OpenGL中,创建和使用Shader的基本步骤如下:
1、通过glCreateShader创建一个或多个着色器对象:
2、使用glShaderSource加载着色器的源代码,和着色器对象关联;
3、glCompileShader编译每个着色器对象
4、使用glCreateProgram创建程序对象
5、通过glAttachShader将所有着色器对象绑定到程序对象上;
6、glLinkProgram链接程序对象;
7、调用glUseProgram使用着色器程序对象,使得着色器可执行程序成为OpenGl当前状态的一部分。
补充:
调试
调试一个shader是非常困难的。shader的世界里没有printf,无法在控制台中打印调试信息, 更没有断点,甚至很多编辑器对shader程序关键字、变量等连高亮显示都不支持。 但是可以通过一些OpenGL提供的函数来获取编译和连接过程中的信息。
在编译阶段使用glGetShaderiv获取编译情况,在连接阶段使用glGetProgramiv获取连接情况。当错误产生的时候,还可以从InfoLog中获得更多的信息。InfoLog中存储了关于上一个操作执行时的相关信息,比如编译阶段的警告和错误,以及连接阶段产生的问题。不幸的是对于错误信息没有统一的标准,所以不同的硬件或驱动程序将提供不同的错误信息。
编译阶段使用glGetShaderiv获取编译情况
函数原型:
void glGetShaderiv (int shader, int pname, int[] params, int offset)
参数含义:
shader是一个shader的id;
pname使用GL_COMPILE_STATUS;
params是返回值,如果一切正常返回GL_TRUE代,否则返回GL_FALSE。
编译阶段使用glGetShaderInfoLog获取编译错误
函数原型:
String glGetShaderInfoLog (int shader)
参数含义:
shader是一个顶点shader或者片元shader的id。
在连接阶段使用glGetProgramiv获取连接情况
函数原型:
void glGetProgramiv (int program, int pname, int[] params, int offset)
参数含义:
program是一个着色器程序的id;
pname是GL_LINK_STATUS;
param是返回值,如果一切正常返回GL_TRUE代,否则返回GL_FALSE。
在连接阶段使用glGetProgramInfoLog获取连接错误
函数原型:
String glGetProgramInfoLog (int program)
参数含义:
program是一个着色器程序的id。
还有官方demo使用的一个宏
#define glError() { \
GLenum err = glGetError(); \
if (err != GL_NO_ERROR) { \
printf("glError: %04x caught at %s:%u\n", err, __FILE__, __LINE__); \
} \
}
清理shader的glDeleteShader方法
当不再需要某个shader或某个程序的时候,需要对其进行清理,以释放资源。前面,提到过如何向一个程序中添加一个shader。这里可调用下面的函数来将一个shader从一个程序中清除掉。
函数原型:
void glDeleteShader (int shader);
参数含义:
shader是要被排除的顶点shader或者片元shader的id。