OpenGL渲染技巧--深度緩沖區(qū),顏色混合,隱藏面消除以及渲染過程中可能遇到的問題

閱讀了該系列之前幾篇文章,相信大家已經(jīng)對OpenGL渲染流程和基本概念有了一個大致的了解, 這里提醒大家,很多名詞和函數(shù), 可以點進去看下源碼是怎么寫的,另外基本概念切勿死記硬背, 靠敲代碼硬背函數(shù)或者API是不可取的, 要于現(xiàn)實生活的實際場景和例子結(jié)合,才更方便我們記住和系統(tǒng)的了解其原理.
廢話不多說,進入正題.

OpenGL渲染技巧(實際繪制中常用方法)

  • 正?&背?剔除
  • 深度測試
  • 顏色混合
  • 多邊形偏移

在講以上幾個常用方法時我們先來了解下什么是 隱藏面消除

在繪制3D場景的時候议纯,由于觀察者和繪制結(jié)果都只能看到其中的一個面仲翎。對于不會被觀察到的面,則我們無需渲染, 那么這樣我們的渲染效率就會提升50%.
例如:在一個不透明墻壁后的物體,就不應該渲染。這種情況就叫做隱藏面消除(Hidden surface elimination)浓恶。

而如何實現(xiàn)隱藏面消除呢?
實際使用中常用有正?&背?剔除, 深度測試等方法

1.油畫算法

油畫算法如其名所說,按照畫油畫的方式,先把底色繪上,再把上面顏色蓋上,其主要原理如下:
先繪制場景中離觀察者較遠的物體,再繪制較近的物體.

油畫算法示意

那么實際開發(fā)中有使用油畫算法的嗎? 答案是幾乎沒有. 那么為什么呢

  • 首先是性能問題, 對于觀察者/繪制結(jié)果來說我們只會看到繪制在最上面的一層(透明度情況除外,下面我們會講到關(guān)于透明度如何處理). 那么如果同一個像素點有五層, 如果按照油畫算法我們需要繪制5次, 顯然我們在性能上就耗費了5倍與此.
  • 另外是順序問題,參考下圖



    以上這種情況, 油畫算法無法得知繪制順序, 因此,在實際開發(fā)場景中,幾乎沒有油畫算法實現(xiàn)隱藏面消除的身影.

2.正背面剔除(CULL_FACE)

正/背面剔除原理:
1- 我們不去繪制那些根本看不到的面包晰,以某種方式去丟棄這部分數(shù)據(jù)伐憾。
2- 我們可以給平面定義正面和背面,OpenGL可以做到檢查所有正面朝向觀察者的面树肃,并渲染它們,從而丟棄背?朝向的面胸嘴。 OpenGL渲染的性能即可提?超過50%。
默認情況逆時針頂點連接順序為圖形正面,也就是我們所能看到的面.
當然我們也可以指定具體哪個面為正面,但是一般都會使用默認.

頂點順序解析

立方體的正背面(默認情況)

注意:
正?和背面是由三角形的頂點順序和觀察者方向共同決定的,隨著觀察者的角度方向的改變,正面背面也會跟著改變乡话。

3.深度測試(DEPTH_TEST)

每個像素點只有一個深度值耳奕,在同一個像素點出現(xiàn)新的深度值時诬像,會與之前進行比較闸婴,如果新的深度值大掠拳,那么離我們更遠,應該是是被遮擋溺欧。如果新的深度值小,那么離我們更近芥牌,我們應該先看到他聂使,這個時候深度緩沖區(qū)儲存小的深度值,并且顏色緩沖區(qū)也將進行對應的更新弃理。比較深度值的這整個過程屎蜓,就叫深度測試。

  • 為什么需要深度緩沖區(qū)?

在不使用深度測試的時候辆苔,如果我們先繪制一個距離比較近的物體扼劈,再繪制距離較遠的物體,則距離遠的位圖因為后繪制荐吵,會把距離近的物體覆蓋掉捍靠,有了深度緩沖區(qū)后, 繪制物體的順序就不那么重 要的榨婆, 實際上良风,只要存在深度緩沖區(qū)闷供,OpenGL 都會把像素的深度值寫?到緩沖區(qū)中. 除?調(diào)?glDepthMask(GL_FALSE).來禁?寫入.

使用深度測試:
深度緩沖區(qū),一般由窗口管理系統(tǒng)GLFW創(chuàng)建.深度值一般由16位统诺、24位、32位值表示. 通常是24位.位數(shù)越高,深度精確度更好婿失。

// 1.開啟深度測試
glEnable(GL_DEPTH_TEST);
// 2.關(guān)閉深度測試
glDisable(GL_DEPTH_TEST);
// 3.指定深度測試判斷模式
glDepthFunc(GL_LESS); //GL_LESS 默認值
// 4.打開啄寡、阻斷深度緩沖區(qū)寫入,默認打開
glDepthMask(GL_TRUE); // 開啟深度緩沖區(qū)寫入
glDepthMask(GL_FALSE); // 開啟深度緩沖區(qū)寫入
指定深度測試判斷模式

拓展:開啟深度測試后懒浮,就一定不會出現(xiàn)問題了嗎识藤?
其實不然,如下圖所示稽穆,三個圖形在深度值相等的情況下赶撰,深度測試無法判斷深度值,會導致無法預測的問題。會造成下面2個畫面交替出現(xiàn)的問題绒疗,這個問題叫 ZFighting 閃爍問題

ZFighting隨即閃爍

那么如何解決ZFighting閃爍問題呢?

啟用Polygon Offset(多邊形偏移)吓蘑,在執(zhí)行深度測試之前,細微的增加深度值溃蔫,使得兩個重疊的圖形之間有細微的差異
//開啟多邊形偏移 glEnable(GL_POLYGON_OFFSET_FILL);
//關(guān)閉多邊形偏移 glDisable(GL_POLYGON_OFFSET_FILL);

指定偏移量琳猫,負值,將使得z值距離我們更更近统刮,?而正值,將使得z值距離我們更更遠侥蒙。

提示: 如何避免ZFighting閃爍問題?

  • 不要將兩個物體靠的太近鞭衩,避免渲染時三?形疊在?一起。這種?方式要求對場景中物體插?一個少量的偏移论衍,那么就可能避免ZFighting現(xiàn)象。例例如上面的?方體和平?面問題中钉凌,將平?下移0.001f就可以解決這個問題,當然手動去插入這個小的偏移是要付出代價的.
  • 盡可能將近裁剪?面設置得離觀察者遠一些捂人。上面我們看到,在近裁剪平?附近酸纲,深度的精確度是很?的瑟匆,因此盡可能讓近裁剪面遠一些的話,會使整個裁剪范圍內(nèi)的精確度變?一些疾嗅。但是這種?方式會使?離觀察者較近的物體被裁減掉冕象,因此需要調(diào)試好裁剪?面參數(shù)。
  • 使?更高位數(shù)的深度緩沖區(qū)论悴,通常使?的深度緩沖區(qū)是24位的墓律,現(xiàn)在有?些硬件使?32位的緩沖區(qū),使精確度得到提?.

4.顏色混合(前面提到的半透明時解決方法)

我們把OpenGL 渲染時會把顏?色值存在顏?色緩存區(qū)中察纯,每個?片段的深度值也是放在深度緩沖區(qū)。當深度緩沖區(qū)被關(guān)閉時捐寥,新的顏?將簡單的覆蓋原來顏?緩存區(qū)存在的顏色值握恳,當深度緩沖區(qū)再次打開時,新的顏?片段只是當它們比原來的值更接近鄰近的裁剪平面才會替換原來的顏?片段崇裁。

  • 使用顏色混合:
    glEnable(GL_BlEND);
    glDisable(GL_BlEND)

?標顏?:已經(jīng)存儲在顏色緩存區(qū)的顏色值
源顏色:作為當前渲染命令結(jié)果進?顏色緩存區(qū)的顏?值
當混合功能被啟動時束昵,源顏?和目標顏色的組合方式是混合方程式控制的。在默認情況
下巴比,混合?方程式如下所示:
Cf = (Cs * S) + (Cd * D)
Cf :最終計算參數(shù)的顏?
Cs : 源顏?
Cd :目標顏?
S:源混合因子
D:?標混合因子

  • 設置混合因?子礁遵,需要?用到glBlendFun函數(shù)
    glBlendFunc(GLenum S,GLenum D);
    S:源混合因?
    D:目標混合因?


    混合因子
  • 表中R、G政勃、B兼砖、A 分別代表 紅、綠懒叛、藍耽梅、alpha。
  • 表中下標S、D洪己,分別代表源、目標
  • 表中C 代表常量顏色(默認黑色)
    調(diào)用方法:
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

顏色混合總結(jié):

最終顏色是以原先的紅色(?標顏?)與后來的藍色(源顏色)進行組合逝钥。源顏色的alpha值越高,添加的藍色顏色成分越高持际,?標顏色所保留的成分就會越少哗咆。 混合函數(shù)經(jīng)常用于實現(xiàn)在其他?些不不透明的物體前面繪制一個透明物體的效果。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市年碘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌埃难,老刑警劉巖涤久,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拴竹,死亡現(xiàn)場離奇詭異,居然都是意外死亡栓拜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來啦鸣,“玉大人,你說我怎么就攤上這事香拉≈锌瘢” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵盛险,是天一觀的道長。 經(jīng)常有香客問我换帜,道長鹤啡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任跳座,我火速辦了婚禮泣矛,結(jié)果婚禮上您朽,老公的妹妹穿的比我還像新娘。我一直安慰自己哗总,他們只是感情好,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著涮母,像睡著了一般。 火紅的嫁衣襯著肌膚如雪沪蓬。 梳的紋絲不亂的頭發(fā)上来候,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天营搅,我揣著相機與錄音,去河邊找鬼转质。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的鸡挠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼彭沼,長吁一口氣:“原來是場噩夢啊……” “哼备埃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起于毙,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤辅搬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后介蛉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體溶褪,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡猿妈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了毁葱。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贰剥。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡蚌成,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出担忧,到底是詐尸還是另有隱情,我是刑警寧澤最欠,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布芝硬,位于F島的核電站,受9級特大地震影響拌阴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜陪拘,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一纤壁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧摄乒,春花似錦悠反、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽茵臭。三九已至舅世,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缨硝,已是汗流浹背罢低。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留宜岛,地道東北人功舀。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓辟汰,卻偏偏與公主長得像阱佛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子瘫絮,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容