我是否能够启动空白变量并在之后声明它们



我想做这样的事情:

vec4 text;
if (something){
  text = texture(backgroundTexture, pass_textureCoords);
}
if (somethingElse){
  text = texture(anotherTexture, pass_textureCoords);
}

这是有效的GLSL代码吗?如果不是,有合适的替代方案吗?

答案取决于somethingsomethingElse实际是什么。

  • 如果这是一个统一的控制流,这意味着所有着色器调用都执行相同的分支,那么这是完全有效的。

  • 如果它们是非统一表达式,那么就有一些限制:

    当纹理使用任何类型的mipmapping或各向异性过滤时,任何需要隐式导数的纹理函数都将检索未定义的结果。

综上所述:是的,这是完全有效的glsl代码,但非均匀控件流中的纹理有一些限制。有关这方面的更多详细信息,请点击此处。

附带说明:在代码示例中,您没有在之后声明变量。你只是在给它们赋值。

编辑(更多信息)

为了更详细地说明什么是均匀和非均匀控制流:着色器(通常)可以有两种类型的输入。像uniform vec3 myuniform;这样的统一变量和像in vec3 myvarying这样的变量。不同之处在于数据来自哪里以及在调用过程中如何更改:

  • 统一格式是从应用程序端设置的,并且(因此)在调用中是恒定的(其中调用简化意味着绘制命令)
  • 变化是从顶点输入(在顶点着色器中)读取的,或者是从以前的着色器阶段(例如在片段着色器中)传递和插值的

统一控制流现在意味着,相应if语句的条件仅依赖于统一。其他一切都是非均匀控制流。让我们看看这个片段着色器示例:

//Uniforms
uniform vec3 my_uniform;
uniform sampler2D my_sampler;
/Varyings
in vec2 tex_coord;
in vec2 ndc_coords;
void main()
{
    vec3 result = vec3(0,0,0);
    if (my_uniform.y > 0.5) //Uniform control flow
        result += texture(my_sampler, tex_coord).rgb;
    if (ndc_coords.y > 0.5) //Non-uniform control flow
        result += texture(my_sampler, tex_coord).rgb;
    float some_value = ndc_coords.y + my_uniform.y;
    if (some_value > 0.5) //Still non-uniform control flow
        result += texture(my_sampler, tex_coord).rgb;
}

在该着色器中,只有第一个纹理读取发生在统一控制流中(因为if条件仅取决于统一变量)。另外两个读取处于非均匀控制流中,因为if条件也取决于变化的(ndc_coords)。

最新更新