深度測試,就是unity中的層級,就是說定義他的層級,這樣纔不會出現多餘的渲染或不需要的圖形。
其實就是根據Z軸上的值,來判斷哪些片段被拋棄。
其實前面我們已經使用過深度測試了,就是下面這句代碼
glEnable(GL_DEPTH_TEST);
使用這句代碼就能開啓深度測試。
我們來複習一下:
這是沒有開深度測試的效果圖:
這是開了深度測試的效果圖:
然後還有一句,禁止更新深度緩存區的代碼,只是用了這句代碼,我的程序就一片背景色,我也沒辦法得知到底是爲啥:
glDepthMask(GL_FALSE);
接下來就是glDepthFunc()了。
其有一堆的設置:
glDepthFunc(GL_ALWAYS);//總是通過深度測試,就是全部通過,跟沒開一樣,參考一號圖
glDepthFunc(GL_LESS);//當片段深度小於深度緩衝區中的值時,通過測試,其實就是默認開啓時的設置,參考二號圖
glDepthFunc(GL_NEVER);//永遠不能通過測試,就是一片背景色唄。一塊三角形都沒有渲染出來。參考三號圖
glDepthFunc(GL_EQUAL);//需要片段深度與深度緩衝區中的值相等時通過測試,參考三號圖
glDepthFunc(GL_LEQUAL);//需要片段深度與深度緩衝區中的值小於相等時通過測試,參考二號圖
glDepthFunc(GL_GREATER);//需要片段深度大於深度緩衝區中的值時通過測試,參考三號圖
glDepthFunc(GL_NOTEQUAL);//需要片段深度與深度緩衝區中的值不相等時通過測試,參考一號圖
glDepthFunc(GL_GEQUAL);//需要片段深度大於等於深度緩衝區中的值時通過測試,參考三號圖
深度值精度:就是我們將觀察空間中Z軸的,通過一種方式轉換到0到1之間,所給計算的精度。
當其比較近的時候,他的精度要求也就高,遠了要就應該低一些,所以我們不能使用線性的函數,
而應該選用非線性的函數。
重要的是要記住深度緩衝中的值在屏幕空間中不是線性的(在透視矩陣應用之前在觀察空間中是線性的)。深度緩衝中0.5的值並不代表着物體的z值是位於平截頭體的中間了,這個頂點的z值實際上非常接近近平面!
下面是深度測試的可視化:
先將FragmentSource.frag的最後一句改一下:
FragColor = vec4(vec3(gl_FragCoord.z), 1.0);
我們就能夠發現所有的正方體都變成了白色,這是因爲屏幕空間中的深度值時非線性的,在z值較小時,精度很高,但z值較大時,精度就並不高。所以當距離拉遠時,屏幕空間中的深度值,也就全部都是接近於1的。而當你拉近視角時,你就能夠看見正方體的白色變暗了,這就是其深度值的變化。
如下圖:
因此我們需要的是從屏幕空間【0,1】轉換到我們的裁剪空間【-1,1】,再逆轉投影矩陣,得到我們要的線性深度值。
之後將片段着色器改成這樣。
#version 330 core
out vec4 FragColor;
float near = 0.1;
float far = 100.0;
float LinearizeDepth(float depth)
{
float z = depth * 2.0 - 1.0; // 將屏幕空間的值轉到裁剪空間
return (2.0 * near * far) / (far + near - z * (far - near)); //逆轉投影矩陣,具體的推導我不想了解,需要的時候再去了解吧
}
void main()
{
float depth = LinearizeDepth(gl_FragCoord.z) / far; // 爲了演示除以 far
FragColor = vec4(vec3(depth), 1.0);
}
我們就得到了下面這個效果圖:
我們可以看到越近的正方體的顏色越深,也代表這他們的值越小。
還有就是當深度測試時,兩個貼圖靠的太近時,因爲其深度值太過接近,所以就有可能出現貼圖重疊的情況。
記錄一下,深度測試時的深度衝突的防止方法。
第一個也是最重要的技巧是永遠不要把多個物體擺得太靠近,以至於它們的一些三角形會重疊
第二個技巧是儘可能將近平面設置遠一些
另外一個很好的技巧是犧牲一些性能,使用更高精度的深度緩衝