第十節(jié)—深度問題

本文為L_Ares個人寫作武学,包括圖片皆為個人親自操作火窒,以任何形式轉(zhuǎn)載請表明原文出處熏矿。

第八褪储、第九節(jié)的問題還沒有完全解決鲤竹,那么這里就涉及到了深度的問題辛藻。本節(jié)將主要學習深度吱肌。

一氮墨、深度的概念

首先要明確的知道,OpenGL中深度到底是什么東西粒褒?

深度就是該像素點在3D世界中诚镰,距離攝像機的距離清笨,也就是常說的Z值抠艾。

在OpenGL中,有頂點緩沖區(qū)齐苛,有顏色緩沖區(qū)凹蜂,之前的代碼也都有涉及到汰瘫,還有一個經(jīng)常寫混弥,但是沒有說明含義的緩沖區(qū)——深度緩沖區(qū)剑逃。

什么是深度緩沖區(qū)蛹磺?

深度緩沖區(qū)是一塊內(nèi)存區(qū)域,它專門的存儲每個像素點(繪制在屏幕上的)深度值俗或。深度值越大(Z值越大)辛慰,那么該點距離攝像機就越遠帅腌。

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

因為會出現(xiàn)像素點重復繪制溺职,或者覆蓋的問題浪耘。在不使用深度測試的時候七冲,如果我們先繪制一個距離攝像機更近一點的物體癞埠,再繪制一個距離攝像機較遠的物體苗踪,因為距離遠的物體是后繪制的通铲,就會把先繪制的朋截,距離攝像機更近的物體覆蓋遮擋掉部服。有了深度緩沖區(qū)后廓八,距離攝像機的遠近就不那么的重要剧蹂。

事實上,只要存在深度緩沖區(qū)其爵,OpenGL都會把像素的深度值寫入到深度緩沖區(qū)中窄驹,除非調(diào)用glDepthMask(GL_FALSE)在禁止寫入

什么是深度測試抗斤?

深度緩沖區(qū)(DepthBuffer)和顏色緩沖區(qū)(ColorBuffer)是具有聯(lián)系的龙宏。當我們需要繪制一個物體表面的時候辆影,OpenGL會把表面對應的像素點的深度值和深度緩沖區(qū)中的深度值進行大小比較蛙讥,如果需要繪制的表面的深度值大于深度緩沖區(qū)中存儲的深度值,則會丟棄大于深度緩沖區(qū)深度值的這部分的繪制。而沒有大于的這部分則會將他們的像素值和深度值替換掉原有的深度緩沖區(qū)和顏色緩沖區(qū)的存儲值闻妓,這個過程也就是深度測試。

這里有一點很重要@绻Α!限嫌!深度緩沖區(qū)存儲的是像素點的深度,是以像素點未單位的稚叹,而不是你所繪制的圖形的z值,因為你可以繪制很多很多的圖形季率,圖形是存在重疊的情況的鞭光,那么重疊的地方,用的都是相同的像素點啡省,保存的是距離觀察者最近的圖形的z值轉(zhuǎn)換成的像素點的深度,而不是圖形的z值。

關(guān)于深度值到底是怎么計算的徐鹤,會開辟延展節(jié)單獨做學習,內(nèi)容比較多劲赠。

二估蹄、使用深度測試

深度緩沖區(qū)最铁,一般由窗口管理系統(tǒng)GLFW創(chuàng)建,深度值一般由16,24嗤无,32位值表示,默認是24位嘉栓,位數(shù)越高,則深度精確度越好馋辈。

開啟深度測試

glEnable(GL_DEPTH_TEST)

這里要注意的是尔崔,如果開啟了深度測試烙常,則證明需要用到深度緩沖區(qū),那么在之前的代碼中,我們經(jīng)常使用的glClearColor()glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)則是必不可少的挣棕。

清除深度緩沖區(qū),其默認值為1.0词身,表示最大的深度值损敷。

深度值的范圍:(0,1)之間溯街。值越小呈昔,表示越靠近觀察者,值越大則越遠離觀察者涡相。

另外,當我們退出這個繪制界面的時候,最好把深度測試關(guān)閉掉犬缨。

深度測試判斷式

void glDepthFunc(GLenum mode)

參數(shù)選擇及含義如下圖2.1:

2.1.png
打開/阻斷深度值的寫入

void glDepthMask(GLBool value)
GL_TRUE:開啟深度緩沖區(qū)寫入迷郑。
GL_FALSE:阻斷深度緩沖區(qū)寫入。

甜甜圈代碼

現(xiàn)在我們補全之前的代碼十电,只需要在void RenderScene()中的開啟正背面剔除的下面增加下面的代碼即可首妖,因為我們要對比象踊,所以這里添加了if判斷袖外。


    if (isDepth) {
        glEnable(GL_DEPTH_TEST);
    }
    else{
        glDisable(GL_DEPTH_TEST);
    }

現(xiàn)在,這個甜甜圈終于不是破輪胎了熔酷。

但是這就沒問題了嘛躺酒?如果深度值重復了,或者說深度值都相同的話量愧,那會不會還有問題呢浑此?

三料饥、ZFighting閃爍問題

先看一下岸啡,當OpenGL無法分辨深度值大小的時候可能會產(chǎn)生的后果擂送。如圖3.1和圖3.2所示:

3.1.png
3.2.png

這就是ZFighting問題蟀拷。

為什么會出現(xiàn)ZFighting問題呢?

因為當OpenGL開啟了深度測試之后,OpenGL就不會再去繪制模型被遮擋的部分,但是由于深度值的精確度的限制,對于深度值相差非常非常小的情況下衰琐,OpenGL也無法精確的判斷他們的深度值大小掐隐,這就會導致深度測試出現(xiàn)不確定性僧凰,也就會出現(xiàn)這種交錯閃爍的情況虑啤。

如何解決ZFighting問題叉寂?

思路也不難,產(chǎn)生這個問題的原因是深度值差別太小,那么我們給他們之間人為添加一個空隙,騙過OpenGL,這就是多邊形偏移方法。

而且這個空隙都不需要由我們來計算看政,OpenGL有提供方法如下:

第一步:啟用Polygon Offset方法解決

glEnable(GL_POLYGON_OFFSET_FILL)
參數(shù)可選,主要根據(jù)光柵化的模式來選擇參數(shù):
GL_POLYGON_OFFSET_FILL 對應光柵化模式:GL_FILL
GL_POLYGON_OFFSET_POINT對應光柵化模式:GL_POINT
GL_POLYGON_OFFSET_LINE 對應光柵化模式:GL_LINE

第二步:指定偏移量

  • 通過void glPolygonOffset(GLFloat factor,GLFloat units)來指定。

  • 每個片元的深度值增加的偏移量如下:

Offset = (m * factor) + (r * units)
m:多邊形的深度的斜率的最大值,多邊形越是與近剪裁面平行,m的值也就越接近0恕出。
r:能產(chǎn)生于窗口坐標系中的可分辨的差異最小值渊抄,r是一個具體的值丧裁,是由OpenGL平臺分配的一個常量煎娇。

  • 一個大于0的Offset會把模型推到離觀察者(攝像機)更遠的位置眨猎,而小于0的Offset會把模型拉近觀察者(攝像機)

  • 一般情況下兰迫,只需要將-1.0和-1賦值給glPolygonOffset即可玲躯。

關(guān)閉偏移量

用完了記得關(guān)茅郎。

glDisable(GL_POLYGON_OFFSET_FILL)

如何預防ZFighting問題?
  • 首先就是不要把兩個物體靠的太近框仔∫ㄎ洌可以手動添加一個很小的偏移量,但是不建議离斩,因為如果繪制的物體很多银舱,本身距離又存在相差不大的情況,手動添加偏移量只可能解決這一個的問題洲脂,但是可能會造成新的問題苟耻。

  • 近剪裁面離觀察者遠一點驱闷,因為更遠的情況下,深度值的精度要求也就更高诚欠,但是這種方法可能造成離觀察者近的物體隨著距離增加而剪裁,所以重點是調(diào)試好剪裁面參數(shù)漾岳。

  • 剛才說了深度緩沖區(qū)的位數(shù)有三種轰绵,位數(shù)越高,精度越高尼荆。16左腔、24、32捅儒,默認是24液样,既然24的不行振亮,那就換32位深度緩沖區(qū)。

四鞭莽、剪裁

理解即可双炕。

關(guān)于窗口、視口撮抓、剪裁區(qū)域

先確定這三者的關(guān)系妇斤,下面我用一張圖來說明,如圖4.1所示:

4.1.png
  • 窗口
    就是項目的顯示界面

  • 視口
    窗口中用來顯示圖形的一塊區(qū)域丹拯,一般情況下和窗口內(nèi)平面等大站超。當然也是可以比窗口大或者小。
    這里要注意乖酬,超出視口的圖形部分是不予顯示的死相。
    我們可以通過glViewport(GLint x, GLint y, GLsizei width, GLsizei height)函數(shù)設置視口的x,y,w,h

  • 剪裁區(qū)域
    如圖4.1所示,可以通過void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)函數(shù)來設置咬像。
    這里的left和right是用視口矩形區(qū)域的最大和最小x坐標算撮,bottom和top也一樣,只不過用的是y坐標县昂,千萬別用窗口的肮柜。也可以指定最近和最遠的z坐標,這樣就會變成一個立體的剪裁區(qū)域倒彰。

定義

在OpenGL中提高渲染的一種方式审洞,只刷新屏幕上發(fā)生變化的部分。

OpenGL可以做到讓要發(fā)生渲染的窗口只指定一個剪裁框待讳。

原理

用于渲染時限制繪制區(qū)域芒澜,可以在屏幕上指定一個矩形區(qū)域進行繪制,其他的不更新繪制创淡。啟用剪裁測試后痴晦,不在矩形區(qū)域內(nèi)的片元被丟棄,只有在矩形區(qū)域內(nèi)的片元才有可能進入幀緩沖琳彩。

就像在屏幕上畫出來一塊矩形區(qū)誊酌,然后在矩形區(qū)域中可以進行指定內(nèi)容的繪制。

使用方法
  • 開啟剪裁測試

glEnable(GL_SCISSOR_TEST)

  • 關(guān)閉剪裁測試

glEnable(GL_SCISSOR_TEST)

  • 指定剪裁窗口

void glScissor(GLint x,GLint y,GLsizei width,GLsizei height)

x,y分別是指定的剪裁窗口的左下角的橫縱坐標值汁针。width,height就是寬高术辐,用來設置剪裁框的尺寸。

至此施无,關(guān)于深度的問題也學習完成了辉词,圓環(huán)也繪制成功了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末猾骡,一起剝皮案震驚了整個濱河市瑞躺,隨后出現(xiàn)的幾起案子敷搪,更是在濱河造成了極大的恐慌,老刑警劉巖幢哨,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赡勘,死亡現(xiàn)場離奇詭異,居然都是意外死亡捞镰,警方通過查閱死者的電腦和手機闸与,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來岸售,“玉大人践樱,你說我怎么就攤上這事⊥雇瑁” “怎么了拷邢?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長屎慢。 經(jīng)常有香客問我瞭稼,道長,這世上最難降的妖魔是什么腻惠? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任环肘,我火速辦了婚禮,結(jié)果婚禮上妖枚,老公的妹妹穿的比我還像新娘廷臼。我一直安慰自己,他們只是感情好绝页,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著寂恬,像睡著了一般续誉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上初肉,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天酷鸦,我揣著相機與錄音,去河邊找鬼牙咏。 笑死臼隔,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的妄壶。 我是一名探鬼主播摔握,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼丁寄!你這毒婦竟也來了氨淌?” 一聲冷哼從身側(cè)響起泊愧,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盛正,沒想到半個月后删咱,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡豪筝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年痰滋,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片续崖。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡敲街,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出袜刷,到底是詐尸還是另有隱情聪富,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布著蟹,位于F島的核電站墩蔓,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏萧豆。R本人自食惡果不足惜奸披,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望涮雷。 院中可真熱鬧阵面,春花似錦、人聲如沸洪鸭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽览爵。三九已至置鼻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蜓竹,已是汗流浹背箕母。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留俱济,地道東北人嘶是。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像蛛碌,于是被迫代替她去往敵國和親聂喇。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355