如何解決深度衝突(Z-fighting),畫面閃爍的問題

參考:OpenGL教程:深度測試

深度衝突

一個很常見的視覺錯誤會在兩個平面或者三角形非常緊密地平行排列在一起時會發生,深度緩衝沒有足夠的精度來決定兩個形狀哪個在前面。結果就是這兩個形狀不斷地在切換前後順序,這會導致很奇怪的花紋。這個現象叫做深度衝突(Z-fighting),因爲它看起來像是這兩個形狀在爭奪(Fight)誰該處於頂端。在這裏插入圖片描述

防止深度衝突

第一個也是最重要的技巧是永遠不要把多個物體擺得太靠近,以至於它們的一些三角形會重疊。通過在兩個物體之間設置一個用戶無法注意到的偏移值,你可以完全避免這兩個物體之間的深度衝突。在箱子和地板的例子中,我們可以將箱子沿着正y軸稍微移動一點。箱子位置的這點微小改變將不太可能被注意到,但它能夠完全減少深度衝突的發生。然而,這需要對每個物體都手動調整,並且需要進行徹底的測試來保證場景中沒有物體會產生深度衝突。

第二個技巧是儘可能將近平面設置遠一些。在前面我們提到了精度在靠近近平面時是非常高的,所以如果我們將近平面遠離觀察者,我們將會對整個平截頭體有着更大的精度。然而,將近平面設置太遠將會導致近處的物體被裁剪掉,所以這通常需要實驗和微調來決定最適合你的場景的近平面距離。

另外一個很好的技巧是犧牲一些性能,使用更高精度的深度緩衝。大部分深度緩衝的精度都是24位的,但現在大部分的顯卡都支持32位的深度緩衝,這將會極大地提高精度。所以,犧牲掉一些性能,你就能獲得更高精度的深度測試,減少深度衝突。

我們上面討論的三個技術是最普遍也是很容易實現的抗深度衝突技術了。還有一些更復雜的技術,但它們依然不能完全消除深度衝突。深度衝突是一個常見的問題,但如果你組合使用了上面列舉出來的技術,你可能不會再需要處理深度衝突了。

其次在THREEjs中,當使用非默認的顏色緩衝區時,注意顏色緩衝區的深度紋理.format是否正確,另外.type是否有足夠高的精度。