Вартість прив'язки шейдерів може бути нетривіальною, але це не буде вашим вузьким місцем, якщо ви не будете надавати тисячі предметів, не купуючи всі об'єкти, які використовують ті самі шейдери.
Хоча я не впевнений, чи це стосується мобільних пристроїв, але графічні процесори не є дуже повільними з гілками, якщо стан між постійною і рівномірною. Обидва є дійсними, обидва використовувалися в минулому, і надалі використовуватимуться в майбутньому, вибирайте той, який, на вашу думку, буде чистішим у вашому випадку.
Крім того, є ще кілька способів досягти цього: "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 досить хороший, щоб оптимізувати будь-які додаткові накладні витрати порівняно з іншими способами цього. Я не проводив жодних тестів з цього приводу, але я люблю це робити.