你知道隱藏面消除的幾種解決方案嗎?

前言

大家先看看下面這張圖(1.png):
1.png

從上面圖片看到了什么?這里议慰,容我賣個關(guān)子蠢古,留個懸念。

一别凹、定義

  • 隱藏面消除
    在繪制3D場景的時候草讶,我們需要決定哪些部分是對觀察者可見的,或者哪些部分是對觀察者不可見的炉菲。對于不可見的部分堕战,應(yīng)該及早丟棄。例如:在一個不透明的墻壁后,就不不應(yīng)該渲染拍霜。這種情況叫做“隱藏面消除“(Hidden surface elimination)嘱丢。

二、隱藏面消除的解決方案

既然對于不可見的部分不進(jìn)行渲染祠饺,那到底有多少種方法可以做到呢越驻?那他們又有哪些優(yōu)缺點(diǎn)呢?又該如何選擇最優(yōu)解決方案吠裆?

  • 方案一:油畫算法

繪制原理:先繪制場景中的離觀察者較遠(yuǎn)的物體伐谈,再繪制較近的物體。
圖例(2.png): 先繪制紅?部分试疙,再繪制??部分,最后再繪制灰色部分抠蚣,即可解決隱藏?消除的問題祝旷。

2.png

利弊:
使?油畫算法,只要將場景按照物理距離觀察者的距離遠(yuǎn)近排序嘶窄,由遠(yuǎn)及近的繪制即可怀跛。那么會出現(xiàn) 什么問題? 如果三個三角形是疊加的情況,油畫算法將?無法處理柄冲。

3.png

  • 方案二:正背面剔除(Face Culling)

繪制原理:繪制觀察者所看到的面吻谋,不繪制看不到的面。

注解:
既然正背面剔除的繪制原理是這樣现横,那我們怎么知道某個面在觀察者的視野中不會出現(xiàn)漓拾?
我們都知道,任何平面都有2個面戒祠,正面和背面骇两,同一個時刻,你只能看到其中一面姜盈。
那哪個是正面低千,哪個又是背面呢?OpenGL又是如何區(qū)分的呢馏颂?

下面示血,我們試著分析頂點(diǎn)的順序來看下:

4.png

OpenGL正背面默認(rèn)是這樣區(qū)分的:
正面: 按照逆時針頂點(diǎn)連接順序的三?形面
背面:按照順時針頂點(diǎn)連接順序的三?形面

那通過立方體來分析又是怎樣的呢棋傍?

5.png

從上圖看:
左側(cè)三角形頂點(diǎn)順序為:1 -> 2 -> 3; 右側(cè)三角形的頂點(diǎn)順序為:1 -> 2 -> 3难审。
當(dāng)觀察者在右側(cè)時舍沙,則右邊的三角形?向為逆時針方向則為正面,而左側(cè)的三角形為順時針則為背?剔宪。
當(dāng)觀察者在左側(cè)時拂铡,則左邊的三角形為逆時針?向判定為正面,而右側(cè)的三角形為順時針判定為背?葱绒。
總的來說感帅,正面和背面是由三角形的頂點(diǎn)定義順序和觀察者?向共同決定的。隨著觀察者的角度方向的改變地淀,正面背面也會跟著改變失球。

優(yōu)勢:
采用正背面剔除,意味著帮毁,我們只需要繪制看得到的面实苞,這在OpenGL渲染的性能上可提高超過50%。

那代碼上又是如何實現(xiàn)的呢烈疚?

//開啟表面剔除(默認(rèn)背面剔除)
void glEnable(GL_CULL_FACE);

//關(guān)閉表面剔除(默認(rèn)背面剔除)
void glDisable(GL_CULL_FACE);

//用戶選擇剔除哪個面(正面/背面)
void glCullFace(GLenum mode);
mode參數(shù)為: GL_FRONT黔牵,GL_BACK,GL_FRONT_AND_BACK 爷肝;默認(rèn)GL_BACK 

//用戶指定繞序哪個為正?
void glFrontFace(GLenum mode);
mode參數(shù)為: GL_CW(順時針)猾浦,GL_CCW(逆時針);默認(rèn)GL_CCW 

舉個例子灯抛,如果我們要剔除正面金赦,那該如何實現(xiàn)?有兩種方式:

//第一種:
glCullFace(GL_BACK);
glFrontFace(GL_CW);

//第二種:
glCullFace(GL_FRONT);
  • 方案三:Z-buffer方法(深度緩沖區(qū)Depth-buffer)

在說Z-buffer方法之前对嚼,我們先通過幾個問題來了解下深度夹抗。
(1)什么是深度?
深度其實就是該像素點(diǎn)在3D世界中距離攝像機(jī)的距離,Z值纵竖。

(2)什么是深度緩沖區(qū)?
深度緩存區(qū)漠烧,就是一塊內(nèi)存區(qū)域,專門存儲著每個像素點(diǎn)(繪制在屏幕上的)深度值磨确。深度值(Z值)越大沽甥,則離攝像機(jī)就越遠(yuǎn)。

(3)為什么需要深度緩沖區(qū)?
在不使?深度測試的時候乏奥,如果我們先繪制?個距離比較近的物理摆舟,再繪制距離較遠(yuǎn)的物理,則距離遠(yuǎn)的位圖因為后繪制,會把距離近的物體覆蓋掉恨诱。有了深度緩沖區(qū)后媳瞪,繪制物體的順序就不那么?? 要了。 實際上照宝,只要存在深度緩沖區(qū)蛇受,OpenGL 都會把像素的深度值寫入到緩沖區(qū)中。除非調(diào)用glDepthMask(GL_FALSE)來禁?寫?厕鹃。

那到底什么是深度測試呢兢仰?
深度緩沖區(qū)(DepthBuffer)和顏色緩存區(qū)(ColorBuffer)是對應(yīng)的。顏色緩存區(qū)存儲像素的顏?色信息剂碴,而深度緩沖區(qū)存儲像素的深度信息把将。 在決定是否繪制一個物體表面時,首先要將表面對應(yīng)的像素的深度值與當(dāng)前深度緩沖區(qū)中的值進(jìn)行比較忆矛。如果?于深度緩沖區(qū)中的值察蹲,則丟棄這部分。否則利用這個像素對應(yīng)的深度值和顏色值催训,分別更新深度緩沖區(qū)和顏色緩存區(qū)洽议。 這個過程稱為“深度測試”。

繪制原理:繪制一個物體表面時漫拭,首先要將表面對應(yīng)的像素的深度值與當(dāng)前深度緩沖區(qū)中的值進(jìn)行比較亚兄,如果?于深度緩沖區(qū)中的值,則丟棄這部分嫂侍。否則利用這個像素對應(yīng)的深度值和顏色值儿捧,分別更新深度緩沖區(qū)和顏色緩存區(qū)。

深度緩沖區(qū)挑宠,一般由窗?管理系統(tǒng)GLFW創(chuàng)建。深度值?般由16位颓影,24位各淀,32位值表示。 通常是24位诡挂。位數(shù)越高碎浇,深度精確度更好。

圖例(6.png):

6.png

那深度測試代碼上又是怎樣的璃俗?

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

/*
在繪制場景前奴璃,需要清除顏色緩存區(qū),深度緩沖
清除深度緩沖區(qū)默認(rèn)值為1.0城豁,表示最大的深度值苟穆,深度值的范圍為(0,1)之間。值越小表示越靠近觀察者,值越大表示越遠(yuǎn)離觀察者雳旅。
*/
glClearColor(0.0f,0.0f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//指定深度測試判斷模式
void glDepthFunc(GLEnum mode);
mode參數(shù):具體見下圖(7.png)

//打開h或阻斷深度緩存區(qū)寫入
void glDepthMask(GLBool value);
value:GL_TURE 開啟深度緩沖區(qū)寫入跟磨;GL_FALSE 關(guān)閉深度緩沖區(qū)寫入。默認(rèn)開啟
7.png

好啦攒盈,深度測試就講到這里抵拘。

最后的最后,
那隱藏面消除的幾種方案講解到此就也結(jié)束啦型豁!
現(xiàn)在再回過去看最上面的那張圖(1.png)僵蛛,你看到什么了嗎?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末迎变,一起剝皮案震驚了整個濱河市充尉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌氏豌,老刑警劉巖喉酌,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異泵喘,居然都是意外死亡泪电,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門纪铺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來相速,“玉大人,你說我怎么就攤上這事鲜锚⊥晃埽” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵芜繁,是天一觀的道長旺隙。 經(jīng)常有香客問我,道長骏令,這世上最難降的妖魔是什么蔬捷? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮榔袋,結(jié)果婚禮上周拐,老公的妹妹穿的比我還像新娘。我一直安慰自己凰兑,他們只是感情好妥粟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吏够,像睡著了一般勾给。 火紅的嫁衣襯著肌膚如雪滩报。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天锦秒,我揣著相機(jī)與錄音露泊,去河邊找鬼。 笑死旅择,一個胖子當(dāng)著我的面吹牛惭笑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播生真,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼沉噩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了柱蟀?” 一聲冷哼從身側(cè)響起川蒙,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎长已,沒想到半個月后畜眨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡术瓮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年康聂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胞四。...
    茶點(diǎn)故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡恬汁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出辜伟,到底是詐尸還是另有隱情氓侧,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布导狡,位于F島的核電站约巷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏旱捧。R本人自食惡果不足惜载庭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望廊佩。 院中可真熱鬧,春花似錦靖榕、人聲如沸标锄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽料皇。三九已至谓松,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間践剂,已是汗流浹背鬼譬。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留逊脯,地道東北人优质。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像军洼,于是被迫代替她去往敵國和親巩螃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評論 2 355