OpenGL正背面剔除、深度測(cè)試

關(guān)于OpenGL繪制流程可查看,之前寫的一篇文章,詳細(xì)解讀了各個(gè)繪制步驟

OpenGL繪制流程

本文主要說明在繪制過程中的正背面剔除以及深度測(cè)試效果;

本示例具體代碼演示下載地址

下載示例代碼運(yùn)行,運(yùn)行效果如下圖,能夠正常繪制出甜甜圈的效果,可以偷偷的笑開心下;

甜甜圈

當(dāng)旋轉(zhuǎn)甜甜圈的時(shí)候,發(fā)現(xiàn)如下圖所示問題,在旋轉(zhuǎn)的過程中,出現(xiàn)了黑色的部分,這個(gè)看起來可不太友好;面對(duì)如此問題該如何解決呢?

旋轉(zhuǎn)甜甜圈

在繪制3D場(chǎng)景的時(shí)候,我們需要決定哪些部分是對(duì)觀察者可?的,或者哪些部分是對(duì)觀察者不可見的.對(duì)于不可見的部分,應(yīng)該及早丟棄.例如在一個(gè)不透明的墻壁后,就不應(yīng)該 渲染.這種情況叫做”隱藏?面消除”(Hidden surface elimination).

解決方案:

油畫算法

油畫畫法

先繪制場(chǎng)景中的離觀察者較遠(yuǎn)的物體,再繪制較近的物體(具體步驟見上圖,先繪制紅色方塊,接著是黃色圓形,接著是灰色長(zhǎng)方形),即可解決隱藏面消除的問題;

油畫畫法弊端

使?油畫算法,只要將場(chǎng)景按照物理距離觀察者的距離遠(yuǎn)近排序,由遠(yuǎn)及近的繪制即可.那么會(huì)出現(xiàn)什么問題??如果個(gè)三?形是疊加的情況,油畫算法將?法處理

疊加三角形

OpenGL提供的解決方案:

正背面剔除(Face Culling)

可以想像下,當(dāng)我們看到一個(gè)3D圖形時(shí),無論從哪個(gè)方向去觀察,最多可以看到幾個(gè)面?~~~答案是3個(gè);基于此,那么就沒有必要繪制根本看不到的3個(gè)面,將看不到的3個(gè)面以某種方式丟棄,OpenGL的渲染性能即可提高50%

OpenGL?可以做到檢查所有正面朝向觀察者的面,并渲染它們.從而丟棄背?朝向的面.?這樣可以節(jié)約片元著?器的性能

glEnable(GL_CULL_FACE);//開啟正面剔除

glDisable(GL_CULL_FACE);//關(guān)閉正面剔除

當(dāng)開啟正面剔除后,運(yùn)行demo會(huì)看到如下效果,prefect~

開啟正背面剔除效果

上面提到了正面、背面兩個(gè)概念,那么OpenGL是如何識(shí)別正面背面,以及是否可以自定義哪個(gè)方向是正面哪個(gè)方向是背面呢?

通過分析頂點(diǎn)數(shù)據(jù)的順序可知

頂點(diǎn)順序

背面:?按照順時(shí)針頂點(diǎn)連接順序的三?形面

正?:?按照逆時(shí)針頂點(diǎn)連接順序的三?形?

立體圖形中的正背面

1、左側(cè)三角形頂點(diǎn)順序?yàn)? 1—> 2—> 3 ;?右側(cè)三角形的頂點(diǎn)順序?yàn)? 1—> 2—> 3 .

2、當(dāng)觀察者在右側(cè)時(shí),則右邊的三?形?向?yàn)槟鏁r(shí)針?向則為正面,而左側(cè)的三?形為順時(shí)針則為背面?

3、當(dāng)觀察者在左側(cè)時(shí),則左邊的三?形為逆時(shí)針?向判定為正面,而右側(cè)的三?角形為順時(shí)針判定為背面.

正面和背面是有三角形的頂點(diǎn)定義順序和觀察者?向共同決定的.隨著觀察者的?度方向的改變,正面背面也會(huì)跟著改變

?戶選擇剔除哪個(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

例如:剔除正面實(shí)現(xiàn)

glCullFace(GL_BACK);

glFrontFace(GL_CW);?

使用正背面剔除效果后,在旋轉(zhuǎn)的過程中沒有黑色陰影出現(xiàn),但是當(dāng)旋轉(zhuǎn)到前后重疊的時(shí)候,會(huì)發(fā)現(xiàn),出現(xiàn)了如下圖所示效果(出現(xiàn)了一個(gè)缺口)?是什么原因?qū)е履兀?/p>

開啟正背面剔除后,當(dāng)旋轉(zhuǎn)到正背面重合時(shí),出現(xiàn)缺口

在甜甜圈旋轉(zhuǎn)過程中,當(dāng)旋轉(zhuǎn)到前后兩部分重疊時(shí),正常情況下應(yīng)該顯示的是離我們近的位置即前面部分,后面部分是隱藏面,但是OpenGL中并不能清除的區(qū)分,兩個(gè)圖層誰顯示在前,誰顯示在后,由此導(dǎo)致甜甜圈產(chǎn)生了缺口

那么如何解決此問題呢?OpenGL給我們提供了哪些方案呢?

在解決問題之前需要了解OpenGL坐標(biāo)體系中的兩個(gè)概念,深度、深度緩存區(qū)

深度

深度其實(shí)就是該像素點(diǎn)在3D世界中距離攝像機(jī)的距離,Z值

深度值一般由16位,24位或者32位值表示,通常是24位。位數(shù)越高的話,深度的精確度越 好。深度值的范圍在[0,1]之間

值越?表示越靠近觀察者

值越大表示遠(yuǎn)離觀察者

深度緩存區(qū)?

深度緩存區(qū),就是一塊內(nèi)存區(qū)域,專門存儲(chǔ)著每個(gè)像素點(diǎn)(繪制在屏幕上的)深度值.存儲(chǔ)在顯存中

深度值(Z值)越?,?則離攝像機(jī)就越遠(yuǎn).

深度值(Z值)越小,?則離攝像機(jī)就越近.

為什么需要深度緩沖區(qū)??在不使用深度測(cè)試的時(shí)候,如果我們先繪制一個(gè)距離?較近的物體,再繪制距離較遠(yuǎn)的物體,則距離遠(yuǎn)的位圖因?yàn)楹罄L制,會(huì)把距離近的物體覆蓋掉.?有了深度緩沖區(qū)后,繪制物體的順序就不那么重要了.?實(shí)際上,只要存在深度緩沖區(qū),OpenGL?都會(huì)把像素的深度值寫?到緩存區(qū)中.?除非調(diào)?用?glDepthMask(GL_FALSE).來禁止寫?.

還記得在渲染的代碼中有一行就是用來專門清除緩存的,包括顏色緩存、深度緩存;因?yàn)槿绻彺鎱^(qū)不清空,之前的數(shù)據(jù)會(huì)有殘留,會(huì)對(duì)目前圖形的繪制造成影響;在不清楚清除哪部分?jǐn)?shù)據(jù)的時(shí)候,可以選擇全部清除,如下

//清空顏色、深度緩存區(qū)

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

在了解了深度以及深度緩存區(qū)之后,在面臨上面缺口問題的時(shí)候,OpenGL提供的解決方案就正式出場(chǎng)啦---深度測(cè)試

深度測(cè)試

glEnable(GL_DEPTH_TEST);//開啟深度測(cè)試

glDisable(GL_DEPTH_TEST);//關(guān)閉深度測(cè)試

開啟深度測(cè)試后,在繪制過程中,像素點(diǎn)新的深度值需要與深度緩存中已經(jīng)存在的深度值作比較,如果新值 > 舊值,則丟棄這部分不繪制,反之,將新的深度值更新至深度緩存區(qū),由于深度緩存區(qū)與顏色緩存區(qū)是一一對(duì)應(yīng)的,同時(shí)也需要更新該像素點(diǎn)的顏色值到顏色緩存區(qū),這個(gè)過程就是深度測(cè)試

開啟深度測(cè)試后,看看效果,在旋轉(zhuǎn)過程中,即使前后重疊,也不會(huì)出現(xiàn)缺口的現(xiàn)象,如下圖

開啟深度測(cè)試效果

深度測(cè)試解決的問題:

1、當(dāng)類似甜甜圈旋轉(zhuǎn)時(shí),前后2個(gè)部分重疊,此時(shí)OpenGL不能清除分辨哪個(gè)圖層在前面,哪個(gè)圖層在后面,則會(huì)出現(xiàn)缺口

2、隱藏面消除,除了使用正背面剔除外,還可使用深度測(cè)試來解決

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容