1、深度測(cè)試
深度就是在OpenGL坐標(biāo)系中,像素點(diǎn)的Z坐標(biāo)距離觀察者的距離。
如果觀察者在Z軸的正方向,Z值越大則越靠近觀察者;
如果觀察者在Z軸的負(fù)方向,Z值越小則越靠近觀察者;
注意:以上兩種情況的坐標(biāo)系都是相對(duì)于物體的坐標(biāo)系,而不是觀察者。
深度緩沖區(qū)(Depth Buffer)
深度緩存區(qū)是指一塊專(zhuān)門(mén)內(nèi)存區(qū)域,存儲(chǔ)在顯存中,用于存儲(chǔ)屏幕上所繪制圖形的每個(gè)像素點(diǎn)的深度值。
深度值越大,離觀察者越遠(yuǎn);
深度值越小,里觀察者越近;
深度緩沖區(qū)原理
將深度值與屏幕上的每個(gè)像素點(diǎn)進(jìn)行一一對(duì)應(yīng),然后將深度值存儲(chǔ)到深度緩沖區(qū)。
在深度緩存區(qū)中,每個(gè)像素點(diǎn)只會(huì)記錄一個(gè)深度值;
深度緩沖區(qū)的范圍是[0, 1]之間,默認(rèn)值是1.0,表示深度值的最大值;
之前的demo中,在RenderScene函數(shù)繪制前,都會(huì)先清空緩存區(qū),這里的緩沖區(qū)就包括深度緩沖區(qū)與顏色緩沖區(qū),因?yàn)槿绻彺鎱^(qū)不清空,之前的數(shù)據(jù)會(huì)有殘留,會(huì)對(duì)目前圖形的繪制造成影響。
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
深度測(cè)試
在繪制一個(gè)物體表面時(shí),?先會(huì)將物體表?對(duì)應(yīng)的像素的深度值與當(dāng)前深 度緩沖區(qū)中的值進(jìn)??較,如果?于深度緩沖區(qū)中的值,則丟棄這部分。否則利?這個(gè)像素對(duì)應(yīng)的深度值和顏?值,分別更新深度緩沖區(qū)和顏?緩存區(qū)。
// 在繪制場(chǎng)景前,清除顏?緩存區(qū),深度緩沖
glClearColor(0.0f,0.0f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 開(kāi)啟深度測(cè)試
glEnable(GL_DEPTH_TEST);
// 關(guān)閉深度測(cè)試
glDisable(GL_DEPTH_TEST);
// 打開(kāi)/關(guān)閉深度緩沖區(qū)寫(xiě)入 ,GL_FALSE: 關(guān)閉寫(xiě)入 GL_TRUE:打開(kāi)寫(xiě)入[圖片上傳中...(GLEnum mode.png-ccee42-1594522176751-0)]
glDepthMask(GLBool value);
// 指定深度測(cè)試判斷模式,默認(rèn)GS_LESS,當(dāng)前深度值 < 存儲(chǔ)深度值時(shí)通過(guò)
glDepthFunc(GLEnum mode);
深度測(cè)試應(yīng)用場(chǎng)景

在繪制甜甜圈demo中,當(dāng)旋轉(zhuǎn)時(shí),就會(huì)出現(xiàn)上圖甜甜圈缺口的情況,其原因是OpenGL無(wú)法區(qū)分物體的兩部分重疊情況,導(dǎo)致缺口出現(xiàn)。此時(shí),就可以通過(guò)深度測(cè)試來(lái)解決,即隱藏面的消除。修復(fù)后結(jié)果圖如下所示:

隱藏面消除方案 總結(jié)
正背面消除:需要根據(jù)頂點(diǎn)數(shù)據(jù)順序判斷用戶(hù)可見(jiàn)部分與隱藏面,隱藏面直接丟棄,不繪制,只繪制可見(jiàn)部分;
深度測(cè)試:可以一次性解決隱藏面消除問(wèn)題,原理是不管有多少圖層,只顯示可見(jiàn)圖層,剩余不可見(jiàn)的都丟棄;
2、多邊形偏移
Z-Fighting(Z沖突,閃爍)問(wèn)題
開(kāi)啟深度測(cè)試后,由于深度緩沖區(qū)精度有限制,導(dǎo)致深度值在誤差極小時(shí),OpenGL出現(xiàn)無(wú)法判斷的情況,導(dǎo)致出現(xiàn)畫(huà)面交錯(cuò)閃現(xiàn)的現(xiàn)象,例如下圖所示:

其問(wèn)題產(chǎn)生的主要原因是由于圖形靠的太近,導(dǎo)致無(wú)法區(qū)分出圖層先后次序。針對(duì)該問(wèn)題,OpenGL提供了一種多邊形偏移(Polygon Offset)方案。
使用多邊形偏移,主要有以下三個(gè)步驟
在繪制前,開(kāi)啟多邊形偏移;
glEnable(GL_POLYGON_OFFSET_FILL);
指定偏移量?glPolygonOffset (GLfloat factor, GLfloat units),參數(shù)一般填 -1 和 -1;
在繪制完成后,關(guān)閉多邊形偏移;
glDisable(GL_POLYGON_OFFSET_FILL);
預(yù)防ZFighting閃爍
避免兩個(gè)物體靠的太近:在繪制時(shí),插入一個(gè)小偏移;
將近裁剪面(設(shè)置透視投影時(shí)設(shè)置)設(shè)置的離觀察者遠(yuǎn)一些:提高裁剪范圍內(nèi)的精確度;
使用更高位數(shù)的深度緩沖區(qū):提高深度緩沖區(qū)的精確度(通常使?的深度緩沖區(qū)是24位的,現(xiàn)在有?些硬件使?32/64位的緩沖區(qū));
3、混合
當(dāng)開(kāi)啟深度測(cè)試后,兩個(gè)重疊的圖層中,如果有一個(gè)圖層是半透明的,另一個(gè)是非半透明,此時(shí)就不能通過(guò)深度值比較,來(lái)進(jìn)行顏色值的覆蓋,而是需要將兩個(gè)顏色進(jìn)行混合,然后存入顏色緩沖區(qū)。
使用
針對(duì)不同需求,顏色混合的使用方式有兩種
開(kāi)關(guān)方式
用于單純的將兩個(gè)圖層重疊時(shí)進(jìn)行顏色混合,這種混合并不能解決顏色的混合。在固定著色器和可編程著色器都可以使用這種方式。
//開(kāi)啟,
glEnable(GL_BlEND);
//關(guān)閉
glDisable(GL_BlEND);
開(kāi)關(guān)方式 + 混合方程式
用于處理類(lèi)似濾鏡效果的場(chǎng)景,簡(jiǎn)單描述就是將需要處理的圖片顏色和圖片上覆蓋的半透明顏色進(jìn)行混合,即兩股顏色混合,此時(shí)如果只是單純的開(kāi)關(guān)方式,已經(jīng)不能滿(mǎn)足我們的需求,需要借助混合方程式,來(lái)實(shí)現(xiàn)兩股顏色的混合。一般是在可編程著色器中片元著色器中使用。
//開(kāi)啟,
glEnable(GL_BlEND);
//設(shè)置混合因子--默認(rèn)值是 GL_SRC_ALPHA 和 GL_ONE_MINUS_SRC_ALPHA
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
//關(guān)閉
glDisable(GL_BlEND);
在glBlendFunc方法中,是通過(guò)混合方程式來(lái)得到顏色的組合,默認(rèn)情況下混合方程式如下所示:
//Cf -- 最終組合的顏色值
//Cd:源顏色 -- 當(dāng)前渲染命令傳入的顏色值
//CS:目標(biāo)顏色 -- 顏色緩沖區(qū)中已經(jīng)存在的顏色值
//S:源混合因子
//D:目標(biāo)混合因子
Cf = (Cs * S) + (Cd * D)
在混合方程中,新顏色的alpha值越高,添加的新顏色成分就越高,舊顏色值值就保留的越少。
混合總結(jié)
在顏色緩沖區(qū)中,每個(gè)像素點(diǎn)只能存儲(chǔ)一種顏色;
顏色混合主要用于實(shí)現(xiàn)在不透明物體前繪制透明物體的效果;
只有上面圖層是透明時(shí),才需要開(kāi)啟顏色混合,如果不是,則沒(méi)有必要開(kāi)啟顏色混合;
引用文章: