OpenGL入門第4課--深度

深度相關的概念

深度

     深度說白了就是距離觀察者的距離,同一個物體的不一樣頂點距離觀察者的距離不必定相同,因此深度是相對於像素點的概念。深度就是該像素點在3D世界中距離攝像機的距離,其實就是該像素點的Z座標值 。bash

深度緩衝區

     深度緩衝區就是一塊內存區域,專門存儲着每一個像素點(繪製在屏幕上的)深度值.深度值(Z值)越⼤大, 則離攝像機就越遠 。函數

      深度緩衝區,通常由窗⼝管理系統,GLFW建立.深度值⼀般由16位,24位,32位值表示. 一般是24位.數越高,深度精確度更好 post

深度測試

     深度緩衝區(DepthBuffer)和顏色緩衝區(ColorBuffer)是對應的,顏色緩衝區存儲像素的顏色信息,而深度緩衝區存儲像素的深度信息. 在決定是否繪製一個物體表面時, 首先要將表面對應像素的深度值與當前深度緩衝區中的值進⾏比較. 若是⼤於深度緩衝區中的值,則丟棄這部分.不然利用這個像素對應的深度值和顏色值.分別更新深度緩衝區和顏色緩衝區. 這個過程稱爲」深度測試」。性能

     例如假設有這麼一種場景:物體A被物體B遮檔了一部分,即A和B有一部分的像素的x,y座標相同,只有z不一樣。如圖:測試

                                  

      假設沒有深度緩衝區或者不開啓深度測試,若是咱們先繪製一個距離⽐較近的物體(B),再繪製距離較遠的物體,則距離遠的位圖由於後繪製,會把距離近的物體覆蓋掉. 有了深度緩衝區而且開啓深度測試後,繪製物體的順序就不那麼重要了. 實際上,只要存在深度緩衝區,OpenGL 都會把像素的深度值寫⼊到緩衝區中. 除⾮調⽤ glDepthMask(GL_FALSE).來禁⽌止寫入. spa

指定深度測試比較運算符

       OpenGL容許修改深度測試中使用的比較運算符,來控制OpenGL何時該經過或丟棄一個片斷,何時去更新深度緩衝。咱們能夠調用glDepthFunc函數來設置比較運算符。
code

glDepthFunc(GL_LESS);
複製代碼

這個函數接受下面表格中的比較運算符:
cdn

                     

     默認狀況下使用的深度函數是GL_LESS,它將會丟棄深度值大於等於當前深度緩衝值的全部片斷。blog

深度衝突

        因爲深度緩衝區精度的限制,一個很常見的視覺錯誤會在兩個平面或者三角形很是緊密地平行排列在一塊兒時會發生,深度緩衝沒有足夠的精度來決定兩個形狀哪一個在前面。結果就是這兩個形狀不斷地在切換先後順序,這會致使很奇怪的花紋。這個現象叫作深度衝突(Z-fighting),由於它看起來像是這兩個形狀在爭奪(Fight)誰該處於頂端。內存

       深度衝突是深度緩衝的一個常見問題,當物體在遠處時效果會更明顯(由於深度緩衝在z值比較大的時候有着更小的精度)一個經常使用的解決方法就是讓深度值之間產生間隔(Polygon Offset ,多邊形偏移),代碼以下:

glEnable(GL_POLYGON_OFFSET_FILL) //啓用多邊形偏移
						glPolygonOffset(-1,-1);//指定偏移量複製代碼

      啓用多邊形偏移的參數有一下三種:

  • GL_POLYGON_OFFSET_POINT:對應光柵化模式: GL_POINT
  • GL_POLYGON_OFFSET_LINE :對應光柵化模式: GL_LINE
  • GL_POLYGON_OFFSET_FILL:對應光柵化模式: GL_FILL

      glPolygonOffset 須要2個參數: factor , units。每一個Fragment的深度值都會增長以下所示的偏移量:Offset = ( m * factor ) + ( r * units);m是指多邊形的深度的斜率的最大值,一個多邊形越是與近裁剪⾯平⾏,m就越接近於0. r是指能產⽣於窗⼝座標系的深度值中可分辨的差別最⼩值,它是是由具體OpenGL平臺指定的一個常量.一個大於0的Offset 會把模型推到離你(攝像機)更遠的位置,相應的一個小於0的Offset會把模型拉近。通常而言,只須要將-1.0 和 -1 這樣簡單賦值給glPolygonOffset 基本能夠知足需求.  

      因爲OpenGL是狀態機因此用完別忘了關閉多邊形偏移:

glDisable(GL_POLYGON_OFFSET_FILL) 複製代碼

      深度衝突不可以被徹底避免,但通常會有一些技巧有助於在你的場景中減輕或者徹底避免深度衝突。

         第一個也是最重要的技巧是永遠不要把多個物體擺得太靠近,以致於它們的一些三角形會重疊。經過在兩個物體之間設置一個用戶沒法注意到的偏移值,你能夠徹底避免這兩個物體之間的深度衝突。

       第二個技巧是儘量將近平面設置遠一些。在前面咱們提到了精度在靠近平面時是很是高的,因此若是咱們將平面遠離觀察者,咱們將會對整個平截頭體有着更大的精度。然而,將近平面設置太遠將會致使近處的物體被裁剪掉,因此這一般須要實驗和微調來決定最適合你的場景的平面距離。

      另一個很好的技巧是犧牲一些性能,使用更高精度的深度緩衝。大部分深度緩衝的精度都是24位的,但如今大部分的顯卡都支持32位的深度緩衝,這將會極大地提升精度。因此,犧牲掉一些性能,你就能得到更高精度的深度測試,減小深度衝突。

       咱們上面討論的三個技術是最廣泛也是很容易實現的抗深度衝突技術了。還有一些更復雜的技術,但它們依然不能徹底消除深度衝突。深度衝突是一個常見的問題,但若是你組合使用了上面列舉出來的技術,你可能不會再須要處理深度衝突了。

相關文章
相關標籤/搜索