我正在查看使用着色器的OpenGL应用程序的来源。一个特殊的着色器看起来像这样:
uniform float someConstantValue;
void main()
{
// Use someConstantValue
}
统一是从代码设置一次,并且在整个应用程序运行时都不会改变。
在什么情况下,我想将someConstantValue
声明为uniform
而不是const float
?
修改 只是为了澄清,常数值是物理常数。
答案 0 :(得分:18)
巨大的原因:
错误:循环索引无法与非常量表达式进行比较。
如果我使用:
uniform float myfloat;
...
for (float i = 0.0; i < myfloat; i++)
我收到错误,因为myfloat
不是constant expression
。
然而这完全有效:
const float myfloat = 10.0;
...
for (float i = 0.0; i < myfloat; i++)
<强>为什么吗
当GLSL(和HLSL)被编译为GPU汇编指令时,循环以非常详细(但使用跳转等优化)方式展开。这意味着在编译期间使用
myfloat
值来展开循环;如果该值是uniform
(即可以更改每个渲染调用),则该循环不能在运行时展开(并且GPU不执行那种JustInTime编译,至少不在WebGL中)。
答案 1 :(得分:9)
首先,使用均匀或常数之间的性能差异可能是微不足道的。其次,仅仅因为一个值本质上总是不变的并不意味着你总是希望它在你的程序中保持不变。程序员通常会调整物理值以产生最佳效果,即使这与现实不符。例如,在某些类型的游戏中,由于重力引起的加速度通常会增加,以使它们更快节奏。
如果您不想在代码中设置制服,可以在GLSL中提供默认值:
uniform float someConstantValue = 12.5;
那就是说,没有理由不将const用于像pi这样的东西,在修改它时没什么价值......
答案 2 :(得分:1)
我可以想到两个原因:
开发人员在多个应用程序中重用着色器库。因此,开发人员不是为每个应用程序自定义每个着色器,而是试图保持它们的通用性。
开发人员预计此变量稍后将成为用户控制的设置。所以宣布它是统一的是为即将到来的功能做准备。
如果我是开发人员并且以上都不适用,那么我会将其声明为“const”,因为它可以提供性能优势,而且我不必从我的代码中设置制服。