1.首先我們來繪制一個(gè)甜甜圈(openGL中自帶的,效果圖如下)
當(dāng)我們?nèi)バD(zhuǎn)這個(gè)甜甜圈的時(shí)候會(huì)發(fā)現(xiàn)如下的問題(如下圖)
我們來分析一下這個(gè)原因蛋铆,正常的情況下,一個(gè)物體在光照下是有兩面的:陽面(光照覆蓋的面)和陰面(背光的面)放接,上圖中紅色部分就是我們理解的陽面戒职,黑色即為陰面,但是上圖的甜甜圈透乾,看起來特別奇怪,本該顯示陽面的部分確顯示了陰面磕秤。但是我們?cè)谛D(zhuǎn)這個(gè)甜甜圈的時(shí)候乳乌,此時(shí)OpenGL就不知道哪個(gè)面是正面,哪個(gè)面是反面市咆,所以會(huì)導(dǎo)致出現(xiàn)上面這種情況汉操。
解決方案:正背面剔除
正背面剔除是openGL針對(duì)無法區(qū)分正反面所出現(xiàn)的一個(gè)解決方案,它主要是用于處理立面體繪制圖形時(shí)蒙兰,只繪制觀察者能看到的部分磷瘤,看不到的部分就丟棄不繪制芒篷,這種做法可以將渲染性能提高50%左右。
那么openGL應(yīng)用了正背面剔除之后是如何區(qū)分正反面的吶采缚?
其實(shí)在OpenGL中默認(rèn)規(guī)定了逆時(shí)針方向繪制的三角形是正面针炉,當(dāng)然你可以改為順時(shí)針為正面,但是一般不建議這么操作扳抽,主要是由于這個(gè)設(shè)置不僅僅是作用于你的項(xiàng)目篡帕,而是作用于OpenGL全局的。我們習(xí)慣OpenGL中默認(rèn)的即可贸呢。OpenGL內(nèi)部會(huì)通過分析頂點(diǎn)數(shù)據(jù)的順序來確認(rèn)正反面镰烧,并且需要結(jié)合開發(fā)者的位置,我們只需將正背面剔除楞陷,開啟/關(guān)閉即可怔鳖。
開啟正背面剔除 ? void glEnable(GL_CULL_FACE);(默認(rèn)背面剔除)
關(guān)閉正背面剔除 ?void glDisable(GL_CULL_FACE);(默認(rèn)背面剔除)
設(shè)置需要剔除的面?void glCullFace(GLenum mode);
model主要有三大類 1.1:GL_FRONT剔除正面 1.2:GL_BACK剔除背面,是默認(rèn)值 1.3?GL_FRONT_AND_BACK剔除正背面固蛾。
至此我們就可以用正背面剔除來解決openGL無法區(qū)分正反面的情況结执。效果圖如下:
細(xì)看這張加了正背面剔除的甜甜圈,又會(huì)發(fā)現(xiàn)這甜甜圈怎么少了一塊魏铅?這其實(shí)是openGL沒有開啟深度測(cè)試的原因昌犹。
深度(z):觀察者距離像素點(diǎn)的距離。
深度緩沖區(qū):就是把距離觀察者的深度值與窗口的每個(gè)像素點(diǎn)1對(duì)1進(jìn)行關(guān)聯(lián)以及儲(chǔ)存览芳。
深度測(cè)試:深度緩沖區(qū)與顏色緩沖區(qū)是對(duì)應(yīng)的斜姥,在決定是否繪制一個(gè)物體的表面時(shí),首先要將該點(diǎn)當(dāng)前的深度值與深度緩沖區(qū)的該點(diǎn)的深度值進(jìn)行比較沧竟,如果當(dāng)前的深度值距觀察者較近铸敏,那么就存儲(chǔ)該點(diǎn)的深度值和對(duì)應(yīng)的顏色值,并繪制出來悟泵,這個(gè)過程叫做深度測(cè)試杈笔。
下面讓我們看看該如何用代碼實(shí)現(xiàn)深度測(cè)試
開啟深度測(cè)試:void?glEnable(GL_DEPTH_TEST);
關(guān)閉深度測(cè)試:void?glDisable(GL_DEPTH_TEST);
當(dāng)然我們也可以用glDepthFunc(GLenum func)來修改深度測(cè)試的測(cè)試規(guī)則,那么測(cè)試的規(guī)則主要是該函數(shù)的枚舉值如下:
開啟了深度測(cè)試截圖如下:
思考:開啟了深度測(cè)試就一定沒有問題了嗎糕非?
其實(shí)不然蒙具,如下圖所示,三個(gè)圖形在深度值相等的情況下朽肥,深度測(cè)試無法判斷深度值禁筏,會(huì)導(dǎo)致無法預(yù)測(cè)的問題。會(huì)造成上圖2個(gè)畫面交替出現(xiàn)的問題衡招,這個(gè)問題叫 ZFighting 閃爍問題篱昔。
那么如何解決這個(gè)問題呢?
啟用Polygon Offset(多邊形偏移),在執(zhí)行深度測(cè)試之前州刽,細(xì)微的增加深度值空执,使得兩個(gè)重疊的圖形之間有細(xì)微的差異
開啟多邊形偏移void glEnable(GL_POLYGON_OFFSET_FILL);
關(guān)閉多邊形偏移void glDisable(GL_POLYGON_OFFSET_FILL);
提示: 如何避免ZFighting閃爍問題?
不要將兩個(gè)物體靠的太近,避免渲染時(shí)三?形疊在?一起穗椅。這種?方式要求對(duì)場(chǎng)景中物體插?一個(gè)少量的偏移辨绊,那么就可能避免ZFighting現(xiàn)象。例例如上面的?方體和平?面問題中房待,將平?下移0.001f就可以解決這個(gè)問題,當(dāng)然手動(dòng)去插入這個(gè)小的偏移是要付出代價(jià)的.
盡可能將近裁剪?面設(shè)置得離觀察者遠(yuǎn)一些邢羔。上面我們看到,在近裁剪平?附近桑孩,深度的精確度是很?的拜鹤,因此盡可能讓近裁剪面遠(yuǎn)一些的話,會(huì)使整個(gè)裁剪范圍內(nèi)的精確度變?一些流椒。但是這種?方式會(huì)使?離觀察者較近的物體被裁減掉敏簿,因此需要調(diào)試好裁剪?面參數(shù)。
使?更高位數(shù)的深度緩沖區(qū)宣虾,通常使?的深度緩沖區(qū)是24位的惯裕,現(xiàn)在有?些硬件使?32/64位的緩沖區(qū),使精確度得到提?.
以上問題深度測(cè)試問題是正對(duì)于不透明圖層之間的绣硝,那么對(duì)于透明的圖層之間該如何處理吶蜻势?我們把問題留在下一遍博客中解析。