麗江網(wǎng)站建設(shè)怎么自己創(chuàng)建一個網(wǎng)站
QT之OpenGL深度測試
- 1. 深度測試概述
- 1. 1 提前深度測試
- 1.2 深度測試相關(guān)函數(shù)
- 2. 深度測試精度
- 2.1 深度沖突
- 3. Demo
- 4. 參考
1. 深度測試概述
在OpenGL
中深度測試(Depth Testing)
是關(guān)閉的,此時(shí)在渲染圖形時(shí)會產(chǎn)生一種現(xiàn)象后渲染的會把最先渲染的遮擋住。而在啟用深度測試后,在渲染時(shí)OpenGL
會將片段的深度與深度緩沖(Depth Buffer)
中的深度值比較,如果比較通過則深度緩沖將更新為新的深度值。如果失敗片段將會被丟棄。
深度緩沖是在片段著色器以及模板測試(Stencil Testing)
運(yùn)行之后在屏幕空間中運(yùn)行的。屏幕空間坐標(biāo)與通過OpenGL
的glViewPort
所定義的視口密切相關(guān)。并且可以直接使用GLSL
內(nèi)置變量gl_FragCoord
從片段著色器中直接訪問。gl_FragCoord
的x
和y
分量代表了片段的屏幕空間坐標(biāo)(其中(0, 0)位于左下角)。gl_FragCoord
中也包含了一個z
分量,它包含了片段真正的深度值。z
值就是需要與深度緩沖內(nèi)容所對比的那個值。
1. 1 提前深度測試
現(xiàn)在大部分的GPU都提供一個叫做提前深度測試(Early Depth Testing)
的硬件特性。提前深度測試允許深度測試在片段著色器之前運(yùn)行。只要我們清楚一個片段永遠(yuǎn)不會是可見的(它在其他物體之后),我們就能提前丟棄這個片段。
片段著色器通常開銷都是很大的,所以我們應(yīng)該盡可能避免運(yùn)行它們。當(dāng)使用提前深度測試時(shí),片段著色器的一個限制是你不能寫入片段的深度值。如果一個片段著色器對它的深度值進(jìn)行了寫入,提前深度測試是不可能的。 OpenGL
不能提前知道深度值。
1.2 深度測試相關(guān)函數(shù)
-
開啟深度測試
glEnable(GL_DEPTH_TEST);
-
每次渲染之前情況深度緩沖
glClear(GL_DEPTH_BUFFER_BIT);
-
執(zhí)行深度測試但不更新深度緩沖。即使用只讀(read-only)的深度緩沖
// 在開啟深度測試后才有效果 glDepthMask(GL_FALSE);
-
指定執(zhí)行深度測試時(shí)的比較方法
/*
GL_ALWAYS 永遠(yuǎn)通過深度測試
GL_NEVER 永遠(yuǎn)不通過深度測試
GL_LESS 在片段深度值小于緩沖的深度值時(shí)通過測試
GL_EQUAL 在片段深度值等于緩沖區(qū)的深度值時(shí)通過測試
GL_LEQUAL 在片段深度值小于等于緩沖區(qū)的深度值時(shí)通過測試
GL_GREATER 在片段深度值大于緩沖區(qū)的深度值時(shí)通過測試
GL_NOTEQUAL 在片段深度值不等于緩沖區(qū)的深度值時(shí)通過測試
GL_GEQUAL 在片段深度值大于等于緩沖區(qū)的深度值時(shí)通過測試
*/
glDepthFunc(GL_LESS);
2. 深度測試精度
在深度緩沖中的深度值是有精度的,深度緩沖會以16、24或32位float的形式存儲它的深度值。在大部分系統(tǒng)中,深度緩沖的精度都是24位的。
深度緩沖中深度值的范圍介于0.0和1.0之間,它將會與觀察者視角所看見的場景中所有物體的z
值進(jìn)行比較。觀察空間的z值可能是投影平截頭體的近平面(Near)
和遠(yuǎn)平面(Far)
之間的任何值。此時(shí)需要某種方式將觀察空間的z
值變換到0.0和1.0之間,可選的方式如下:
-
線性變換
-
非線性變換
非線性不會考慮的問題是當(dāng)深度為1000和深度為1時(shí)渲染精度不同的問題。而非線性的深度值很大一部分是由很小的z
值所決定的,這給了近處的物體很大的深度精度。
2.1 深度沖突
一個很常見的視覺錯誤是在兩個平面或者三角形非常緊密地平行排列在一起時(shí),由于深度緩沖沒有足夠的精度來決定兩個形狀哪個在前面。結(jié)果就是這兩個形狀不斷地在切換前后順序,這會導(dǎo)致很奇怪的花紋,這個現(xiàn)象叫做深度沖突(Z-fighting)
。
深度沖突不能夠完全避免,但有一些技巧可以減輕或者完全避免深度沖突:
- 永遠(yuǎn)不要把多個物體擺的太靠近,以至于它們的一些三角形會重疊
通過在兩個物體之間設(shè)置一個用戶無法注意到的偏移值,你可以完全避免這兩個物體之間的深度沖突。在箱子和地板的例子中,我們可以將箱子沿著正y軸稍微移動一點(diǎn)。箱子位置的這點(diǎn)微小改變將不太可能被注意到,但它能夠完全減少深度沖突的發(fā)生。然而,這需要對每個物體都手動調(diào)整,并且需要進(jìn)行徹底的測試來保證場景中沒有物體會產(chǎn)生深度沖突。 - 盡可能將近平面設(shè)置遠(yuǎn)一些
在前面提到了精度在靠近近平面時(shí)是非常高的,所以如果我們將近平面遠(yuǎn)離觀察者,我們將會對整個平截頭體有著更大的精度。然而,將近平面設(shè)置太遠(yuǎn)將會導(dǎo)致近處的物體被裁剪掉,所以這通常需要實(shí)驗(yàn)和微調(diào)來決定最適合你的場景的近平面距離。 - 使用更高精度的深度緩沖
此種方法是犧牲性能來減少深度沖突
3. Demo
非線性depth演示:
源碼
4. 參考
OpenGL 深度測試