2013-11-26 15 views
9

Tôi đang làm việc trên một chương trình WebGL thực hiện ánh xạ bóng. Sau khi tính toán các giá trị độ sâu ở từng đoạn, tôi có một câu lệnh if ở cuối để tính toán ánh sáng dựa trên việc liệu đoạn đó có nằm trong bóng hay không.Trình đổ bóng đoạn WebGL không phân nhánh chính xác trên if statement

gl_FragColor = vec4(calcLighting(light0, eye_dir, eye_dir_norm, normal), 1); 
if (light_tex_coord.z - depth <= 0.0) { 
    gl_FragColor += vec4 
     (calcLighting(light1, eye_dir, eye_dir_norm, normal) 
     , 0.0 
    ); 
} 

Shadows not being correctly computed, branch never taken

nơi depth là chiều sâu của bản đồ bóng và light_tex_coord là vị trí của mảnh trong không gian cảnh của light1. light1 là một điểm sáng xoay quanh mô hình, và light0 là một điểm ánh sáng tĩnh vị trí tại máy ảnh.

Vấn đề ở đây là nếu nhánh không bao giờ được thực hiện, vì vậy cảnh chỉ có light0 áp dụng cho nó. Tôi đã kiểm tra rằng depth, light_tex_coordcalculateLighting hoạt động chính xác.

Đây là điều lạ, tuy nhiên, thay thế ở trên với đoạn mã sau:

if (light_tex_coord.z - depth <= 0.0) { 
    gl_FragColor = vec4(0,1,0,1); 
} else { 
    gl_FragColor = vec4(1,0,0,1); 
} 

Shadowed fragments correctly computed and drawn as red and green

Nguyên nhân shadowed khu vực được rút ra một cách chính xác màu đỏ, và không bóng tối để được rút ra trong màu xanh lá cây. Tức là, nhánh được đánh giá đúng. Thay thế nó bằng này:

gl_FragColor = vec4(calcLighting(light0, eye_dir, eye_dir_norm, normal), 1); 
gl_FragColor += vec4 
    (calcLighting(light1, eye_dir, eye_dir_norm, normal) 
    , 0.0 
    ); 

Lighting computed without shadows

Nguyên nhân ánh sáng được tính toán một cách chính xác (sans bóng, mặc dù). Có vẻ như khi tôi gọi hàm calcLighting đắt tiền hơn trong câu lệnh if, nó thậm chí không bận tâm lấy nó.

Hơn nữa, tôi đã thử áp dụng ánh sáng theo nhiều cách, kể cả sử dụng chức năng clamp; luôn thực hiện việc thêm và sử dụng toán tử terinary để nhân số thứ hai gọi calcLighting bằng 1 hoặc 0 và sắp xếp câu lệnh if của tôi theo nhiều cách khác nhau. Không có gì có vẻ hiệu quả.

Có điều gì tôi thiếu về cách phân nhánh hoạt động trong webgl không?

+0

Bạn đã thử tích lũy màu thành biến 'vec4' riêng biệt và ** chỉ ** gán' gl_FragColor' giá trị của biến khác này một lần. Việc ghi vào 'gl_FragColor' nhiều lần trong một shader được hỗ trợ như đang đọc giá trị của nó (cần thiết để thực hiện' + = ') nhưng tất cả các tài khoản vấn đề này dường như liên quan đến một hoặc cả hai hành động này cho dòng điều khiển của bạn. –

+0

Tôi đã thử thay thế tất cả các trường hợp 'gl_FragColor' trong các đoạn mã trên bằng một bộ tích lũy' vec4 acc; '. Tôi chỉ được chỉ định ở cuối trình đổ bóng với 'gl_FragColor = acc;' Không thay đổi trong bất kỳ trường hợp nào ở trên. – Cookyt

+0

Bạn có thể cung cấp toàn bộ mã fs không? Ngoài ra, nó sẽ tạo ra sự khác biệt nếu bạn thay đổi mã thành 'gl_FragColor + = vec4 (calcLight (..), 1.0)'? [note 1.0 alpha value] –

Trả lời

0

Có thể ngữ cảnh WebGl không hỗ trợ độ sâu. Sau đó, các biểu thức sử dụng nó sẽ bị bỏ qua.

Bạn có thể kiểm tra điều này với getContextAttributes()

+0

Trong mã javascript của tôi, tôi kiểm tra phần mở rộng độ sâu, và nếu nó không tồn tại, sau đó tôi ghi các giá trị độ sâu vào bộ đệm màu. Trong mọi trường hợp, các trình duyệt mà tôi đã thử nghiệm này hỗ trợ phần mở rộng độ sâu. – Cookyt

0

Thay vì các chi nhánh, có bạn xem một cái gì đó thực sự triệt để như thế này:

gl_FragColor += vec4 (
    calcLighting(light1, eye_dir, eye_dir_norm, normal) 
    , 0.0 
    ) * abs (min (sign (light_tex_coord.z - depth), 0.0)); 

Nó không phải là giải pháp đẹp nhất trên thế giới, nhưng nó chỉ có thể giúp bạn hiểu thêm về những gì bạn đang tìm kiếm. Về cơ bản nó mất light_tex_coord.z - depth <= 0.0 biểu thức điều kiện của bạn và làm cho nó thành một đẹp floating-point 0.0 hoặc 1.0 rằng bạn có thể nhân ánh sáng bằng cách hoặc là giữ hoặc loại bỏ kết quả chi nhánh. Loại cách đổ bóng sử dụng để hoạt động trước khi điều khiển luồng động được giới thiệu.

+0

Đó là một ý tưởng gọn gàng, nhưng tiếc là nó dường như không có tác dụng gì khi tôi sử dụng nó. – Cookyt

0

Chủ đề được 2 tuổi nhưng đây là 2 xu của tôi:

Tôi đã có một vấn đề tương tự và tìm thấy một trang trên Internet với một cuộc thảo luận có chứa các câu sau:

[... ] (trừ khi bạn làm những thứ điên rồ như hình ảnh viết bên trong các khối có điều kiện). [...]

Vì vậy, tôi đã cố gắng để đưa các màu điểm ảnh trong một biến tạm thời

vec4 col; 

địa phương để main(), trong "nếu" phát biểu tôi sửa đổi chỉ col, và tôi đặt màu pixel chỉ ở cuối cùng:

gl_FragColor = col; 

Điều này giải quyết được sự cố của tôi. Tất nhiên nó có thể yêu cầu lập trình bổ sung gây phiền nhiễu để cho dòng chảy đạt đến dòng cuối cùng trong mọi tình huống.

Các vấn đề liên quan