在繪制3D場景的時(shí)候,我們需要決定哪些部分是對(duì)觀察者可見,或者哪些部分是對(duì)觀察者不可見的。對(duì)于不可見的部分,就不應(yīng)該渲染。這種情況叫做隱藏面消除(Hidden surface elimination)。
-
正背面剔除(Face Culling)
默認(rèn)情況下,按照逆時(shí)針頂點(diǎn)連接順序的三角形面為正面
默認(rèn)情況下,按照順時(shí)針頂點(diǎn)連接順序的三角形面為背面
-
開啟正背面剔除(默認(rèn)背面剔除)
void glEnable(GL_CULL_FACE) -
關(guān)閉表面剔除(默認(rèn)背面剔除)
void glDisable(GL_CULL_FACE) -
選擇剔除那個(gè)面
void glCullFace(GLenum mode) mode參數(shù)為: GL_FRONT, GL_BACK, GL_FRONT_AND_BACK, 默認(rèn)GL_BACK -
指定繞序那個(gè)為正面
void glFrontFace(GLenum mode) mode的參數(shù)為: GL_CW, GL_CCW, 默認(rèn)值: GL_CCW
-
深度緩沖區(qū)
- 專門存儲(chǔ)每個(gè)像素點(diǎn)的深度值,深度值越大,則離攝像機(jī)越遠(yuǎn)。
- 在不使用深度測試的時(shí)候,如果我們先繪制一個(gè)距離比較近的物體,再繪制距離較遠(yuǎn)的物體,則距離遠(yuǎn)的物體因?yàn)楹罄L制而把距離近的物體覆蓋掉。有了深度緩沖區(qū)后,繪制物體的順序就不那么重要的。只要存在深度緩沖區(qū),OpenGL都會(huì)把像素的深度值寫入到緩沖區(qū)中。除非調(diào)用glDepthMask(GL_FALSE)來禁止寫入。
-
深度測試
深度緩沖區(qū)(DepthBuffer)和顏色緩沖區(qū)(ColorBuffer)是對(duì)應(yīng)的。
在決定是否繪制一個(gè)物體表面時(shí),首先要將表面對(duì)應(yīng)的像素深度值與當(dāng)前深度緩沖區(qū)中的值進(jìn)行比較。如果大于深度緩沖區(qū)中的值,則丟棄這部分,否則利用這個(gè)像素對(duì)應(yīng)的深度值和顏色值分別更新深度緩沖區(qū)和顏色緩沖區(qū),這個(gè)過程稱為深度測試。
深度值一般由16位、24位、32位值表示。通常是24位,位數(shù)越高,深度精確度更好。
-
開啟深度測試
glEnable(GL_DEPTH_TEST) -
清除深度緩沖區(qū)(默認(rèn)值為1.0,表示最大的深度值,深度值的范圍為[0, 1]之間,值越小表示越靠近觀察者,值越大表示越遠(yuǎn)離觀察者)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) -
深度測試判斷模式
glDepthFunc(GLEnum mode)枚舉值 描述 GL_NEVER 總是不能通過測試 GL_ALWAYS 總是通過測試 GL_LESS 當(dāng)前深度值 < 存儲(chǔ)的深度值時(shí)通過 GL_LEQUAL 當(dāng)前深度值 <= 存儲(chǔ)的深度值時(shí)通過 GL_EQUAL 當(dāng)前深度值 = 存儲(chǔ)的深度值時(shí)通過 GL_GEQUAL 當(dāng)前深度值 >= 存儲(chǔ)的深度值時(shí)通過 GL_GREATER 當(dāng)前深度值 > 存儲(chǔ)的深度值時(shí)通過 GL_NOTEQUAL 當(dāng)前深度值 != 存儲(chǔ)的深度值時(shí)通過 -
打開/阻斷 深度緩沖區(qū)寫入
glDepthMask(GLboolean flag) flag: GL_TRUE 開啟深度緩沖區(qū)寫入,GL_FALSE 關(guān)閉深度緩沖區(qū)寫入
-
ZFighting閃爍問題
由于深度緩沖區(qū)精度的限制,對(duì)于深度值相差非常小的情況,OpenGL就可能出現(xiàn)不能正確判斷兩者的深度值,就會(huì)導(dǎo)致深度測試的結(jié)果不可預(yù)測,顯示出來的現(xiàn)象就是交錯(cuò)閃爍兩個(gè)畫面。
-
啟用 Polygon Offset(多邊形偏移),讓深度值之間產(chǎn)生間隔。
glEnable(GL_POLYGON_OFFSET_FILL) 參數(shù)列表: 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 -
指定偏移量
glPolygonOffset(GLFloat factor, GLFloat units) 應(yīng)用到片段上總偏移計(jì)算方程式: Depth Offset = (Dz * factor) + (r * units) Dz: 深度值 r: 使得深度緩沖區(qū)產(chǎn)生變化的最小值 可以設(shè)置factor和units為-1,-1。 -
關(guān)閉 Polygon Offset
glDisable(GL_POLYGON_OFFSET_FILL)
-
裁剪
用于渲染時(shí)限制繪制區(qū)域。
-
開啟裁剪
glEnable(GL_SCISSOR_TEST) -
關(guān)閉裁剪
glDisable(GL_SCISSOR_TEST) -
指定裁剪窗口
void glScissor(GLint x, GLint y, GLsize width, GLsize height) -
窗口、視口、裁剪區(qū)域
- 窗口:顯示界面
- 視口:窗口中用來顯示圖形的一塊矩形區(qū)域,它可以和窗口等大,也可以比窗口大或者小。只有繪制在視口區(qū)域中的圖形才能被顯示,如果圖形有一部分超出視口區(qū)域,那么那一部分是看不到的。通過glViewPort()函數(shù)設(shè)置。
- 裁剪區(qū)域(平行投影):視口矩形區(qū)域的最小最大x坐標(biāo)(left, right)和最小最大y坐標(biāo)(bottom, top),而不是窗口的最小最大x坐標(biāo)和y坐標(biāo)。通過glOrtho()函數(shù)設(shè)置,這個(gè)函數(shù)還需指定最近最遠(yuǎn)z坐標(biāo),形成一個(gè)立體的裁剪區(qū)域。
-
混合
-
開啟混合
glEnable(GL_BLEND) -
組合顏色
目標(biāo)顏色:已經(jīng)存儲(chǔ)在顏色緩存區(qū)的顏色值
源顏色:作為當(dāng)前渲染命令結(jié)果進(jìn)入顏色緩存區(qū)的顏色值
在默認(rèn)情況下,混合方程式如下:Cf = (Cs * S) + (Cd * D) Cf: 結(jié)果顏色 Cs: 源顏色 Cd: 目標(biāo)顏色 S: 源混合因子 D: 目標(biāo)混合因子 -
設(shè)置混合因子
glBlendFunc(GLenum S, GLenum D) S: 源混合因子 D: 目標(biāo)混合因子枚舉值 RGB混合因子 AlPha混合因子 GL_ZERO (0,0,0) 0 GL_ONE (1,1,1) 1 GL_SRC_COLOR (Rs,Gs,Bs) As GL_ONE_MINUS_SRC_COLOR (1,1,1)-(Rs,Gs,Bs) 1-As GL_DST_COLOR (Rd,Gd,Bd) Ad GL_ONE_MINUS_DST_COLOR (1,1,1)-(Rd,Gd,Bd) 1-Ad GL_SRC_ALPHA (As,As,As) As GL_ONE_MINUS_SRC_ALPHA (1,1,1)-(As,As,As) 1-As GL_DST_ALPHA (Ad,Ad,Ad) Ad GL_ONE_MINUS_DST_ALPHA (1,1,1)-(Ad,Ad,Ad) 1-Ad GL_CONSTANT_COLOR (Rc,Gc,Bc) Ac GL_ONE_MINUS_CONSTANT_COLOR (1,1,1)-(Rc,Gc,Bc) 1-Ac GL_CONSTANT_ALPHA (Ac,Ac,Ac) Ac GL_ONE_MINUS_CONSTANT_ALPHA (1,1,1)-(Ac,Ac,Ac) 1-Ac GL_SRC_ALPHA_SATURATE (f,f,f)*f=min(As,1-Ad) 1 表中R、G、B、A分別表示紅、綠、藍(lán)、alpha
下標(biāo)s、d,分別表示源、目標(biāo)
表中c代表常量顏色(默認(rèn)黑色) -
改變混合方程式
glBlendEquation(GLenum mode)枚舉值 RGB混合因子 GL_FUNC_ADD Cf=(Cs * S) + (Cd * D) GL_FUNC_SUBTRACT Cf=(Cs * S) - (Cd * D) GL_FUNC_REVERSE_SUBTRACT Cf=(Cd * D) - (Cs * S) GL_MIN Cf=min(Cs,Cd) GL_MAX Cf=max(Cs,Cd) -
設(shè)置混合因子(RGB和Alpha分開設(shè)置)
void glBlendFuncSeparate(GLenum strRGB, GLenum dstRGB, GLenum strAlpha, GLenum dstAlpha) -
設(shè)置常量混合顏色
void glBlendColor(GLclampf red, GLclampf green, GLclamf blue, GLclampf alpha)
-