天天看點

openGL深度沖突z-fighting

openGL系列文章目錄

文章目錄

  • ​​openGL系列文章目錄​​
  • ​​前言​​
  • ​​一、為什麼會産生z-fighting​​
  • ​​二、防止深度沖突​​
  • ​​1.第一種方法​​
  • ​​2.第二種方法​​
  • ​​3.第三種方法​​
  • ​​參考​​

前言

針對z-fighting從問題的描述,到為什麼會産生z-fighting現象,在繼而從投影矩陣的的角度來解釋這個問題的發生以及解決,最後稍微介紹一下深度值的非線性與線性的轉換所能應用的渲染場景。如有不妥歡迎留言,如果讀者覺得我的文章對自己有益,還望推薦給自己的朋友,感激不盡。

開啟深度測試後OpenGL就不會再去繪制模型被遮擋的部分,這樣實作的顯示畫面更為真實,但是由于深度緩沖區精度的限制,對于深度相差非常小的情況(例如在同一平面上進行兩次繪制),OpenGL就不能正确判定兩者的深度值,會導緻深度測試的結果不可預測,顯示出來的現象時交錯閃爍的前後兩個畫面,這種情況稱為z-fighting。

下面我将從這幾個方向進行闡述z-fighting的前世今生

1.z-fighting問題的描述

2.為什麼會産生z-fighting現象?

3.從透視投影矩陣的角度解釋以及如何避免

4.深度值的非線性與線性的轉化

一、為什麼會産生z-fighting

z-fighting問題的描述

首先來講一下,我們在進行三維渲染物體的時候,一般都是采用透視投影矩陣這樣會産生近大遠小的效果,很符合現實中人眼觀看世界的情況。但是渲染中經常會遇到場景中離視點較遠的物體會有閃爍的現象,而場景中離視點比較近的地方反而很少會長生物體閃爍的現象。

這是為什麼那?

而如果我們換用了正交投影矩陣後,閃爍的問題會極大的解決,這又是為什麼那?

為什麼會産生z-fighting現象?

第一點原因

場景中渲染多個三維物體的時候,幾個三維物體的擺放位置有點接近,導緻在深度緩沖測試的時候,會産生精度的誤差,然後會導緻幾個物體之間的片段值有的時候a通過,有的時候b通過,導緻交替顯示這幾個物體的顔色值,然後那就會産生閃爍的現象。

第二點原因

采用透視投影矩陣渲染的場景,其深度緩沖區存儲的深度值,ndc空間中的深度值。而ndc空間的深度值是經由透視空間轉換過來的,ndc空間的深度值與透視空間的深度值轉換并非是線性的,而是非線性。大家都知到,透視空間轉換到ndc空間會有一步透視除法,是處以z值。這樣就會導緻,離視點越近的物體的片段深度值是越精确的,離視點距離約遠的物體的片段的深度值是約不精确的。這樣就會導緻z-fighting問題。

而采用正交透視矩陣渲染場景,其變換是線性的,為什麼,因為其透視空間轉換為ndc空間的時候采用的透視除法是處以1,是以其片段距離視點的深度值是線性的,這樣除非你把兩個物體設定的位置非常接近,否則是産生不了z-fighting這種現象的。

那麼為什麼透視投影矩陣渲染場景的時候,在透視空間轉換到ndc空間時,透視除法會除以z值那?下面筆者從透視投影矩陣的數學推導層面來回到這個問題。

從透視投影矩陣計算的角度解釋以及如何避免

三維空間的物體在經曆的圖元裝配以後,會經曆剪裁與淘汰這兩步操作。其中在剪裁中經曆坐标系的轉換的。

坐标系的轉換如下所示:

模型坐标系–>世界坐标系—>相機坐标系—>投影坐标系—>标準裝置化空間–>視口變換—>光栅化階段。

在其投影坐标系轉換到标準裝置化空間的時,需要将xyz坐标轉換為-1到1之間,也可以說标準裝置化空間(NDC)是一個立方體空間。那麼該怎麼達到這樣的操作那?答案是借助于矩陣,矩陣的一個幾何意義就是将一個物體從一個坐标系轉換到另外一個坐标系。那麼筆者下面将去介紹這個透視投影矩陣是長的什麼樣子。

openGL深度沖突z-fighting
openGL深度沖突z-fighting

注意到藍色線框裡面.有花屏現象

openGL深度沖突z-fighting

這張圖檔就沒有深度沖突

二、防止深度沖突

1.第一種方法

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

2.第二種方法

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

3.第三種方法

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

參考