WebGL中深度碰撞方法總結

z-fighting問題是三維渲染中常見的問題,本文根據實際工做中遇到的一些場景,進行了系統的總結spa

一個實際工做中的問題

當兩個面離得太近就會發生深度碰撞問題,好比:code

遇到深度檢測問題,最重要的是先搞明白是哪兩個面離得太近致使的問題。好比上面這個問題,一直以來我都覺得是柱子的面跟底圖基礎底面的問題。因此嘗試了各類解決深度檢測的問題都沒起做用。blog

 

直到後面一次偶然的嘗試,開啓了CULL_FACE後,這個深度碰撞正常了。思考了好久纔想到原來它發生深度碰撞的緣由不是跟地圖底面,而是柱子的上頂面跟下頂面離得太近發生的碰撞。恍然大悟!get

這張圖的表現頗有欺騙性,底面是黑色的,而恰好碰撞部分也是一部分藍,一部分發暗,因此很讓人想固然的認爲是底圖跟柱子之間的問題。這個緣由是由於默認沒有面剔除,致使底面也被繪製了,而底面的法線方向與光線方向夾角很大,致使最後計算的顏色發暗。因此碰撞部分一部分明亮,一部分發暗。it

換個了底圖樣式,仍然是這種結果,能夠證實上述緣由。io

 

最終這個問題的解決方式是,開啓CULL_FACE,剔除背面三角形,同時在着色中爲頂點增長一點偏移class

let parameters = {
            [GL.DEPTH_TEST]: true,
            [GL.CULL_FACE]: true,
            [GL.CULL_FACE_MODE]: GL.FRONT
        };
// 計算cube該頂點的位置, cube的X座標範圍是-1~1,(rotatedPosition.x * coverage + 1.0) / 2.0座標範圍在0~1之間
  // cube的Z座標範圍是-1~1,(rotatedPosition.z * coverage - 1.0) / 2.0座標範圍在-1~0之間
  // cubeTopLeftPosition在cube局部座標系的(-1, 0, -1)位置
  vec4 vertexPosition = cubeTopLeftPosition + vec4(
    vec2(
      (rotatedPosition.x * coverage + 1.0) / 2.0 * useRadius,
      (rotatedPosition.z * coverage - 1.0) / 2.0 * useRadius
    ),
    1.0, 1.0
  );

深度檢測根本緣由

因爲z-buffer的精度並非線性相關的,而是在靠近near平面是精度很是大,可是靠近遠平面時精度很是低,所若是平面離着相機很是遠,那麼就極可能出現深度檢測問題。基礎

解決方法

1.      首先搞明白是哪兩個面發生的深度碰撞渲染

2.      數據層面永遠不要把兩個物體靠的太近,最好在用戶不太注意的地方稍微加一點偏移方法

3.      將near設置的大一些,這樣使得場景中的物體都在高精度範圍內,但這種方式也是須要調整,near設置的太大,會致使一些應當在視野範圍內的物體被裁切掉

4.      在着色器中適當增長一個小的偏移

5.      利用depthRange來調整深度緩衝範圍

6.      修改投影矩陣的第十位,增長一個小的偏移(http://note.youdao.com/noteshare?id=43a15cadb1afebb1b4ad24a4c159d1e0&sub=37ECF8DF031440D99B69D9CE60850F8A

相關文章
相關標籤/搜索