GLSL着色器中的常量浮点值 - 使用制服的任何理由?

ksh*_*har 13 opengl shader constants glsl

我正在查看使用着色器的OpenGL应用程序的来源.一个特殊的着色器看起来像这样:

uniform float someConstantValue;
void main()
{
    // Use someConstantValue
}
Run Code Online (Sandbox Code Playgroud)

统一是从代码设置一次,并且在整个应用程序运行时都不会更改.

在什么情况下我想宣布someConstantValue为a uniform而不是const float

编辑: 只是为了澄清,常数值是物理常数.

Adr*_*ley 20

巨大的原因:

错误:循环索引无法与非常量表达式进行比较.

如果我使用:

uniform float myfloat;
...
for (float i = 0.0; i < myfloat; i++)
Run Code Online (Sandbox Code Playgroud)

我收到错误,因为myfloat不是constant expression.


但是这完全有效:

const float myfloat = 10.0;
...
for (float i = 0.0; i < myfloat; i++)
Run Code Online (Sandbox Code Playgroud)

为什么?

当GLSL(以及HLSL)编译为GPU汇编指令时,循环以非常详细(但使用跳转等优化)方式展开.这意味着myfloat在编译期间使用该值来展开循环; 如果该值是a uniform(即可以更改每个渲染调用),则该循环不能在运行时展开(并且GPU不执行那种JustInTime编译,至少不在WebGL中).

  • 这是回答与问题相反的问题 - OP想知道为什么你会使用uniform而不是const,而不是相反。 (3认同)
  • 这些情况非常罕见,并且在计算着色器(以及一些骨架动画系统)中出现的次数最多。 (2认同)
  • 这在OpenGLES/WebGL中并不罕见 (2认同)

fin*_*lia 9

首先,使用均匀或常数之间的性能差异可能是微不足道的.其次,仅仅因为一个值本质上总是不变的并不意味着你总是希望它在你的程序中保持不变.程序员通常会调整物理值以产生最佳效果,即使这与现实不符.例如,由于重力引起的加速度通常在某些类型的游戏中增加,以使它们更快节奏.

如果您不想在代码中设置制服,可以在GLSL中提供默认值:

uniform float someConstantValue = 12.5;
Run Code Online (Sandbox Code Playgroud)

也就是说,没有理由不将const用于像pi这样的东西,在那里修改它几乎没有价值....

  • "使用统一或常数之间的性能差异**可能**可忽略不计"猜测不好.声明一个常量值允许GLSL编译器执行其他方式无法实现的优化.但令人遗憾的是,GLSL编译器往往会出现错误并以不可预测的方式运行.所以一般的答案真的不可能.我在使用const和非const数组(取决于它们的长度)之间遇到了严重的性能差异,即使它们的值永远不会被修改.我认为这是一个编译器错误. (3认同)
  • 尽管之前的评论在当时可能是准确的,但现在可以预期这种即时编译。可以像常量一样优化统一值。有关详细信息,请参阅 [此](https://www.khronos.org/opengl/wiki/Core_Language_(GLSL)#Dynamically_uniform_expression)。 (3认同)