深度測(cè)試

深度測(cè)試

在使用OpenGL繪制完下面圖形進(jìn)行旋轉(zhuǎn)時(shí),則出現(xiàn)了下面的情況:


1594797028631.jpg

1594797033130.jpg

在了解相關(guān)資料之后,后面的這種情況出現(xiàn)是因?yàn)楫?dāng)圖形進(jìn)行旋轉(zhuǎn)時(shí),兩個(gè)部分重疊,此時(shí)OpenGL不能清楚分辨哪個(gè)圖層在前,哪個(gè)圖層在后,則會(huì)出現(xiàn)這種仿佛被咬了一個(gè)口的現(xiàn)象。當(dāng)這種情況出現(xiàn)后,可以通過(guò)開(kāi)啟深度測(cè)試來(lái)解決此問(wèn)題。

什么是深度

深度其實(shí)就是該像素點(diǎn)在OpenGL 坐標(biāo)系中距離觀察者的距離,即Z值。觀察者可以放在坐標(biāo)系的任意位置,但是不能簡(jiǎn)單的說(shuō)Z值越大或者越小,則觀察者就越靠近物體。而是當(dāng)觀察者在Z軸的正方向,Z值越大則靠近觀察者;當(dāng)觀察者在Z軸負(fù)方向,Z值越小則靠近觀察者。

什么是深度緩存區(qū)

深度緩存區(qū)就是顯存中的一塊區(qū)域,存儲(chǔ)著每個(gè)像素點(diǎn)(繪制在屏幕上的)深度值,深度值越大,則離觀察者越遠(yuǎn)。

深度測(cè)試

深度緩存區(qū)(DepthBuffer)和顏色緩存區(qū)(ColorBuffer)是對(duì)應(yīng)的。顏色緩存區(qū)存儲(chǔ)像素的顏色信息,而深度緩存區(qū)存儲(chǔ)像素的深度信息。在決定是否繪制一個(gè)物體表面時(shí),首先要將表面對(duì)應(yīng)的像素的深度值與當(dāng)前緩存區(qū)中的值進(jìn)行對(duì)比。如果大于深度緩存區(qū)中的值,則丟棄這部分。否則利用這個(gè)像素對(duì)應(yīng)的深度值和顏色值。分別更新深度緩存取和顏色緩存區(qū),這個(gè)過(guò)程稱(chēng)為“深度測(cè)試”。
當(dāng)開(kāi)啟了深度測(cè)試時(shí),在繪制每個(gè)像素前,OpenGL會(huì)把它的深度值與目前像素點(diǎn)對(duì)應(yīng)存儲(chǔ)的深度值進(jìn)行比較。如果像素點(diǎn)新對(duì)應(yīng)深度值<像素點(diǎn)對(duì)應(yīng)的深度值,(就是比較兩個(gè)當(dāng)前圖層時(shí),哪一個(gè)圖層更接近觀察者)那么此時(shí)就會(huì)將該像素點(diǎn)的深度值進(jìn)行取而代之;相反,則像素點(diǎn)上的新顏色值距離觀察者更同時(shí)會(huì)被遮擋,那么此時(shí)它對(duì)應(yīng)的深度值與顏色值就會(huì)被拋棄,不進(jìn)行繪制。

開(kāi)啟深度測(cè)試

glEnable(GL_DEPTH_TEST);

關(guān)閉深度測(cè)試

glDisable(GL_DEPTH_TEST);

深度測(cè)試規(guī)則

深度緩存區(qū)的默認(rèn)值為1.0,為最大深度值,深度值的范圍是[0,1]之間。
深度測(cè)試的測(cè)試規(guī)則為多個(gè)枚舉值,我們可以通過(guò)glDepthFunc(GLenum func)來(lái)修改。其中具體枚舉值如下圖:

1594802589660.jpg

深度測(cè)試的潛在風(fēng)險(xiǎn)ZFighting

在我們開(kāi)啟深度測(cè)試后,OpenGL就不會(huì)再去繪制模型被遮擋的部分,這會(huì)使得顯示效果更加真實(shí)。但是當(dāng)深度緩存區(qū)精度的限制對(duì)于深度相差非常小的情況下(在同一平面上進(jìn)行兩次繪制),OpenGL就可能出現(xiàn)不能正確判斷兩者的深度值,會(huì)導(dǎo)致深度測(cè)試的結(jié)果不可預(yù)測(cè),從而導(dǎo)致顯示出來(lái)的現(xiàn)象交錯(cuò)閃爍兩個(gè)圖像交錯(cuò)出現(xiàn)。


1594803959187.jpg

那么如何解決ZFighting

既然是因?yàn)橐驗(yàn)榭康奶?,無(wú)法區(qū)分圖層先后。那么我們可以在圖層之間加入一個(gè)微妙的間隔。其中OpenGL有提供相應(yīng)的解決方案,即“多邊形偏移”。

  1. 啟用多邊形偏移Polygon Offset。在深度值之間產(chǎn)生間隔,讓兩個(gè)圖形之間有間隔,那么就意味著就不會(huì)因?yàn)樯疃戎迪嗖钸^(guò)小而導(dǎo)致深度測(cè)試無(wú)法預(yù)測(cè),將兩個(gè)重疊的圖形之間的深度值區(qū)分開(kāi)來(lái)。
 //啟用多邊形偏移
  /*
    GL_POLYGON_OFFSET_POINT  對(duì)應(yīng)模式:GL_POINT
    GL_POLYGON_OFFSET_LINE   對(duì)應(yīng)模式:GL_LINE
    GL_POLYGON_OFFSET_FILL   對(duì)應(yīng)模式:GL_FILL
   */
  glEnable(GL_POLYGON_OFFSET_FILL);
  ```

2. 指定偏移量
 通過(guò)glPolygonOffset來(lái)指定。當(dāng)Offset大于0會(huì)把模型推到離你(觀察者)更遠(yuǎn)的位置,當(dāng)offset小于0時(shí)會(huì)把模型拉近。一般而言,只需要將-1和-1這樣簡(jiǎn)單賦值就基本上滿足需求了。

/*
應(yīng)用到片段上的總偏移計(jì)算公式
Depth Offset = (DZfactor)+(runits);
DZ:深度值(Z)
r:使得深度緩存區(qū)產(chǎn)生變化的最小值
*/
glPolygonOffset(GLfloat factor, GLfloat units);

3. 關(guān)閉多邊形偏移
```//關(guān)閉多邊形偏移
    glDisable(GL_POLYGON_OFFSET_FILL);

預(yù)防ZFighting閃爍問(wèn)題

  1. 不要將兩個(gè)物體相隔太近,避免渲染時(shí)三角形疊在一起。
  2. 盡可能將近裁剪面離觀察者遠(yuǎn)一些。
  3. 使用更高位數(shù)的深度緩存區(qū),通常使用的深度緩存區(qū)是24位,現(xiàn)在有一些硬件使用32/64位緩存區(qū),使得精確度得到提高
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容