我正在查看一个使用着色器的OpenGL应用程序的源代码。其中一个特定的着色器如下所示:
uniform float someConstantValue;
void main()
{
// Use someConstantValue
}
这个 uniform 只在代码中设置一次,在应用程序运行时不会改变。
在什么情况下,我想将 someConstantValue
声明为 uniform
而不是 const float
?
编辑: 只是澄清一下,这个常量值是一个物理常数。
我正在查看一个使用着色器的OpenGL应用程序的源代码。其中一个特定的着色器如下所示:
uniform float someConstantValue;
void main()
{
// Use someConstantValue
}
这个 uniform 只在代码中设置一次,在应用程序运行时不会改变。
在什么情况下,我想将 someConstantValue
声明为 uniform
而不是 const float
?
编辑: 只是澄清一下,这个常量值是一个物理常数。
重要原因:
错误:循环索引无法与非常量表达式进行比较。
如果我使用:
uniform float myfloat;
...
for (float i = 0.0; i < myfloat; i++)
因为myfloat
不是一个常量表达式
,所以我会得到一个错误。
然而,这个是完全有效的:
const float myfloat = 10.0;
...
for (float i = 0.0; i < myfloat; i++)
为什么?
当GLSL(以及HLSL)被编译成GPU汇编指令时,循环会以非常冗长的方式展开(尽管使用跳转等进行了优化)。这意味着编译时使用
myfloat
值展开循环;如果该值是一个uniform
(即每个渲染调用都可能发生变化),那么该循环直到运行时才能展开(而GPU不做这种即时编译,至少在WebGL中不这样做)。
首先,使用uniform或constant之间的性能差异可能是可以忽略不计的。其次,仅因为一个值在自然界中始终是常量,并不意味着您在程序中总是希望它保持不变。即使当物理值与现实不符时,程序员也经常会调整这些值以产生最佳效果。例如,在某些类型的游戏中,重力加速度经常增加,以使游戏更快节奏。
如果您不想在代码中设置uniform,可以在GLSL中提供默认值:
uniform float someConstantValue = 12.5;
话虽如此,对于像圆周率这样的变量,使用const是没有问题的,因为它没有被修改的必要。
开发人员在多个应用程序中重复使用着色器库。因此,开发人员尝试保持它们的通用性,而不是为每个应用程序定制每个着色器。
开发人员预计此变量将成为用户可控制的设置。因此,将其声明为uniform是为即将推出的功能做准备。
如果我是开发人员,并且以上情况都不适用,则我会将其声明为“const”,因为这可以提高性能,而且我不必从我的代码中设置uniform。