2

我在片段着色器中有以下代码:

precision lowp float;

varying vec2 v_texCoord;
uniform sampler2D s_texture;

uniform bool color_tint;
uniform float color_tint_amount;
uniform vec4 color_tint_color;

void main(){
    float gradDistance;
    vec4 texColor, gradColor;
    texColor = texture2D(s_texture, v_texCoord);
    if (color_tint){
        gradColor = color_tint_color;
        gradColor.a = texColor.a;
        texColor = gradColor * color_tint_amount + texColor * (1.0 - color_tint_amount);
    }
    gl_FragColor = texColor;
}

代码运行良好,但有趣的是,即使color_tint我传入的都是错误的,上面的代码仍然会严重拖累性能。比较时:

void main(){
    float gradDistance;
    vec4 texColor, gradColor;
    texColor = texture2D(s_texture, v_texCoord);
    if (false){
        gradColor = color_tint_color;
        gradColor.a = texColor.a;
        texColor = gradColor * color_tint_amount + texColor * (1.0 - color_tint_amount);
    }
    gl_FragColor = texColor;
}

Which the later one can achieve 40+ fps while the first one is about 18 fps. I double checked and all color_tint passed in the first one are false so the block should never executed.

BTW, I am programming the above in Android 2.2 using GLES20.

Could any expert know what's wrong with the shader?

4

2 回答 2

6

如果可能,片段着色器上的分支非常慢,请避免使用它们。使用 color_tint_amount 0 表示无色调。预乘 color_tint_color 并保存每个像素的乘法。使 color_tint_amount = 1.0 - color_tint_amount。(所以现在 1.0 意味着没有 gradColor)这些着色器每秒运行数百万次,您必须尽可能保存每个循环。

于 2011-05-04T05:47:46.880 回答
6

我不是片段着色器方面的专家,但我认为第二个会更快,因为整个 if 语句可以在编译时删除,因为它永远不会是真的。在第一个中,直到运行时才知道它color_tint总是错误的,因此每次都需要检查并分支。分支可能很昂贵,尤其是在通常为可预测的串行编程而设计的图形硬件上。

我建议您尝试将其重写为无分支 - 达伦的回答在这个方向上有一些很好的建议。

于 2011-05-04T06:17:33.513 回答