Opengl GLSL着色器中的常量浮点值-是否有使用统一的理由?
我正在查看一个使用着色器的OpenGL应用程序的源代码。一个特定着色器如下所示:Opengl GLSL着色器中的常量浮点值-是否有使用统一的理由?,opengl,glsl,constants,shader,Opengl,Glsl,Constants,Shader,我正在查看一个使用着色器的OpenGL应用程序的源代码。一个特定着色器如下所示: uniform float someConstantValue; void main() { // Use someConstantValue } 统一从代码中设置一次,在整个应用程序运行时不会更改 在什么情况下,我希望将someConstantValue声明为统一的,而不是常量浮点 编辑: 只是澄清一下,常量值是一个物理常量。我可以想到两个原因: 开发人员在多个应用程序中重用着色器库。因此,开发人员没有
uniform float someConstantValue;
void main()
{
// Use someConstantValue
}
统一从代码中设置一次,在整个应用程序运行时不会更改
在什么情况下,我希望将someConstantValue
声明为统一的
,而不是常量浮点
编辑:
只是澄清一下,常量值是一个物理常量。我可以想到两个原因:
如果我是开发人员,并且上述任何一项都不适用,那么我会将其声明为“const”,因为它可以提供性能优势,而且我不必从代码中设置统一。首先,使用统一或常量之间的性能差异可能可以忽略不计。第二,仅仅因为一个值在本质上总是恒定的,并不意味着你总是希望它在你的程序中是恒定的。程序员通常会调整物理值以产生最佳效果,即使这与实际情况不符。例如,在某些类型的游戏中,重力引起的加速度通常会增加,以使游戏节奏更快 如果您不想在代码中设置统一,可以在GLSL中提供默认值:
uniform float someConstantValue = 12.5;
这就是说,没有理由不将const用于pi之类的东西,因为修改它几乎没有什么价值
uniform float myfloat;
...
for (float i = 0.0; i < myfloat; i++)
错误:循环索引无法与非常量表达式进行比较
如果我使用:
uniform float myfloat;
...
for (float i = 0.0; i < myfloat; i++)
为什么? 当GLSL(以及HLSL)被编译成GPU汇编指令时,循环将以非常详细的方式展开(但使用跳转等优化)。这意味着
myfloat
值在编译时用于展开循环;如果该值是一个统一的(即可以更改每个渲染调用),则该循环在运行时之前无法展开(GPU不会进行这种编译,至少在WebGL中不会)
这些情况非常罕见,在计算着色器(以及一些骨骼动画系统)中出现的次数最多。现在,您可以期望现代OpenGL和D3D对统一值(在一次渲染调用期间未更改的任何值)执行即时编译。例如,在启动呈现调用时,检查布尔统一变量的if语句将被编译掉—GPU上不会执行任何运行时检查。有关更多信息,请参阅。这是对问题的相反回答-OP想知道为什么要使用统一而不是常量,而不是相反。这在OpenGLES/WebGL中并不罕见“使用统一或常量之间的性能差异可能可以忽略不计”猜测起来并不好。声明一个常量值允许GLSL编译器执行否则无法执行的优化。但令人遗憾的是,GLSL编译器往往有bug,并且以不可预测的方式运行。所以一个笼统的答案是不可能的。我在使用常量数组和非常量数组(取决于它们的长度)时遇到了严重的性能差异,即使它们的值永远不会被修改。我假设这是一个编译器错误。虽然之前的评论在当时可能是准确的,但现在可以预期这种即时编译。均匀值可以像常量一样进行优化。更多信息请参见。所以,从理论上讲,警察可能比制服更出色?但是统一在所有顶点着色器调用中共享,但常量仅在一个调用中初始化/共享?Re“并且我不必从代码中设置统一”。如前所述,始终可以在着色器中设置uniform
的默认(初始)值。