1、深度測試
深度就是在OpenGL坐標(biāo)系中柏肪,像素點的Z坐標(biāo)距離觀察者的距離姐刁。
如果觀察者在Z軸的正方向,Z值越大則越靠近觀察者烦味;
如果觀察者在Z軸的負(fù)方向龙填,Z值越小則越靠近觀察者;
注意:以上兩種情況的坐標(biāo)系都是相對于物體的坐標(biāo)系,而不是觀察者岩遗。
深度緩沖區(qū)(Depth Buffer)
深度緩存區(qū)是指一塊專門內(nèi)存區(qū)域扇商,存儲在顯存中,用于存儲屏幕上所繪制圖形的每個像素點的深度值宿礁。
深度值越大案铺,離觀察者越遠(yuǎn);
深度值越小梆靖,里觀察者越近控汉;
深度緩沖區(qū)原理
將深度值與屏幕上的每個像素點進行一一對應(yīng),然后將深度值存儲到深度緩沖區(qū)返吻。
在深度緩存區(qū)中姑子,每個像素點只會記錄一個深度值;
深度緩沖區(qū)的范圍是[0, 1]之間测僵,默認(rèn)值是1.0街佑,表示深度值的最大值;
之前的demo中捍靠,在RenderScene函數(shù)繪制前沐旨,都會先清空緩存區(qū),這里的緩沖區(qū)就包括深度緩沖區(qū)與顏色緩沖區(qū)榨婆,因為如果緩存區(qū)不清空磁携,之前的數(shù)據(jù)會有殘留,會對目前圖形的繪制造成影響良风。
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
深度測試
在繪制一個物體表面時谊迄,?先會將物體表?對應(yīng)的像素的深度值與當(dāng)前深 度緩沖區(qū)中的值進??較,如果?于深度緩沖區(qū)中的值烟央,則丟棄這部分统诺。否則利?這個像素對應(yīng)的深度值和顏?值,分別更新深度緩沖區(qū)和顏?緩存區(qū)吊档。
// 在繪制場景前,清除顏?緩存區(qū),深度緩沖
glClearColor(0.0f,0.0f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 開啟深度測試
glEnable(GL_DEPTH_TEST);
// 關(guān)閉深度測試
glDisable(GL_DEPTH_TEST);
// 打開/關(guān)閉深度緩沖區(qū)寫入 篙议,GL_FALSE: 關(guān)閉寫入 GL_TRUE:打開寫入[圖片上傳中...(GLEnum mode.png-ccee42-1594522176751-0)]
glDepthMask(GLBool value);
// 指定深度測試判斷模式唾糯,默認(rèn)GS_LESS怠硼,當(dāng)前深度值 < 存儲深度值時通過
glDepthFunc(GLEnum mode);
深度測試應(yīng)用場景
在繪制甜甜圈demo中,當(dāng)旋轉(zhuǎn)時移怯,就會出現(xiàn)上圖甜甜圈缺口的情況香璃,其原因是OpenGL無法區(qū)分物體的兩部分重疊情況,導(dǎo)致缺口出現(xiàn)舟误。此時葡秒,就可以通過深度測試來解決,即隱藏面的消除。修復(fù)后結(jié)果圖如下所示:
隱藏面消除方案 總結(jié)
正背面消除:需要根據(jù)頂點數(shù)據(jù)順序判斷用戶可見部分與隱藏面眯牧,隱藏面直接丟棄蹋岩,不繪制,只繪制可見部分学少;
深度測試:可以一次性解決隱藏面消除問題剪个,原理是不管有多少圖層,只顯示可見圖層版确,剩余不可見的都丟棄扣囊;
2、多邊形偏移
Z-Fighting(Z沖突绒疗,閃爍)問題
開啟深度測試后侵歇,由于深度緩沖區(qū)精度有限制,導(dǎo)致深度值在誤差極小時吓蘑,OpenGL出現(xiàn)無法判斷的情況惕虑,導(dǎo)致出現(xiàn)畫面交錯閃現(xiàn)的現(xiàn)象,例如下圖所示:
其問題產(chǎn)生的主要原因是由于圖形靠的太近士修,導(dǎo)致無法區(qū)分出圖層先后次序枷遂。針對該問題,OpenGL提供了一種多邊形偏移(Polygon Offset)方案棋嘲。
使用多邊形偏移酒唉,主要有以下三個步驟
在繪制前,開啟多邊形偏移;
glEnable(GL_POLYGON_OFFSET_FILL);
指定偏移量?glPolygonOffset (GLfloat factor, GLfloat units)沸移,參數(shù)一般填 -1 和 -1;
在繪制完成后痪伦,關(guān)閉多邊形偏移;
glDisable(GL_POLYGON_OFFSET_FILL);
預(yù)防ZFighting閃爍
避免兩個物體靠的太近:在繪制時雹锣,插入一個小偏移网沾;
將近裁剪面(設(shè)置透視投影時設(shè)置)設(shè)置的離觀察者遠(yuǎn)一些:提高裁剪范圍內(nèi)的精確度;
使用更高位數(shù)的深度緩沖區(qū):提高深度緩沖區(qū)的精確度(通常使?的深度緩沖區(qū)是24位的蕊爵,現(xiàn)在有?些硬件使?32/64位的緩沖區(qū))辉哥;
3、混合
當(dāng)開啟深度測試后攒射,兩個重疊的圖層中醋旦,如果有一個圖層是半透明的,另一個是非半透明会放,此時就不能通過深度值比較饲齐,來進行顏色值的覆蓋,而是需要將兩個顏色進行混合咧最,然后存入顏色緩沖區(qū)捂人。
使用
針對不同需求御雕,顏色混合的使用方式有兩種
開關(guān)方式
用于單純的將兩個圖層重疊時進行顏色混合,這種混合并不能解決顏色的混合滥搭。在固定著色器和可編程著色器都可以使用這種方式酸纲。
//開啟,
glEnable(GL_BlEND);
//關(guān)閉
glDisable(GL_BlEND);
開關(guān)方式 + 混合方程式
用于處理類似濾鏡效果的場景瑟匆,簡單描述就是將需要處理的圖片顏色和圖片上覆蓋的半透明顏色進行混合福青,即兩股顏色混合,此時如果只是單純的開關(guān)方式脓诡,已經(jīng)不能滿足我們的需求无午,需要借助混合方程式,來實現(xiàn)兩股顏色的混合祝谚。一般是在可編程著色器中片元著色器中使用宪迟。
//開啟,
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方法中交惯,是通過混合方程式來得到顏色的組合次泽,默認(rèn)情況下混合方程式如下所示:
//Cf -- 最終組合的顏色值
//Cd:源顏色 -- 當(dāng)前渲染命令傳入的顏色值
//CS:目標(biāo)顏色 -- 顏色緩沖區(qū)中已經(jīng)存在的顏色值
//S:源混合因子
//D:目標(biāo)混合因子
Cf = (Cs * S) + (Cd * D)
在混合方程中,新顏色的alpha值越高席爽,添加的新顏色成分就越高意荤,舊顏色值值就保留的越少。
混合總結(jié)
在顏色緩沖區(qū)中只锻,每個像素點只能存儲一種顏色玖像;
顏色混合主要用于實現(xiàn)在不透明物體前繪制透明物體的效果;
只有上面圖層是透明時齐饮,才需要開啟顏色混合捐寥,如果不是,則沒有必要開啟顏色混合祖驱;
引用文章: