第九节—关于GLSL
本文为L_Ares个人写作,包括图片皆为个人亲自操作,如需转载请表明原文出处。
首先,什么是GLSL,他在OpenGL ES中是做什么的?
GLSL的全称是 : OpenGL Shading Language
所以通过名字就很明显的知道了,GLSL是一门语言,而且是着色器语言。
那么着色器,也就是我们的管线也就必然是可编程的了,不然要GLSL干嘛呢?
这也是OpenGL从1.0过度到3.0的变化。在OpenGL 1.0中,都是框架的开发者设定好的管线,也就是我们说的固定管线。OpenGL 2.0时,为了增加OpenGL的适用范围和场景,就开放了可编程管线,让我们可以自定义一些渲染管线。
GLSL的代码执行是在GPU上进行的,GLSL的着色器常见或者说常用的包括了:
-
顶点着色器 (Vertex Shader)
-
片元着色器 (Fragment Shader)
有些shader的代码就是直接用字符串存储的,因为本身GLSL代码就不归你的编译器来编译,或者说从编译--->link--->生成Program,都是你自己来做的。
后来发现这么写shader即不方便阅读,更不方便书写,因为大多的的编译器是没有GLSL语法补全的,写错了都不知道,所以就命名了两种后缀不同的文件,分别存储顶点着色器GLSL代码,和片元着色器GLSL代码:
-
顶点着色器GLSL代码的文件后缀 :
.vsh
-
片元着色器GLSL代码的文件后缀:
.fsh
还可以直接把文件后缀写成.glsl
,在这里写shader代码,顶点和片元要自己来区分。
顶点着色器: 你会看到gl_Postion
片元着色器: 你会看到gl_FragColor
GLSL中的常见函数
上面说了,从编译--->link--->生成Program,都要我们自己完成,那么就需要GLSL中对应的函数,来做到这些。
1. 创建着色器
GLuint glCreateShader(GLenum type);
返回值 :GLuint
: 无符号整型。是一个指向新着色器对象的句柄。可以用glDeleteShader
删除。
参数 : type
: 创建的着色器的类型。也就是顶点着色器就写GL_VERTEX_SHADER
,如果是片元着色器就写GL_FRAGMENT_SHADER
。
2. 删除着色器
void glDeleteShader(GLuint shader);
参数 : shader
: 要删除的着色器对象的句柄。
3. 将GLSL代码链接到Shader上
void glShaderSource(GLuint shader, GLSizei count, const GLChar *const *string, const GLint length);
参数:
(1). shader
: 指向着色器对象的句柄。
(2). count
: 着色器源字符串的数量。着色器可以由多个源字符串组成,但是每个着色器只有一个main
函数。
(3). string
: 指向保存数量的count的着色器源字符串的数组指针。
(4). length
: 指向保存每个着色器字符串大小且元素数量为count的整数数组指针。
4. 编译着色器
void glCompileShader(GLuint shader);
参数 : shader
: 需要编译的着色器对象的句柄。
5. 获取编译之后得到的信息
void glGetShaderiv(GLuint shader, GLenum pname, GLint *params);
参数:
(1). shader
: 需要编译的着色器对象的句柄
(2). pname
: 获取的信息参数。可选 : GL_COMPILE_STATUS
、GL_DELETE_STATUS
、GL_INFO_LOG_LENGTH
、GL_SHADER_SOURCE_LENGTH
、GL_SHADER_TYPE
。
(3). params
: 指向查询结果的整数存储位置的指针。
6. 获取Shader信息日志
void glGetShaderInfoLog(GLuint shader, GLSizei maxLength, GLSizei *length, GLChar *infoLog);
参数:
(1). shader
: 需要获取信息日志的着色器对象的句柄
(2). maxLength
: 保存信息日志的缓存区大小
(3). length
: 写入的信息日志的长度(减去NULL 终止符)。如果不需要知道长度,可以设置这个参数为NULL。
(4). infoLog
: 指向保存信息日志的缓存区的指针(字符串型)。
7. 创建一个程序对象Program
GLuint glCreateProgram();
返回值 : 返回一个新执行程序对象的句柄。
9. 删除一个执行程序对象
void glDeleteProgram(GLuint program);
参数 : program
: 要删除的执行新程序对象的句柄。
10. 着色器与程序(program)链接
或者说是关联起来。
void glAttachShader(GLuint program, GLuint shader);
参数:
(1). 指向执行程序的句柄。
(2). 要链接在一起的着色器句柄。
11. 断开着色器和Program的链接
void glDetachShader(GLuint program, GLuint shader);
参数:
(1). 指向执行程序的句柄。
(2). 要接触链接的着色器句柄。
12. 链接Program(程序)对象
glLinkProgram(GLuint program);
参数 : program
: 指向要链接的程序对象的句柄。
13. 检查程序链接状态
void glGetProgramiv(GLuint program, GLenum pname, GLint *params);
参数:
(1). program
: 需要获取信息的程序对象的句柄
(2). pname
: 可选枚举,会放到最后的图片里面。
(3). params
: 指向查询结果整型存储位置的指针
14. 获取程序信息日志信息
void glGetProgramInfoLog(GLuint shader, GLSizei maxLength, GLSizei *length, GLChar *infoLog);
参数:
(1). shader
: 指向需要获取信息的程序对象句柄。
(2). maxLength
: 存储信息日志的缓存区的大小。
(3). length
: 写入信息日志的长度(减去NULL,终止符)。不想知道可以设置NULL
(4). infoLog
: 指向存储信息日志的字符缓存区的指针。
15. 使用Program(程序)
前提是你的link成功了。
void glUseProgram(GLuint program);
参数: program
: 设置为活动程序的程序对象句柄。