在 OpenGL 中,着色器变量 是在着色器程序(使用 GLSL 语言编写)中使用的特殊变量,它们是实现 CPU 上的应用程序与 GPU 上的着色器之间,以及不同着色器阶段之间进行数据通信的关键机制。 简单来说,它们是数据进出着色器这个小程序”的通道。
着色器变量主要通过存储限定符(Storage Qualifiers)来定义其作用和数据流向。在现代 OpenGL (3.3+ Core Profile) 中,主要的限定符是 in
、out
和 uniform
。在旧版 OpenGL ES 2.0 或桌面版 OpenGL 的兼容性配置文件中,则使用 attribute
和 varying
。
以下是主要着色器变量类型的详细解释:
1. uniform
(全局变量)
uniform
变量用于从 CPU 应用程序向 GPU 上的着色器传递数据。
- 作用:传递对于一次完整的绘制指令(例如,绘制一个模型)中所有顶点和片段都保持一致的数据。
- 特点:
- 全局性:在单个着色器程序对象中,
uniform
变量是全局的,顶点着色器和片段着色器都可以访问到同一个uniform
变量。 - 只读性:对于着色器来说,
uniform
变量是只读的,它们的值不能在着色器内部被修改。 - 由 CPU 设置:其值由 CPU 端的应用程序通过
glUniform*
系列函数进行设置。
- 全局性:在单个着色器程序对象中,
- 常见用途:传递变换矩阵(模型、视图、投影矩阵)、光照参数、全局颜色、时间值等。
示例 (GLSL 代码):
uniform mat4 projectionMatrix; // 投影矩阵
uniform vec4 ourColor; // 一个全局颜色
2. in
(输入变量)
in
变量用于将数据传入一个着色器阶段。
-
在顶点着色器中 (等同于旧版的
attribute
):- 作用:接收从顶点缓冲对象 (VBO) 传来的逐顶点数据。
- 特点:每个顶点都有自己独有的一套数据。这是定义模型形状和顶点特定属性(如颜色、纹理坐标)的基础。
- 常见用途:顶点位置、法线向量、顶点颜色、纹理坐标。
-
在片段着色器中 (等同于旧版的
varying
的接收端):- 作用:接收从顶点着色器传递过来的数据。
- 特点:接收到的值是经过光栅化阶段插值计算后的结果。例如,如果三角形的三个顶点颜色不同,那么三角形内部的每个片段接收到的颜色值将是这三个顶点颜色的平滑渐变。
3. out
(输出变量)
out
变量用于将数据从一个着色器阶段传出到下一个阶段。
-
在顶点着色器中 (等同于旧版的
varying
的发送端):- 作用:将数据传递给片段着色器。这些数据会先经过光栅化器的插值处理。
- 声明:在一个阶段声明为
out
的变量,必须在下一个阶段声明为同名同类型的in
变量,才能正确链接。
-
在片段着色器中:
- 作用:指定当前片段(像素)的最终输出颜色。
示例:数据从顶点着色器传递到片段着色器
// --- 顶点着色器 (Vertex Shader) ---
#version 330 core
layout (location = 0) in vec3 aPos; // 输入:顶点位置 (来自VBO)
layout (location = 1) in vec3 aColor; // 输入:顶点颜色 (来自VBO)
out vec3 ourColor; // 输出:将颜色传递给片段着色器
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor; // 将输入的顶点颜色直接传递出去
}
// --- 片段着色器 (Fragment Shader) ---
#version 330 core
out vec4 FragColor; // 输出:最终的像素颜色
in vec3 ourColor; // 输入:从顶点着色器接收的、经过插值的颜色
void main()
{
FragColor = vec4(ourColor, 1.0);
}
旧版限定符 (attribute
和 varying
)
attribute
: 只能在顶点着色器中使用,功能与现代GLSL中的in
变量(用于顶点输入)完全相同,用于接收逐顶点数据。varying
: 用于在顶点着色器和片段着色器之间传递经过插值的数据。它在顶点着色器中被赋值,在片段着色器中被读取。varying
的功能被现代GLSL的out
(顶点着色器) 和in
(片段着色器) 组合所取代。
内建变量 (Built-in Variables)
GLSL 还提供了一些以 gl_
开头的内建变量,它们具有预定义的行为:
gl_Position
: 顶点着色器的输出变量,必须被赋值。它决定了顶点在屏幕上的最终位置。gl_FragColor
: 片段着色器的输出变量(在旧版GLSL中),用于指定片段的颜色。现代GLSL中通常由自定义的out
变量代替。gl_FragCoord
: 片段着色器的输入变量,包含片段的窗口坐标。