我在片段着色器中有以下代码:
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;
}
后者可以达到40+ fps,而第一个可以达到18 fps。我仔细检查过,第一个传递的所有color_tint
都是假的,所以块永远不会被执行。
BTW,我正在使用GLES20在Android 2.2中编写上述内容。
任何专家都能知道着色器有什么问题吗?
答案 0 :(得分:6)
片段着色器上的分支非常慢,如果可能的话,避免它们。使用color_tint_amount为0表示无色调。预乘color_tint_color并保存每个像素的乘法。 make color_tint_amount = 1.0 - color_tint_amount。 (所以现在1.0意味着没有gradColor)这些着色器每秒运行数百万次,你必须保存每个周期。
答案 1 :(得分:6)
我不是片段着色器的专家,但我认为第二个会更快,因为整个if语句可以在编译时删除,因为它永远不会是真的。在第一个中,它不能告诉color_tint
在运行时始终为false,因此每次都需要检查并分支。分支可能很昂贵,特别是在通常用于可预测的串行编程的图形硬件上。
我建议你尝试将其重写为无分支 - 达伦的回答在这方面有一些很好的建议。