2013-11-26 65 views
9

我正在研究一個實現陰影映射的WebGL程序。在計算每個片段的深度值後,我在最後有一個if語句,它根據片段是否在陰影中計算光照。WebGL片段着色器不能正確分支if語句

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

其中depth是影子圖的深度和light_tex_coord是片段的在light1場景空間中的位置。 light1是圍繞模型旋轉的點光源,light0是靜態定位在相機上的點光源。

這裏的問題是if分支從不被採用,所以場景只有light0應用於它。我已檢查depth,light_tex_coordcalculateLighting是否正常工作。

下面是奇怪的事情,不過,用下面的代碼替換上面:

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

原因陰影區域以紅色繪製正確,並且未投影在綠色繪製。也就是說,分支正確評估。與此替換它:

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

導致照明被正確地計算(沒有陰影,雖然)。看起來,當我在if語句中調用更加昂貴的calcLighting函數時,它甚至不會考慮採用它。

此外,我已經嘗試在幾種方式應用照明,包括使用clamp函數;總是添加並使用terinary運算符將第二個calcLighting調用乘以1或0,並以不同方式排列我的if語句。似乎沒有任何工作。

有什麼我錯過了關於如何分支在webgl中工作?

+0

您是否嘗試將顏色累加到單獨的'vec4'變量,並且**只將**這個其他變量的值分配給一次'gl_FragColor'。在着色器中多次寫入'gl_FragColor'應該支持讀取它的值(這是實現'+ ='所必需的),但是通過所有帳戶,這個問題似乎與這些動作中的一個或兩個有關給你的控制流量。 –

+0

我嘗試用累加器'vec4 acc;'替換上述代碼片段中的所有'gl_FragColor'實例。我只在具有'gl_FragColor = acc;的着色器末尾進行分配;'在上述任何情況下都沒有變化。 – Cookyt

+0

你能提供整個FS代碼嗎? 另外,如果將代碼更改爲'gl_FragColor + = vec4(calcLight(..),1.0)',它會有什麼區別嗎? [注意1.0 alpha值] –

回答

0

也許WebGl上下文不支持深度。然後使用它的表達式將被忽略。

你可以用getContextAttributes()

+0

在我的JavaScript代碼中,我檢查深度擴展,如果它不存在,那麼我將深度值寫入顏色緩衝區。無論如何,我測試過的瀏覽器都支持深度擴展。 – Cookyt

0

而是分支的檢查這一點,你有沒有考慮真正激進的是這樣的:

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

它不是世界上最漂亮的解決方案,但它只是可能會爲您尋找更多的東西。它基本上需要你light_tex_coord.z - depth <= 0.0條件表達式,並使其成爲一個不錯的浮點0.01.0,您可以通過要麼保持丟棄分支結果乘以照明。種類的着色器使用在引入動態流控制之前工作。

+0

這是一個很好的想法,但不幸的是,當我使用它時似乎沒有任何效果。 – Cookyt

0

主題是2歲,但這裏是我的2美分:

我也有類似的問題,發現了一個網頁在互聯網上,用含有如下句子的討論:

[... ](除非你在像條件 塊內寫入圖像等瘋狂的東西)。 [...]

所以我試圖把像素顏色在臨時變量

vec4 col; 

本地主(),在「if」語句我只修改山坳,我就定像素顏色只在最末端:

gl_FragColor = col; 

這解決了我的問題。當然,它可能需要煩人的額外編程來讓流量在任何情況下都能達到最後一條線。