GLSL语言简单入门
为什么会有着色器语言
GLSL(OpenGL Shader Language) 是一种类C语言,它包含了一些针对向量和矩阵的特性。
它是着色器(Shader)使用的语言,着色器是运行在GPU上的小程序,供渲染管线中的某个特定部分使用。
GLSL的结构
1 |
|
首先声明使用的OpenGL版本
其次由于渲染管线的结构,每一个着色器之间通过输入输出变量来通信,所以需要声明输入和输出变量,uniform和main函数。
当我们特别谈论到顶点着色器的时候,每个输入变量也叫顶点属性(Vertex Attribute)。我们能声明的顶点属性是有上限的,它一般由硬件来决定。OpenGL确保至少有16个包含4分量的顶点属性可用,但是有些硬件或许允许更多的顶点属性,你可以查询GL_MAX_VERTEX_ATTRIBS来获取具体的上限:
1
2
3 int nrAttributes;
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &nrAttributes);
std::cout << "Maximum nr of vertex attributes supported: " << nrAttributes << std::endl;
数据类型
默认基础数据类型:int、float、double、uint、bool
容器类型:Vector、Matrix
向量
向量是一个可以包含2、3或4个分量的容器。
分量的类型可以是之前默认基础类型的任何一个。
获取分量可以通过vec.x来获取
分量的重组
1 | vec2 someVec; |
矩阵将在后面介绍
输入与输出
GLSL定义了in和out关键词来负责渲染管线中不同着色器之间的数据的交流和传递。
但是在顶点和片段着色器中有一些特殊的地方
顶点着色器
顶点着色器作为渲染管线中的第一个着色器,它接受的不是其他着色器输出的变量,而是从缓存中获取的顶点数据,我们在笔记2中,使用了glVertexAttribPointer函数来规定顶点数据该如何使用,其中第一个参数叫做顶点参数的位置值,他就是我们在编写顶点着色器中声明的。
方法是layout(location = 0)作为in关键词的前缀。location是用来标记顶点数据的码(Key)。
片段着色器
它需要一个vec4颜色输出变量,因为片段着色器需要生成一个最终输出的颜色。如果你在片段着色器没有定义输出颜色,OpenGL会把你的物体渲染为黑色(或白色)。
Uniform
Uniform类似于c++中全局变量的意思,这意味着它必须在每个着色器程序对象中都是第一无二的,它可以被着色器程序d饿任意着色器在任意阶段访问,第二,无论你把uniform设置为什么,uniform会一直保存。
我们可以在一个着色器中添加uniform关键字至类型和变量名前来声明一个GLSL的uniform。
1 |
|
我们在片段着色器中声明了一个uniform vec4的ourColor,并把片段着色器的输出颜色设置为uniform值的内容。这个uniform值的内容是一个颜色,这个颜色在OpenGL程序中设定好了,我们现在要做的就是找到它的索引值,这样才能更新它。
我们用glGetUniformLocation查询uniform ourColor的位置值。
这里我们用uniform,来制作一个颜色会随着时间改变而改变的三角形。
使用如上的片段着色器,然后在渲染循环中加上如下的代码
1 | float timeValue = glfwGetTime(); |
我们使用glfwGetTime()函数来获取时间,通过sin函数来进行标准化处理,作为我们的颜色值.
使用glGetUniformLocation来查询uniform ourcolor的值,我们提供对应的着色器程序和uniform的名字,如果glGetUniformLocation返回-1就代表没有找到这个位置值。最后,我们可以通过glUniform4f函数设置uniform值。注意,查询uniform地址不要求你之前使用过着色器程序,但是更新一个uniform之前你必须先使用程序(调用glUseProgram),因为它是在当前激活的着色器程序中设置uniform的。
这样我们的uniform变量就设置完成了。