learnopengl-2-着色器
learnopengl-2-着色器
GLSL
着色器是使用一种叫GLSL的类C语言写成的。GLSL是为图形计算量身定制的,它包含一些针对向量和矩阵操作的有用特性。
Shader的典型结构
1 |
|
数据类型
GLSL中包含C等其它语言大部分的默认基础数据类型:int、float、double、uint和bool。
还有两种容器类型,分别是向量(Vector)和矩阵(Matrix)
向量
类型 | 含义 |
---|---|
vecn | 包含n个float分量的默认向量 |
bvecn | 包含n个bool分量的向量 |
ivecn | 包含n个int分量的默认向量 |
uvecn | 包含n个unsigned int分量的向量 |
dvecn | 包含n个double分量的默认向量 |
向量的使用十分灵活,如下所示:
1 |
|
输入与输出
GLSL定义了in和out关键字专门来实现这个目的。每个着色器使用这两个关键字设定输入和输出,只要一个输出变量与下一个着色器阶段的输入匹配,它就会传递下去。但有两个特例:顶点着色器和片段着色器。
顶点着色器
顶点着色器需要一种特殊的输入,从顶点数据中直接接收输入。使用location这一元数据指定输入变量
1 |
|
片段着色器
片段着色器需要一个vec4颜色输出变量,因为片段着色器需要生成一个最终输出的颜色。
1 |
|
Uniform
Uniform是一种从CPU中的应用向GPU中的着色器发送数据的方式, 具体使用时就是在shader(GPU)中定义uniform变量,该变量可以在main函数(CPU)中被赋值和改变。
uniform是全局的(Global),必须在每个着色器中都是独一无二的。
在程序中改变uniform的值需要先找到着色器中uniform属性的位置,用glGetUniformLocation函数查询,使用方法如下:
1 |
|
之后使用glUniform函数改变uniform的值:
1 |
|
自己的着色器类
定义一个着色器类实现从硬盘读取着色器,然后编译并链接它们,并对它们进行错误检测。
从文件读取shader
之前我们都使用硬编码shader代码的方式使用shader,在这里尝试从外部文件中读取shader代码。
练习
- 修改顶点着色器让三角形上下颠倒:
1
2
3
4
5
6
7
8
9
10
11#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out vec3 ourColor;
void main()
{
gl_Position = vec4(aPos.x, -aPos.y, aPos.z, 1.0); // 将y坐标取反即可
ourColor = ourColor;
} - 使用uniform定义一个水平偏移量,在顶点着色器中使用这个偏移量把三角形移动到屏幕右侧:
1
2
3
4
5
6
7
8
9
10
11
12#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out vec3 ourColor;
uniform float hori_offset; // 在程序中修改即可
void main()
{
gl_Position = vec4(aPos.x-hori_offset, aPos.y, aPos.z, 1.0);
ourColor = ourColor;
} - 使用out关键字把顶点位置输出到片段着色器,并将片段的颜色设置为与顶点位置相等(来看看连顶点位置值都在三角形中被插值的结果)。做完这些后,尝试回答下面的问题:为什么在三角形的左下角是黑的?:
1
2
3
4
5
6
7
8
9#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
ourColor = aPos;
}
左下角是黑色是因为左下角的坐标是(-0.5f, -0.5f, 0.0f)是负值,而负值在颜色计算时会转换成0,并且插值后的结果也仍然是负值,故直到三角形中心才开始有颜色的渐变。
learnopengl-2-着色器
https://kenny-hoho.github.io/2022/10/28/learnopengl-2-着色器/