Biaya mengikat shader mungkin tidak sepele, tetapi itu tidak akan menjadi hambatan Anda kecuali Anda merender ribuan item tanpa menumpuk semua objek yang menggunakan shader yang sama.
Meskipun saya tidak yakin apakah ini berlaku untuk perangkat seluler, tetapi GPU tidak terlalu lambat dengan cabang jika kondisinya antara konstan dan seragam. Keduanya valid, keduanya telah digunakan di masa lalu dan akan terus digunakan di masa depan, pilih mana yang menurut Anda akan lebih bersih dalam kasus Anda.
Selain itu, ada beberapa cara lain untuk mencapai hal ini: "Uber-shaders" dan sedikit tipu daya dengan cara program OpenGL shader dihubungkan.
"Uber-shaders" pada dasarnya adalah pilihan pertama, minus percabangan, tetapi Anda akan memiliki beberapa shader. Alih-alih menggunakan if
pernyataan, Anda menggunakan preprocessor - #define
, #ifdef
, #else
, #endif
, dan mengkompilasi versi yang berbeda, termasuk yang tepat #define
karena apa yang Anda butuhkan.
vec4 color;
#ifdef PER_VERTEX_COLOR
color = in_color;
#else
color = obj_color;
#endif
Anda juga dapat memecah shader menjadi fungsi terpisah. Memiliki satu shader yang mendefinisikan prototipe untuk semua fungsi dan memanggilnya, tautkan sekelompok shader tambahan yang menyertakan implementasi yang tepat. Saya telah menggunakan trik ini untuk pemetaan bayangan, untuk memudahkan menukar cara penyaringan dilakukan pada semua objek tanpa harus memodifikasi semua shader.
//ins, outs, uniforms
float getShadowCoefficient();
void main()
{
//shading stuff goes here
gl_FragColor = color * getShadowCoefficient();
}
Lalu, saya bisa memiliki beberapa file shader lain yang menentukan getShadowCoefficient()
, seragam yang diperlukan, dan tidak ada yang lain. Misalnya, shadow_none.glsl
berisi:
float getShadowCoefficient()
{
return 1;
}
Dan shadow_simple.glsl
berisi (disederhanakan dari shader saya yang mengimplementasikan 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;
}
Dan Anda bisa memilih apakah Anda ingin shading atau tidak dengan menghubungkan shadow_*
shader yang berbeda . Solusi ini mungkin memiliki overhead yang lebih banyak, tetapi saya ingin berpikir bahwa kompiler GLSL cukup baik untuk mengoptimalkan semua overhead tambahan dibandingkan dengan cara lain untuk melakukan ini. Saya belum menjalankan tes apa pun tentang ini, tetapi itulah cara saya suka melakukannya.