OpenGL 深度測試

2021-09-10 01:55:41 字數 2734 閱讀 4535

啟用深度測試

唯讀深度緩衝

深度測試函式

深度值精度

深度衝突

防止深度衝突

深度緩衝就像顏色緩衝(color buffer)(儲存所有的片段顏色:視覺輸出)一樣,在每個片段中儲存了資訊,並且(通常)和顏色緩衝有著一樣的寬度和高度。深度緩衝是由視窗系統自動建立的,它會以16、24或32位float的形式儲存它的深度值。在大部分的系統中,深度緩衝的精度都是24位的。

深度緩衝是在片段著色器執行之後(以及模板測試(stencil testing)執行之後,我們將在下一節中討論)在螢幕空間中執行的。螢幕空間座標與通過opengl的glviewport所定義的視口密切相關,並且可以直接使用glsl內建變數gl_fragcoord從片段著色器中直接訪問。gl_fragcoord的x和y分量代表了片段的螢幕空間座標(其中(0, 0)位於左下角)。gl_fragcoord中也包含了乙個z分量,它包含了片段真正的深度值。z值就是需要與深度緩衝內容所對比的那個值

現在大部分的gpu都提供乙個叫做提前深度測試(early depth testing)的硬體特性。提前深度測試允許深度測試在片段著色器之前執行。只要我們清楚乙個片段永遠不會是可見的(它在其他物體之後),我們就能提前丟棄這個片段。

片段著色器通常開銷都是很大的,所以我們應該盡可能避免執行它們。當使用提前深度測試時,片段著色器的乙個限制是你不能寫入片段的深度值。如果乙個片段著色器對它的深度值進行了寫入,提前深度測試是不可能的。opengl不能提前知道深度值。

當深度測試(depth testing)被啟用的時候,opengl會將乙個片段的的深度值與深度緩衝的內容進行對比。opengl會執行乙個深度測試,如果這個測試通過了的話,深度緩衝將會更新為新的深度值。如果深度測試失敗了,片段將會被丟棄。

在某些情況下你會需要對所有片段都執行深度測試並丟棄相應的片段,但不希望更新深度緩衝。基本上來說,你在使用乙個唯讀的(read-only)深度緩衝。opengl允許我們禁用深度緩衝的寫入,只需要設定它的深度掩碼(depth mask)設定為gl_false就可以了

gldepthmask(gl_false);
opengl允許我們修改深度測試中使用的比較運算子。這允許我們來控制opengl什麼時候該通過或丟棄乙個片段,什麼時候去更新深度緩衝。我們可以呼叫gldepthfunc函式來設定比較運算子(或者說深度函式(depth function)):

深度緩衝包含了乙個介於0.0和1.0之間的深度值,它將會與觀察者視角所看見的場景中所有物體的z值進行比較。觀察空間的z值可能是投影平截頭體的近平面(near)和遠平面(far)之間的任何值。我們需要一種方式來將這些觀察空間的z值變換到[0, 1]範圍之間,其中的一種方式就是將它們線性變換到[0, 1]範圍之間。下面這個(線性)方程將z值變換到了0.0到1.0之間的深度值:

然而,在實踐中是幾乎永遠不會使用這樣的線性深度緩衝(linear depth buffer)的z。要想有正確的投影性質,需要使用乙個非線性的深度方程,它是與 1/z 成正比的。它做的就是在z值很小的時候提供非常高的精度,而在z值很遠的時候提供更少的精度。花時間想想這個:我們真的需要對1000單位遠的深度值和只有1單位遠的充滿細節的物體使用相同的精度嗎?線性方程並不會考慮這一點。

深度緩衝中的值在螢幕空間中不是線性的

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

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

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

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

openGL 深度測試

opengl裡常出現深度測試,一直不清楚。今天就來弄清楚。1 什麼是深度?深度其實就是該象素點在3d世界中距離攝象機的距離 繪製座標 深度快取中儲存著每個象素點 繪製在螢幕上的 的深度值!深度值 z值 越大,則離攝像機越遠。深度值是存貯在深度快取裡面的,我們用深度快取的位數來衡量深度快取的精度。深度...

openGL 深度測試

opengl裡常出現深度測試,一直不清楚。今天就來弄清楚。1 什麼是深度?深度其實就是該象素點在3d世界中距離攝象機的距離 繪製座標 深度快取中儲存著每個象素點 繪製在螢幕上的 的深度值!深度值 z值 越大,則離攝像機越遠。深度值是存貯在深度快取裡面的,我們用深度快取的位數來衡量深度快取的精度。深度...

openGL 深度測試

opengl裡常出現深度測試,一直不清楚。今天就來弄清楚。1 什麼是深度?深度其實就是該象素點在3d世界中距離攝象機的距離 繪製座標 深度快取中儲存著每個象素點 繪製在螢幕上的 的深度值!深度值 z值 越大,則離攝像機越遠。深度值是存貯在深度快取裡面的,我們用深度快取的位數來衡量深度快取的精度。深度...