20

我正在查看使用着色器的 OpenGL 应用程序的源代码。一个特定的着色器如下所示:

uniform float someConstantValue;
void main()
{
    // Use someConstantValue
}

统一从代码中设置一次,并且在整个应用程序运行时永远不会更改。

在什么情况下我想声明someConstantValue为 auniform而不是 as const float

编辑: 澄清一下,常数值是一个物理常数。

4

3 回答 3

26

巨大的原因

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

如果我使用

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值在编译时用于展开循环;如果该值是 a uniform(即可以更改每个渲染调用),则该循环在运行时才能展开(并且 GPU 不会进行这种 JustInTime 编译,至少在 WebGL 中不会)。

于 2014-05-11T17:01:24.467 回答
12

首先,使用制服或常数之间的性能差异可能可以忽略不计。其次,仅仅因为一个值在本质上总是恒定的,并不意味着你总是希望它在你的程序中是恒定的。程序员经常会调整物理值以产生最好看的结果,即使这与现实不符。例如,在某些类型的游戏中,由于重力的加速度通常会增加,以使其节奏更快。

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

uniform float someConstantValue = 12.5;

也就是说,没有理由不将 const 用于 pi 之类的东西,因为修改它的价值不大......

于 2013-07-04T22:04:20.173 回答
2

我可以想到两个原因:

  1. 开发人员在多个应用程序中重用了一个着色器库。因此,开发人员没有为每个应用程序定制每个着色器,而是试图保持它们的通用性。

  2. 开发人员预计此变量稍后将成为用户控制的设置。因此,将其声明为制服是为即将推出的功能做准备。

如果我是开发人员并且以上都不适用,那么我会将其声明为“const”,因为它可以带来性能优势,并且我不必从我的代码中设置统一。

于 2013-07-01T10:50:54.030 回答