我应该在 GLSL 中使用条件分支来避免可能的纹理查找吗?

Cra*_*nog 7 opengl textures glsl

我有一系列关于 GLSL 中不统一的流量控制及其在现代桌面 GPU 上的性能成本的问题。首先,我想指出,我已经阅读了手册,但仍然没有找到答案。让我们开始吧。

  1. Alpha 检查和零乘优化。哪个片段着色器运行得更快?(两者的标题相同)

    in vec2 textureCoordIn; //interpolated texture coords from vertex shader
    out vec4 outputColor; //resulted color should be here
    uniform sampler2D alphaMask; // splat alpha mask for textures1-4;
    uniform sampler2D mainTexture1;
    uniform sampler2D mainTexture2;
    uniform sampler2D mainTexture3;
    uniform sampler2D mainTexture4;
    
    void main(){
        vec4 maskValues = texture(alphaMask,textureCoordIn);
        if (maskValues.r>0){
            outputColor += maskValues.r * texture(mainTexture1,textureCoordIn);
        }
        if (maskValues.g>0){
            outputColor += maskValues.g * texture(mainTexture2,textureCoordIn);
        }
        if (maskValues.b>0){
            outputColor += maskValues.b * texture(mainTexture3,textureCoordIn);
        }
        if (maskValues.w>0){
            outputColor += maskValues.w * texture(mainTexture4,textureCoordIn);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    或者

    void main(){
        vec4 maskValues = texture(alphaMask,textureCoordIn);
        outputColor += maskValues.r * texture(mainTexture1,textureCoordIn);
        outputColor += maskValues.g * texture(mainTexture2,textureCoordIn);
        outputColor += maskValues.b * texture(mainTexture3,textureCoordIn);
        outputColor += maskValues.w * texture(mainTexture4,textureCoordIn);
    }
    
    Run Code Online (Sandbox Code Playgroud)

    假设 maskValues 在 50% 的情况下可以为零。哪种着色器执行速度更快?同样有趣的是,如果 glsl 具有针对零乘法的内置优化。有人知道吗?

  2. 纹理数组可能存在错误的索引优化。避免未定义的行为?假设我们有纹理数组(sampler2DArray)。每个顶点都有 ivec4 属性,该属性包含该纹理数组的 4 个纹理索引。在片段着色器中,我们需要返回该索引的纹理颜色总和。仙女简单。但是,如果我们想处理索引可以指向“空”纹理的情况,我们应该做什么。在初始化步骤中,我们可以将此索引(顶点属性)设置为“-1”,这意味着 vec4(0,0,0,0) 颜色。处理它的最佳(也是正确的!)方法是什么?

    in vec2 textureCoordIn; //interpolated texture coords from vertex shader
    out vec4 outputColor; //resulted color should be here
    uniform sampler2DArray globalTextureArray;
    flat in ivec4 textureIndexes;
    
    void main(){
        if (textureIndexes.x > -1){
            outputColor += texture(globalTextureArray, vec3(textureCoordIn,textureIndexes.x));
        }
        if (textureIndexes.y > -1){
            outputColor += texture(globalTextureArray, vec3(textureCoordIn,textureIndexes.y));
        }
        if (textureIndexes.z > -1){
            outputColor += texture(globalTextureArray, vec3(textureCoordIn,textureIndexes.z));
        }
        if (textureIndexes.w > -1){
            outputColor += texture(globalTextureArray, vec3(textureCoordIn,textureIndexes.w));
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    或者

    我们应该将“假”(透明黑色)纹理放入 globalTextureArray 中,并使用它们的索引来处理这种情况。那么哪个更快 - if-else fork 或 4x 纹理查找?