Opengl GLSL着色器中的常量浮点值-是否有使用统一的理由?

Opengl GLSL着色器中的常量浮点值-是否有使用统一的理由?,opengl,glsl,constants,shader,Opengl,Glsl,Constants,Shader,我正在查看一个使用着色器的OpenGL应用程序的源代码。一个特定着色器如下所示: uniform float someConstantValue; void main() { // Use someConstantValue } 统一从代码中设置一次,在整个应用程序运行时不会更改 在什么情况下,我希望将someConstantValue声明为统一的,而不是常量浮点 编辑: 只是澄清一下,常量值是一个物理常量。我可以想到两个原因: 开发人员在多个应用程序中重用着色器库。因此,开发人员没有

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

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
    的默认(初始)值。