在Shader编程中,Uniform 是一种特殊的全局变量,用于在CPU(应用程序)和GPU(Shader)之间传递数据。它的核心特点是:值由CPU设置,在Shader运行时保持常量(不可修改),但可以在不同渲染调用之间改变。
关键特性
-
只读性
Shader代码中不能修改Uniform的值,它只能由CPU通过图形API(如OpenGL、WebGL、Vulkan等)设置。 -
全局性
在Shader的所有执行实例(如顶点着色器的每个顶点、片段着色器的每个像素)中,Uniform的值是相同的。 -
高效传递
Uniform的值存储在GPU的常量区域,访问速度快,适合传递低频变化的参数(如变换矩阵、光照参数等)。
常见用途
Uniform通常用于传递以下数据:
- 变换矩阵:模型(
modelMatrix)、视图(viewMatrix)、投影(projectionMatrix)。 - 光照参数:光源位置、颜色、强度。
- 材质属性:颜色、纹理采样器、反射系数。
- 时间变量:用于动画(如
u_time控制动态效果)。
代码示例
1. Shader中的声明(GLSL示例)
// 顶点着色器
uniform mat4 u_projectionMatrix;
uniform vec3 u_lightPosition;
void main() {
gl_Position = u_projectionMatrix * vec4(position, 1.0);
}
2. CPU端设置Uniform(以WebGL为例)
// 获取Uniform位置
const projectionMatrixLoc = gl.getUniformLocation(program, "u_projectionMatrix");
const lightPosLoc = gl.getUniformLocation(program, "u_lightPosition");
// 设置Uniform的值
gl.uniformMatrix4fv(projectionMatrixLoc, false, projectionMatrix);
gl.uniform3f(lightPosLoc, 1.0, 2.0, 3.0);
与其他变量的区别
| 变量类型 | 作用域 | 可修改性 | 传递方向 | 典型用途 |
|---|---|---|---|---|
| Uniform | 全局,跨Shader | CPU → GPU | 低频全局参数 | 矩阵、光照、时间 |
| Attribute | 顶点级(顶点着色器) | CPU → GPU | 逐顶点数据 | 顶点位置、法线、UV |
| Varying | 顶点→片段着色器 | GPU内部 | 插值数据 | 颜色、纹理坐标传递 |
| Sampler | 纹理采样器 | CPU → GPU | 纹理绑定 | 贴图引用 |
注意事项
- 性能优化
Uniform的频繁更新可能引发性能问题,尽量合并相关参数(如将多个vec3组合成mat4)。 - 兼容性
不同Shader语言(GLSL、HLSL)中Uniform的语法可能略有差异。 - 调试
如果Uniform未正确设置,Shader可能使用默认值(如0或未定义行为),需检查设置代码和变量名是否匹配。
Uniform是Shader与外部世界沟通的桥梁,合理使用它能高效控制渲染效果。