NDK OpenGL ES 3.0 開發(十):深度測試

該原創文章首發於微信公衆號:字節流動

深度測試

OpenGL 深度測試是指在片段着色器執行之後,利用深度緩衝所保存的深度值決定當前片段是否被丟棄的過程。

深度緩衝區通常和顏色緩衝區有着相同的寬度和高度,一般由窗口系統自動創建並將其深度值存儲爲 16、 24 或 32 位浮點數。

當深度測試開啓的時候, OpenGL 纔會測試深度緩衝區中的深度值。如果此測試通過,深度緩衝內的值可以被設爲新的深度值;如果深度測試失敗,則丟棄該片段。

深度測試是在片段着色器運行之後(並且在模板測試運行之後)在屏幕空間中執行的。

與屏幕空間座標相關的視區是由 OpenGL 的視口設置函數 glViewport 函數給定,並且可以通過片段着色器中內置的 gl_FragCoord 變量訪問。

gl_FragCoord 的 X 和 y 表示該片段的屏幕空間座標 ((0,0) 在左下角),其取值範圍由 glViewport 函數決定,屏幕空間座標原點位於左下角。

gl_FragCoord 還包含一個 z 座標,它包含了片段的實際深度值,此 z 座標值是與深度緩衝區的內容進行比較的值。

深度緩衝區中包含深度值介於 0.0 和 1.0 之間,物體接近近平面的時候,深度值接近 0.0 ,物體接近遠平面時,深度接近 1.0 。

(深度緩衝區的可視化)在片段着色器中將深度值轉換爲物體顏色顯示:

#version 300 es
precision mediump float;
in vec2 v_texCoord;
layout(location = 0) out vec4 outColor;
uniform sampler2D s_TextureMap;
void main()
{
    vec4 objectColor = vec4(vec3(gl_FragCoord.z), 1.0f);
    outColor = objectColor;
}

顯示結果:
深度緩衝區的可視化

從圖中可以觀察到,靠近屏幕的物體顏色更黑(深度值更小),遠離屏幕的物體顏色更白(深度值更大)

深度測試默認是關閉的,啓用深度測試使用 glEnable(GL_DEPTH_TEST);

啓用與不啓用深度測試時,繪製 3D 物體對比:
啓用深度測試
啓用深度測試
不啓用深度測試
不啓用深度測試

開啓深度測試後,如果片段通過深度測試,OpenGL 自動在深度緩衝區存儲片段的 gl_FragCoord.z 值,如果深度測試失敗,那麼相應地丟棄該片段。

如果啓用深度測試,那麼需要在渲染之前使用 glClear(GL_DEPTH_BUFFER_BIT); 清除深度緩衝區,否則深度緩衝區將保留上一次進行深度測試時所寫的深度值。

另外在一些場景中,我們需要進行深度測試並相應地丟棄片段,但我們不希望更新深度緩衝區,那麼可以設置深度掩碼glDepthMask(GL_FALSE);實現禁用深度緩衝區的寫入(只有在深度測試開啓時纔有效)。

OpenGL 深度測試是通過深度測試函數 glDepthFunc 控制深度測試是否通過和如何更新深度緩衝區。

深度測試函數接收的比較運算符:
深度測試函數接收的比較運算符

深度測試啓用後,默認情況下深度測試函數使用 GL_LESS,這將丟棄深度值高於或等於當前深度緩衝區的值的片段。

深度測試中,深度衝突現象需要值得注意。深度衝突(Z-fighting)是指兩個平面(或三角形)相互平行且靠近的過於緊密,模板緩衝區不具有足夠的精度確定哪一個平面靠前,導致這兩個平面的內容不斷交替顯示,看上去像平面內容爭奪頂靠前的位置。

防止深度衝突的方法:

  • 不要讓物體之間靠得過近,以免它們的三角形面片發生重疊;
  • 把近平面設置得遠一些(越靠近近平面的位置精度越高);
  • 犧牲一些性能,使用更高精度的深度值。

實現代碼路徑:
https://github.com/githubhaohao/NDK_OpenGLES_3_0

聯繫與交流

我的公衆號
在這裏插入圖片描述
我的微信
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章