個人
OpenGL
專題學習目錄,但願和你們一塊兒學習交流進步!編程
- OpenGL學習(一)-- 術語瞭解
- OpenGL學習(二)-- Xcode 搭建 OpenGL 環境
- OpenGL學習(三)-- OpenGL 基礎渲染
- OpenGL學習(四)-- 正面&背面剔除和深度測試
- OpenGL學習(五)-- 裁剪與混合
- OpenGL學習(六)-- 基礎紋理
- OpenGL學習(七)-- 基礎變化綜合練習實踐總結
- OpenGL學習(八)-- OpenGL ES 初探(上)
- OpenGL學習(九)-- OpenGL ES 初探(下)GLKit
- OpenGL學習(十)-- 着色語言 GLSL 語法介紹
- OpenGL學習(十一)-- 用 GLSL 實現加載圖片
- OpenGL學習(十二)-- OpenGL ES 紋理翻轉的策略對比
默認狀況下,咱們所渲染的每一個點、線或三角形都會再屏幕上進行光柵化,並按照在組合圖元批次時指定的順序排列,這在某些狀況下會產生問題。緩存
若是咱們繪製一個由不少個三角形組成的實體對象,那麼第一個繪製的三角形可能會被後面繪製的三角形覆蓋。以下圖這個像游泳圈似的模型,其中一些三角形在游泳圈的背面,另外一些在正面,正常咱們應該是看不到背面的(不考慮透明幾何體的特殊狀況)。這樣的話,三角形繪製的順序可能會一團糟,就變成了下圖的樣子:函數
對這些三角形排序,先渲染較遠的三角形,再在它們上方渲染較近的三角形。但這種方法在圖形處理中效率很低,必須在任何發生重疊的地方對每一個像素進行兩次寫操做,速度會變慢。而且對獨立的三角形排序的開銷會太高。因此通常不推薦使用。post
對正面和背面三角形進行區分的緣由之一就是爲了進行剔除。背面剔除能極大提升性能,避免上圖出現的問題。它很高效,在渲染的圖元裝配階段就總體拋棄了一些三角形。性能
開啓背面剔除: glEnable(GL_CULL_FACE);
學習
關閉背面剔除: glDisable(GL_CULL_FACE);
測試
請注意,咱們並無知名剔除的是正面仍是背面。這是由另一個函數 glCullFace
控制的。spa
void glCullFace(GLenum mode);
複製代碼
mode 參數的可用值爲 GL_FRONT
、GL_BACK
或 GL_FRONT_AND_BACK
。這樣要消除不透明物體的內部幾何圖形就須要兩行代碼:.net
void glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
複製代碼
在某些狀況下,剔除實體幾何體的正面也頗有必要,好比要顯示圖形內部渲染的時候。在渲染透明對象時(下面立刻就會講到混合),咱們常常會對一個對象進行兩次渲染,第一次會開啓透明並剔除正面,第二次則消除背面。這樣就在渲染正面以前渲染了背面,這也是渲染透明物體的須要。3d
可是在開啓背面剔除後,會發現上面的游泳圈模型仍是顯示的有問題,如圖:
- 深度:
深度
就是在 openGL 座標系中,像素點的 Z 座標距離觀察者的距離。觀察者可能放在座標系的任何位置,那麼,就不能簡單的說 Z 數值越大或越小,就是越靠近觀察者。 若是觀察者在Z軸的正方向,Z 值大的靠近觀察者,若是是在Z軸的反方向,則 Z 值小的更靠近觀察者。
- 深度緩衝區(DepthBuffer):
深度緩衝區
原理就是把一個距離觀察平面(近裁剪面)的深度值(或距離)與窗口中的每一個像素相關聯。 首先,使用glClear(GL_DEPTH_BUFFER_BIT)
,把全部像素的深度值設置爲最大值。 若是啓用了深度緩衝區,在繪製每一個像素以前,OpenGL 會把它的深度值和已經存儲在這個像素的深度值進行比較。若是,新像素深度值 < 原先像素深度值,則新像素值會取代原先的;反之,新像素值被遮擋,它的顏色值和深度將被丟棄。 這個比較、丟棄的過程就叫作深度測試
,深度測試是另外一種高效消除隱藏面的技術。
申請一個顏色緩衝區和一個深度緩衝區:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
複製代碼
要 啓用
深度測試,只需調用 glEnable(GL_DEPTH_TEST);
關閉
深度測試: glDisable(GL_DEPTH_TEST);
若是沒有深度緩衝區,那麼啓動深度測試的命令將被忽略。 在繪製場景前,清除顏色緩衝區和深度緩衝區:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
複製代碼
開啓了深度測試後,咱們終於獲得了一個咱們想要的游泳圈模型:
清除深度緩衝區的默認值是1.0,表示最大的深度值,深度值的範圍在[0,1]之間。 用戶經過 glDepthFunc(GLenum func)
函數指定深度測試的規則,這個函數包括一個參數,以下表:
參數 | 說明 |
---|---|
GL_ALWAYS |
老是經過測試 |
GL_NEVER |
老是不經過測試 |
GL_LESS |
當前深度值 < 存儲的深度值時經過 |
GL_EQUAL |
當前深度值 = 存儲的深度值時經過 |
GL_LEQUAL |
當前深度值 <= 存儲的深度值時經過 |
GL_GREATER |
當前深度值 > 存儲的深度值時經過 |
GL_NOTEQUAL |
當前深度值 != 存儲的深度值時經過 |
GL_GEQUAL |
當前深度值 >= 存儲的深度值時經過 |
- 避免深度值相同形成的z-fighting衝突問題的幾種作法:
- 在第二次繪製時,插入一個少許的偏移。
- 使用
glPolygonOffset
函數調節片斷的深度值,使得深度值偏移而不產生重疊。
- 使用更高位數的深度緩衝區,一般使用的深度緩衝區是 24 位的,如今有一些硬件使用使用 32 位的緩衝區,使精確度獲得提升。
以上的總結參考了並部分摘抄瞭如下文章,很是感謝如下做者的分享!:
一、《OpenGL超級寶典 第5版》
二、《OpenGL編程指南(第八版)》
三、做者 The fool 的《OpenGL學習腳印:深度測試(depth testing)》
四、做者 lysc_forever的《OpenGL中的深度、深度緩存、深度測試》
轉載請備註原文出處,不得用於商業傳播——凡幾多