正背面剔除的理解和解決方案:
-
在渲染過程中可能會產(chǎn)生以下這個問題:
QQ20200709-141648-HD.gif
問題:為什么會產(chǎn)生像圖片那樣的問題芳绩,會出現(xiàn)一大坨黑色的掀亥,我明明只是渲染的紅色的,黑色的是怎么來的妥色?帶著這個問題我們往下看...
-
隱藏面消除(Hidden surface elimination)
在繪制3D場景的時候搪花,我們需要決定哪些部分是對觀察者可見的,或者是哪些部分是對觀察者不可見的嘹害。對于不可見的部分撮竿,應(yīng)該及早丟棄。例如在一個不透明的墻壁后吼拥,就不應(yīng)該渲染倚聚,這種情況叫做“隱藏面消除“(Hidden surface elimination)
。
圖中的圓圈剛開始是紅色的凿可,當我們轉(zhuǎn)動圓圈的時候惑折,就會有一部分黑色的授账,這部分黑色的就是隱藏面,是觀察者不可見的惨驶,這部分既然不可見白热,我們就不應(yīng)該把它渲染出來,接下來我們就通過隱藏面消除來優(yōu)化它粗卜。
對于這個問題屋确,我們先來看有幾種解決方案:
-
油畫算法
:
1.先繪制場景中的離觀察者較遠的物體,再繪制較近的物體.
2.例如下?面的圖例: 先繪制紅?色部分,再繪制黃色部分,最后再繪制灰色部分,即可解決隱藏面消除的 問題
image.png
3.使用油畫算法的弊端,只要將場景按照物理理距離觀察者的距離遠近排序,由遠及近的繪制即可.那么會出現(xiàn) 什么問題? 如果三個三角形是疊加的情況,油畫算法將?法處理理.
image.png
通過上面的分析,油畫算法不能處理疊加的情況续扔,那我們接下來就研究一下正背面剔除(Face Culling)
攻臀。
- 嘗試相信一個3D圖形,你從任何一個?向去觀察,最多可以看到幾個?面? 答案是,最多3面. 從一個立方體的任意位置和方向上看,你不可能看到多于3個面. 那么思考? 我們?yōu)楹我嘤嗟娜ダL制那根本看不到的3個面? 如果我們能以某種方式去丟棄這部分數(shù)據(jù),OpenGL 在渲染的性能即可提高超過50%。
- 如何知道某個面在觀察者的視??中不會出現(xiàn)? 任何平面都有2個面,正面/背面.意味著你?個時刻只能看到一面纱昧。OpenGL 可以做到檢查所有正面朝向觀察者的面,并渲染它們.從而丟棄背面朝向的面. 這樣可以 節(jié)約片元著?器的性能刨啸。如果告訴OpenGL 你繪制的圖形,哪個面是正面,哪個面是背面,通過分析頂點數(shù)據(jù)的順序识脆。
正背面區(qū)分
- 正面: 按照逆時針頂點連接順序的三角形面
-
背面: 按照順時針頂點連接順序的三角形面
image.png
分析立方體中的正背面
- 左側(cè)三角形頂點順序為: 1—> 2—> 3 ; 右側(cè)三角形的頂點順序為: 1—> 2—> 3.
- 當觀察者在右側(cè)時,則右邊的三角形方向為逆時針方向則為正面,?左側(cè)的三角形為順時針則為背面
- 當觀察者在左側(cè)時,則左邊的三角形為逆時針方向判定為正面,而右側(cè)的三角形為順時針判定為背面
- 正面和背面是有三角形的頂點定義順序和觀察者方向共同決定的.隨著觀察者的角度方向的改變,正面背面也 會跟著改變
- 開啟表面剔除(默認背面剔除)
void glEnable(GL_CULL_FACE);
- 關(guān)閉表面剔除(默認背面剔除)
void glDisable(GL_CULL_FACE);
- ?戶選擇剔除那個面(正面/背面)
void glCullFace(GLenum mode);
mode參數(shù)為:GL_FRONT,GL_BACK,GL_FRONT_AND_BACK ,默認GL_BACK
- ?戶指定繞序那個為正面
void glFrontFace(GLenum mode);
mode參數(shù)為:GL_CW,GL_CCW
,默認值:GL_CCW
- 例如,剔除正面實現(xiàn)(1)
glCullFace(GL_BACK); glFrontFace(GL_CW);
- 例如,剔除正面實現(xiàn)(2)
glCullFace(GL_FRONT);
深度測試
- 概念:深度緩沖區(qū)(
DepthBuffer
)和顏色緩存區(qū)(ColorBuffer
)是對應(yīng)的.顏?緩存區(qū)存儲像素的顏色信 息,?深度緩沖區(qū)存儲像素的深度信息. 在決定是否繪制一個物體表面時, ?先要將表面對應(yīng)的像 素的深度值與當前深度緩沖區(qū)中的值進行?較. 如果大于深度緩沖區(qū)中的值,則丟棄這部分.否則 利用這個像素對應(yīng)的深度值和顏色值.分別更新深度緩沖區(qū)和顏色緩存區(qū). 這個過程稱為”深度測試”
设联。
- 什么是深度?
深度
其實就是該像素點在3D
世界中距離攝像機的距離,Z
值. - 什么是深度緩沖區(qū)?
深度緩存區(qū)
,就是一塊內(nèi)存區(qū)域,專門存儲著每個像素點(繪制在屏幕上的)深度值.深度值(Z
值)越大, 則離攝像機就越遠. - 為什么需要深度緩沖區(qū)?
在不使?深度測試的時候,如果我們先繪制一個距離比較近的物體,再繪制距離較遠的物體,則距離遠的位圖因為后繪制,會把距離近的物體覆蓋掉. 有了深度緩沖區(qū)后,繪制物體的順序就不那么??重要的. 實際上,只要存在深度緩沖區(qū),OpenGL
都會把像素的深度值寫入到緩沖區(qū)中. 除非調(diào)用glDepthMask(GL_FALSE)
來禁止寫入.
-
深度值計算
- 深度值一般由16位,24位或者32位值表示灼捂,通常是24位离例。位數(shù)越高的話,深度的精確度越好悉稠。深度值的范圍在[0,1]之間宫蛆,值越小表示越靠近觀察者,值越大表示遠離觀察者偎球。
深度緩沖主要是通過計算深度值來比較?小洒扎,在深度緩沖區(qū)中包含深度值介于0.0和1.0之間, 從觀察者看到其內(nèi)容與場景中的所有對象的 z 值進行了?較衰絮。這些視圖空間中的 z 值可以在投影平頭截體的近平面和遠平面之間的任何值袍冷。我們因此需要一些方法來轉(zhuǎn)換這些視圖空間 z 值 到 [0,1] 的范圍內(nèi)猫牡。
-
使用深度測試
- 深度緩沖區(qū),一般由窗口管理系統(tǒng),
GLFW
創(chuàng)建. - 開啟深度測試
glEnable(GL_DEPTH_TEST)
; - 在繪制場景前,清除顏色緩存區(qū),深度緩沖
glClearColor(0.0f,0.0f,0.0f,1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- 清除深度緩沖區(qū)默認值為
1.0
,表示最大的深度值,深度值的范圍為(0,1)
之間. 值越小表示越靠近觀察者,值越大表示 越遠離觀察者
- 深度緩沖區(qū),一般由窗口管理系統(tǒng),