什么是OpenGL中的深度、深度緩存、深度測試?
2011-05-01 10:50:32| 分類: 默認分類 | 標簽:opengl |字號大中小 訂閱
1)直觀理解
深度其實就是該象素點在3d世界中距離攝象機的距離,深度緩存中存儲着每個象素點(繪制在屏幕上的)的深度值!深度測試決定了是否繪制較遠的象素點(或較近的象素點),通常選用較近的,而較遠優先能實現透視的效果!!!
2)Z值(深度值)、Z buffer(深度緩存)
下面先講講Z坐標。Z坐標和X、Y坐標一樣。在變換、裁減和透視除法后,Z的范圍為-1.0~1.0。DepthRange映射指定Z坐標的變換,這與用於將X和Y映射到窗口坐標的視口變換類似,但DepthRange映射又與視口映射有所不同,因為深度緩存的硬件方案對應用程序來說是隱藏的。調用DepthRange的參數是[0.0,1.0],與一片斷相聯的Z值(深度值)表示到眼睛的距離。在默認情況下,最接近眼睛的片斷(在近截面上)被映射到0.0,離眼睛最遠的片斷(在遠截面上)映射到1.0。片斷可以映射為深度緩存范圍的子集(通過在DepthRange中指定更小的值)。映射也可以相反,這樣的話離眼睛最遠的片斷在0.0,最近的片斷在1.0(調用DepthRange(1.0,0.0)),雖然這樣反向映射是可以的,但對實際應用作用不大。
要理解為什么渲染質量上會不一致,最重要的是要理解屏幕Z坐標的特性。Z值指定了從片斷到眼睛的距離。在正交投影中距離和Z值的關系是線性的,但在透視投影中卻不是的。在透視投影中這種關系是非線性的,而且非線性的程度與Frustum函數中的far/near(或gluPerspective函數中的zFar/zNear)成比例。這種非線性在靠近近截面時增加了Z值的精度,而且增加了深度緩存的效率;但是在視見體的其它部分則降低了精度,也就減少了深度緩存的精確性。根據經驗,far/near比值大於1000會有這種不好的效果。所以一般far/near比值應小於1000。要想解決這個問題,最簡單的方法是通過將近截面遠離眼睛來降低far/near比值,其唯一的副作用是離眼睛很近的物體可能會被裁減掉,但在特定的應用程序中這很少是個問題,近截面的位置對X、Y坐標的投影沒有影響,因此這對圖像的影響很小。
還有OpenGL光柵化和深度緩存的一些其他方面值得一提。一個大問題是光柵化過程使用不精確的算法,所以很難處理共面的圖元,除非它們共享相同的平面方程。這個問題在有限精度的深度緩存實現中更加嚴重。這些問題包括:貼花(decaling)、隱藏線消除、輪廓多邊形和陰影等。不過現在已經提出許多方法來解決這些問題,如PolygonOffset技術等。
深度緩存的位數是衡量深度緩存精度的參數。深度緩存位數越高,則精確度越高,目前的顯卡一般都可支持16位的Z Buffer,一些高級的顯卡已經可以支持32位的Z Buffer,但一般用24位Z Buffer就已經足夠了。
3)深度測試
OpenGL中的深度測試是采用深度緩存器算法,消除場景中的不可見面。在默認情況下,深度緩存中深度值的范圍在0.0到1.0之間,這個范圍值可以通過函數:
glDepthRange (nearNormDepth, farNormalDepth);
將深度值的范圍變為nearNormDepth到farNormalDepth之間。這里nearNormDepth和farNormalDepth可以取0.0到1.0范圍內的任意值,甚至可以讓nearNormDepth > farNormalDepth。這樣,通過glDepthRange函數可以在透視投影有限觀察空間中的任意區域進行深度測試。
另一個非常有用的函數是:
glClearDepth (maxDepth);
參數maxDepth可以是0.0到1.0范圍內的任意值。glClearDepth用maxDepth對深度緩存進行初始化,而默認情況下,深度緩存用1.0進行初始化。由於在進行深度測試中,大於深度緩存初始值的多邊形都不會被繪制,因此glClearDepth函數可以用來加速深度測試處理。這里需要注意的是指定了深度緩存的初始化值之后,應調用:
glClear(GL_DEPTH_BUFFER_BIT);
完成深度緩存的初始化。
在深度測試中,默認情況是將需要繪制的新像素的z值與深度緩沖區中對應位置的z值進行比較,如果比深度緩存中的值小,那么用新像素的顏色值更新幀緩存中對應像素的顏色值。這種比較測試的方式可以通過函數:
glDepthFunc(func);
進行修改。其中參數func的值可以為GL_NEVER(沒有處理)、GL_ALWAYS(處理所有)、GL_LESS(小於)、GL_LEQUAL(小於等於)、GL_EQUAL(等於)、GL_GEQUAL(大於等於)、GL_GREATER(大於)或GL_NOTEQUAL(不等於),其中默認值是GL_LESS。這些測試可以在各種應用中減少深度緩存處理的的計算。