Chi phí cho các shader ràng buộc có thể không phải là nhỏ, nhưng nó sẽ không phải là nút cổ chai của bạn trừ khi bạn kết xuất hàng ngàn mục mà không gộp tất cả các đối tượng sử dụng cùng các shader.
Mặc dù tôi không chắc điều này có áp dụng cho thiết bị di động hay không, nhưng GPU không bị chậm một cách khủng khiếp với các nhánh nếu điều kiện nằm giữa hằng số và đồng phục. Cả hai đều hợp lệ, cả hai đã được sử dụng trong quá khứ và sẽ tiếp tục được sử dụng trong tương lai, chọn bất kỳ cái nào bạn nghĩ sẽ sạch hơn trong trường hợp của bạn.
Ngoài ra, có một vài cách khác để thực hiện điều này: "Trình tạo bóng Uber" và một mẹo nhỏ với cách các chương trình trình tạo bóng OpenGL được liên kết.
"Uber-shader" về cơ bản là lựa chọn đầu tiên, trừ khi phân nhánh, nhưng bạn sẽ có nhiều shader. Thay vì sử dụng if
các báo cáo, bạn sử dụng tiền xử lý - #define
, #ifdef
, #else
, #endif
, và biên dịch các phiên bản khác nhau, trong đó có thích hợp #define
s cho những gì bạn cần.
vec4 color;
#ifdef PER_VERTEX_COLOR
color = in_color;
#else
color = obj_color;
#endif
Bạn cũng có thể chia shader thành các chức năng riêng biệt. Có một shader xác định nguyên mẫu cho tất cả các hàm và gọi chúng, liên kết một loạt các shader bổ sung bao gồm các cài đặt thích hợp. Tôi đã sử dụng thủ thuật này để lập bản đồ bóng, để giúp dễ dàng trao đổi cách lọc được thực hiện trên tất cả các đối tượng mà không phải sửa đổi tất cả các trình đổ bóng.
//ins, outs, uniforms
float getShadowCoefficient();
void main()
{
//shading stuff goes here
gl_FragColor = color * getShadowCoefficient();
}
Sau đó, tôi có thể có nhiều tệp shader khác xác định getShadowCoefficient()
, đồng phục cần thiết và không có gì khác. Ví dụ shadow_none.glsl
: chứa:
float getShadowCoefficient()
{
return 1;
}
Và shadow_simple.glsl
chứa (đơn giản hóa từ trình đổ bóng của tôi thực hiện các 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;
}
Và bạn có thể chỉ cần chọn xem bạn có muốn tô bóng hay không bằng cách liên kết một shadow_*
shader khác . Giải pháp này rất có thể có nhiều chi phí hơn, nhưng tôi muốn nghĩ rằng trình biên dịch GLSL đủ tốt để tối ưu hóa mọi chi phí phụ so với các cách khác để làm điều này. Tôi chưa thực hiện bất kỳ thử nghiệm nào về vấn đề này, nhưng đó là cách tôi muốn làm.