绑定着色器的成本可能不小,但是除非您要渲染数千个项目而不批处理使用相同着色器的所有对象,否则绑定着色器不会成为您的瓶颈。
尽管我不确定这是否适用于移动设备,但是如果条件介于常数和统一之间,GPU的分支运行速度不会太慢。两者都是有效的,都已在过去使用过,将来会继续使用,请选择您认为适合的情况中的任何一种。
此外,还有其他一些方法可以实现此目的:“ Uber着色器”和OpenGL着色器程序链接方式的一些技巧。
从本质上讲,“ Uber着色器”是减去分支的首选,但是您将拥有多个着色器。而不是使用的if
语句,你可以使用预处理器- ,#define
,#ifdef
,#else
,#endif
和编译不同的版本,包括正确的#define
是给你所需要的。
vec4 color;
#ifdef PER_VERTEX_COLOR
color = in_color;
#else
color = obj_color;
#endif
您也可以将着色器分解为单独的功能。有一个着色器定义所有功能的原型并调用它们,链接一堆包含适当实现的额外着色器。我已使用此技巧进行阴影映射,以轻松交换如何对所有对象进行过滤,而无需修改所有着色器。
//ins, outs, uniforms
float getShadowCoefficient();
void main()
{
//shading stuff goes here
gl_FragColor = color * getShadowCoefficient();
}
然后,我可以拥有多个其他的着色器文件getShadowCoefficient()
,这些文件定义了,必要的制服以及其他内容。例如,shadow_none.glsl
包含:
float getShadowCoefficient()
{
return 1;
}
并且shadow_simple.glsl
包含(从实现CSM的着色器中简化):
in vec4 eye_position;
uniform sampler2DShadow shad_tex;
uniform mat4 shad_mat;
float getShadowCoefficient()
{
vec4 shad_coord = shad_mat * eye_position;
return texture(shad_tex, shad_coord).x;
}
您可以通过链接不同的shadow_*
着色器来简单地选择是否要着色。该解决方案可能会产生更多开销,但是与其他方式相比,我想认为GLSL编译器足以优化任何额外开销。我没有对此进行任何测试,但这是我喜欢的方式。