GLSL(OpenGL Shading Language)是用于编写 OpenGL 着色器程序的高级编程语言,主要分为顶点着色器(Vertex Shader)、片段着色器(Fragment Shader),有时还会用到几何着色器(Geometry Shader)等。
1. 版本声明
在 GLSL 代码开头,通常需要声明使用的 GLSL 版本,以确保编译器能正确解析代码。
#version 330 core
#version
是预处理指令。330
表示使用的是 OpenGL 3.3 对应的 GLSL 版本。core
表示使用核心模式,该模式移除了一些已被弃用的特性。
2. 数据类型
2.1 基本数据类型
float
:单精度浮点数,例如float myFloat = 1.0;
。int
:整数类型,例如int myInt = 5;
。bool
:布尔类型,值为true
或false
,例如bool myBool = true;
。
2.2 向量类型
向量类型由基本数据类型组合而成,常见的有:
vec2
、vec3
、vec4
:分别表示二维、三维和四维浮点数向量。例如:
vec2 myVec2 = vec2(1.0, 2.0);
vec3 myVec3 = vec3(1.0, 2.0, 3.0);
vec4 myVec4 = vec4(1.0, 2.0, 3.0, 4.0);
ivec2
、ivec3
、ivec4
:整数向量。bvec2
、bvec3
、bvec4
:布尔向量。
2.3 矩阵类型
矩阵类型用于表示变换矩阵,常见的有:
mat2
、mat3
、mat4
:分别表示 2x2、3x3 和 4x4 的浮点数矩阵。例如:
mat4 myMat4 = mat4(1.0, 0.0, 0.0, 0.0,0.0, 1.0, 0.0, 0.0,0.0, 0.0, 1.0, 0.0,0.0, 0.0, 0.0, 1.0
);
3. 变量声明与修饰符
3.1 变量声明
和其他编程语言类似,GLSL 声明变量时需要指定类型。例如:
float myFloat;
vec3 myVec3;
3.2 修饰符
in
:用于声明输入变量,通常用于顶点着色器接收顶点属性,或片段着色器接收顶点着色器传递的数据。例如:
// 顶点着色器中接收顶点位置
layout (location = 0) in vec3 aPos;
layout (location = 0)
是用于指定该输入变量在顶点属性中的位置。
out
:用于声明输出变量,顶点着色器使用out
变量将数据传递给片段着色器。例如:
// 顶点着色器中传递颜色数据给片段着色器
out vec3 ourColor;
uniform
:用于声明全局变量,在着色器程序运行期间保持不变,可在 CPU 端设置其值。例如:
// 片段着色器中使用的全局颜色变量
uniform vec4 ourColor;
4. 函数
4.1 内置函数
GLSL 提供了许多内置函数,用于数学计算、向量和矩阵操作等。例如:
length()
:计算向量的长度。
vec3 myVec3 = vec3(1.0, 2.0, 3.0);
float len = length(myVec3);
dot()
:计算两个向量的点积。
vec3 vecA = vec3(1.0, 0.0, 0.0);
vec3 vecB = vec3(0.0, 1.0, 0.0);
float dotProduct = dot(vecA, vecB);
4.2 用户自定义函数
用户可以自定义函数,函数定义包括返回类型、函数名、参数列表和函数体。例如:
// 自定义函数:计算两个向量的和
vec3 addVectors(vec3 a, vec3 b) {return a + b;
}
5. 顶点着色器和片段着色器示例
5.1 顶点着色器示例
#version 330 core
// 输入顶点位置
layout (location = 0) in vec3 aPos;
// 输出颜色数据给片段着色器
out vec3 ourColor;void main()
{// 设置顶点位置gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);// 传递颜色数据ourColor = vec3(1.0, 0.0, 0.0);
}
5.2 片段着色器示例
#version 330 core
// 接收顶点着色器传递的颜色数据
in vec3 ourColor;
// 输出最终的片段颜色
out vec4 FragColor;void main()
{// 设置片段颜色FragColor = vec4(ourColor, 1.0);
}
6. 向量分量访问
可以通过不同的方式访问向量的分量:
- 按顺序访问:使用
.x
、.y
、.z
、.w
访问向量的分量,也可以使用.r
、.g
、.b
、.a
(用于颜色)或.s
、.t
、.p
、.q
(用于纹理坐标)。例如:
vec3 myVec3 = vec3(1.0, 2.0, 3.0);
float x = myVec3.x;
float r = myVec3.r;
- 分量重组:可以通过重新组合向量的分量来创建新的向量。例如:
vec3 myVec3 = vec3(1.0, 2.0, 3.0);
vec2 newVec2 = myVec3.xy;
vec4 newVec4 = vec4(myVec3.zyx, 1.0);
7. 控制流语句
GLSL 支持常见的控制流语句,如 if-else
、for
循环等。
7.1 if-else
语句
float value = 5.0;
if (value > 10.0) {// 执行某些操作
} else {// 执行其他操作
}
7.2 for
循环
for (int i = 0; i < 10; i++) {// 循环体
}