Die Kosten für das Binden von Shadern sind möglicherweise nicht trivial, aber es wird kein Engpass sein, es sei denn, Sie rendern Tausende von Elementen, ohne alle Objekte zu stapeln, die dieselben Shader verwenden.
Ich bin mir zwar nicht sicher, ob dies für mobile Geräte gilt, aber GPUs sind mit Zweigen nicht besonders langsam, wenn der Zustand zwischen einer Konstanten und einer Uniform liegt. Beide sind gültig, beide wurden in der Vergangenheit verwendet und werden auch in Zukunft verwendet. Wählen Sie die aus, die Ihrer Meinung nach in Ihrem Fall sauberer ist.
Darüber hinaus gibt es einige andere Möglichkeiten, um dies zu erreichen: "Uber-Shader" und ein wenig Trick bei der Verknüpfung von OpenGL-Shader-Programmen.
"Uber-Shader" sind im Wesentlichen die erste Wahl, abzüglich der Verzweigung, aber Sie haben mehrere Shader. Anstelle der Verwendung von if
Aussagen, verwenden Sie die Prä - Prozessor - #define
, #ifdef
, #else
, #endif
, und verschiedene Versionen kompilieren, einschließlich der richtigen #define
s für das, was Sie brauchen.
vec4 color;
#ifdef PER_VERTEX_COLOR
color = in_color;
#else
color = obj_color;
#endif
Sie können den Shader auch in separate Funktionen aufteilen. Lassen Sie einen Shader, der Prototypen für alle Funktionen definiert und aufruft, eine Reihe zusätzlicher Shader verknüpfen, die die richtigen Implementierungen enthalten. Ich habe diesen Trick für die Schattenzuordnung verwendet, um das Austauschen der Filterung für alle Objekte zu vereinfachen, ohne alle Shader ändern zu müssen.
//ins, outs, uniforms
float getShadowCoefficient();
void main()
{
//shading stuff goes here
gl_FragColor = color * getShadowCoefficient();
}
Dann könnte ich mehrere andere Shader-Dateien haben, die definieren getShadowCoefficient()
, die notwendigen Uniformen und sonst nichts. shadow_none.glsl
Enthält zum Beispiel :
float getShadowCoefficient()
{
return 1;
}
Und shadow_simple.glsl
enthält (vereinfacht von meinem Shader, der CSMs implementiert):
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;
}
Und Sie können einfach auswählen, ob Sie eine Schattierung wünschen oder nicht, indem Sie einen anderen shadow_*
Shader verknüpfen . Diese Lösung hat zwar mehr Overhead, aber ich würde gerne glauben, dass der GLSL-Compiler gut genug ist, um zusätzlichen Overhead im Vergleich zu anderen Methoden zu optimieren. Ich habe noch keine Tests durchgeführt, aber so mache ich das gerne.