Shader 學(xué)習(xí)之路-渲染隊(duì)列、Zwrite靠瞎、ZTest(十)

第一篇

【顏色緩沖區(qū)】

顏色緩沖區(qū)(COLOR_BUFFER)就是幀緩沖區(qū)(FRAME_BUFFER),你需要渲染的場景最終每一個(gè)像素都要寫入該緩沖區(qū),然后由它在渲染到屏幕上顯示.

【深度緩沖區(qū)】

深度緩沖區(qū)(DEPTH_BUFFER)與幀緩沖區(qū)對應(yīng),用于記錄上面每個(gè)像素的深度值,通過深度緩沖區(qū),我們可以進(jìn)行深度測試,從而確定像素的遮擋關(guān)系,保證渲染正確.

【模板緩沖區(qū)】

模版緩沖(STENCIL_BUFFER)與深度緩沖大小相同,通過設(shè)置模版緩沖每個(gè)像素的值,我們可以指定在渲染的時(shí)候只渲染某些像素,從而可以達(dá)到一些特殊的效果.

深度緩沖區(qū)的作用就是區(qū)分顏色所在的層次,防止把被遮擋住的顏色顯示出來。

當(dāng)一個(gè)像素第二次被繪制時(shí)– 例如當(dāng)一個(gè)物體在另一個(gè)物體之后被繪制- 深度緩沖要么保留前面的深度值乏盐,要么使用第二個(gè)像素的深度值替換當(dāng)前深度值佳窑。那個(gè)深度保留哪個(gè)深度拋棄取決于你選擇的深度函數(shù)。例如父能,如果當(dāng)前深度函數(shù)是CompareFunction.LessEqual時(shí)神凑,只有小于等于當(dāng)前深度值的值才會被保留,而大于當(dāng)前深度值的值會被拋棄法竞。這叫做深度測試耙厚,每次繪制像素時(shí)都會進(jìn)行深度測試。當(dāng)對一個(gè)像素進(jìn)行深度測試時(shí)岔霸,它的顏色會被寫入渲染目標(biāo)薛躬,而深度被寫入深度緩沖

深度緩沖區(qū)原理以及為什么要用它

----------------參考資料《OpenGL編程指南》

1.在開始介紹深度緩存之前,先了解一下隱藏表面消除呆细。隱藏表面消除(hidden-surface removal)就是消除實(shí)心物體被其他物體所遮擋的那部分型宝。實(shí)現(xiàn)隱藏表面消除最簡單方法就是使用深度緩沖區(qū)(又叫Z緩沖區(qū))。

2.深度緩沖區(qū)原理深度緩沖區(qū)原理就是把一個(gè)距離觀察平面(近裁剪面)的深度值(或距離)與窗口中的每個(gè)像素相關(guān)聯(lián)絮爷。首先趴酣,使用glClear(GL_DEPTH_BUFFER_BIT),把所有像素的深度值設(shè)置為最大值(一般是遠(yuǎn)裁剪面)。然后坑夯,在場景中以任意次序繪制所有物體岖寞。硬件或者軟件所執(zhí)行的圖形計(jì)算把每一個(gè)繪制表面轉(zhuǎn)換為窗口上一些像素的集合,此時(shí)并不考慮是否被其他物體遮擋柜蜈。其次仗谆,OpenGL會計(jì)算這些表面和觀察平面的距離。如果啟用了深度緩沖區(qū)淑履,在繪制每個(gè)像素之前隶垮,OpenGL會把它的深度值和已經(jīng)存儲在這個(gè)像素的深度值進(jìn)行比較。新像素深度值<原先像素深度值秘噪,則新像素值會取代原先的狸吞;反之,新像素值被遮擋指煎,他顏色值和深度將被丟棄蹋偏。為了啟動深度緩沖區(qū),必須先啟動它贯要,即glEnable(GL_DEPTH_TEST)暖侨。每次繪制場景之前,需要先清除深度緩沖區(qū)崇渗,即glClear(GL_DEPTH_BUFFER_BIT),然后以任意次序繪制場景中的物體。

第二篇

openGL里常出現(xiàn)深度測試宅广,一直不清楚葫掉。今天就來弄清楚。


1跟狱、深度

? ???所謂深度俭厚,就是在openGL坐標(biāo)系中,像素點(diǎn)Z坐標(biāo)距離攝像機(jī)的距離驶臊。攝像機(jī)可能放在坐標(biāo)系的任何位置挪挤,那么,就不能簡單的說Z數(shù)值越大或越小关翎,就是越靠近攝像機(jī)扛门。

2、深度緩沖區(qū)

????? 深度緩沖區(qū)原理就是把一個(gè)距離觀察平面(近裁剪面)的深度值(或距離)與窗口中的每個(gè)像素相關(guān)聯(lián)纵寝。

????? 首先论寨,使用glClear(GL_DEPTH_BUFFER_BIT),把所有像素的深度值設(shè)置為最大值(一般是遠(yuǎn)裁剪面)。

????? 然后爽茴,在場景中以任意次序繪制所有物體葬凳。硬件或者軟件所執(zhí)行的圖形計(jì)算把每一個(gè)繪制表面轉(zhuǎn)換為窗口上一些像素的集合,此時(shí)并不考慮是否被其他物體遮擋室奏。

????? 其次火焰,OpenGL會計(jì)算這些表面和觀察平面的距離。如果啟用了深度緩沖區(qū)胧沫,在繪制每個(gè)像素之前昌简,OpenGL會把它的深度值和已經(jīng)存儲在這個(gè)像素的深度值進(jìn)行比較。新像素深度值<原先像素深度值琳袄,則新像素值會取代原先的江场;反之,新像素值被遮擋窖逗,他顏色值和深度將被丟棄址否。

????? 為了啟動深度緩沖區(qū),必須先啟動它碎紊,即glEnable(GL_DEPTH_TEST)佑附。每次繪制場景之前,需要先清除深度緩沖區(qū)仗考,即glClear(GL_DEPTH_BUFFER_BIT)音同,然后以任意次序繪制場景中的物體。

? ??? 數(shù)學(xué)基礎(chǔ):

? ??? 待渲染的照相機(jī)空間中的深度經(jīng)常定義為近距?near?到遠(yuǎn)距?far?之間的?z?值秃嗜,Z坐標(biāo)和X权均、Y坐標(biāo)一樣顿膨。在變換、裁減和透視除法后叽赊,Z的范圍為-1.0~1.0恋沃。DepthRange映射指定Z坐標(biāo)的變換,這與用于將XY映射到窗口坐標(biāo)的視口變換類似必指,在透視變換之后囊咏,得到新的?z'?值:

?????其中??是照相機(jī)空間的值,它有時(shí)候也表示為?w?或者?w'塔橡。

????? 結(jié)果?z'?是在?-1??1?之間歸一化之后的值梅割,其中近距?near?平面位于?-1?處,遠(yuǎn)距?far?平面位于?1?處葛家。在這個(gè)范圍之外的相應(yīng)點(diǎn)在視圖體之外户辞,不需要進(jìn)行渲染。

?????為了實(shí)現(xiàn)深度緩沖惦银,在整個(gè)屏幕空間上的對當(dāng)前多邊形頂點(diǎn)之間進(jìn)行插值來計(jì)算?z'?的值咆课,通常這些中間數(shù)值在深度緩沖區(qū)中用定點(diǎn)數(shù)格式保存。距離近距?near?平面越近扯俱,z'?值越密书蚪;距離越遠(yuǎn),z'?值越稀迅栅。這樣距離照相機(jī)越近精度越高殊校。near?平面距離照相機(jī)越近,則遠(yuǎn)距離位置的精度越低读存。near?平面距離照相機(jī)太近是在遠(yuǎn)距離物體產(chǎn)生人為誤差的一個(gè)常見因素为流。

? ?3、深度測試

? ? ? ?OpenGL中的深度測試是采用深度緩存器算法让簿,消除場景中的不可見面敬察。在默認(rèn)情況下,深度緩存中深度值的范圍在0.01.0之間尔当,這個(gè)范圍值可以通過函數(shù):

??????? glDepthRange (nearNormDepth, farNormalDepth);

? ? ? ?將深度值的范圍變?yōu)?b>nearNormDepth到farNormalDepth之間莲祸。這里nearNormDepthfarNormalDepth可以取0.01.0范圍內(nèi)的任意值,甚至可以讓nearNormDepth > farNormalDepth椭迎。這樣锐帜,通過glDepthRange函數(shù)可以在透視投影有限觀察空間中的任意區(qū)域進(jìn)行深度測試。

? ? ? ?另一個(gè)非常有用的函數(shù)是:

??????? glClearDepth (maxDepth);

? ? ? ?參數(shù)maxDepth可以是0.01.0范圍內(nèi)的任意值畜号。glClearDepthmaxDepth對深度緩存進(jìn)行初始化缴阎,而默認(rèn)情況下,深度緩存用1.0進(jìn)行初始化简软。由于在進(jìn)行深度測試中蛮拔,大于深度緩存初始值的多邊形都不會被繪制述暂,因此glClearDepth函數(shù)可以用來加速深度測試處理。這里需要注意的是指定了深度緩存的初始化值之后语泽,應(yīng)調(diào)用:

??????? glClear(GL_DEPTH_BUFFER_BIT); ??完成深度緩存的初始化贸典。

? ? ? ?在深度測試中视卢,默認(rèn)情況是將需要繪制的新像素的z值與深度緩沖區(qū)中對應(yīng)位置的z值進(jìn)行比較踱卵,如果比深度緩存中的值小,那么用新像素的顏色值更新幀緩存中對應(yīng)像素的顏色值据过。這種比較測試的方式可以通過函數(shù):

??????? glDepthFunc(func);

進(jìn)行修改惋砂。其中參數(shù)func的值可以為GL_NEVER(沒有處理)、GL_ALWAYS(處理所有)绳锅、GL_LESS(小于)西饵、GL_LEQUAL(小于等于)、GL_EQUAL(等于)鳞芙、GL_GEQUAL(大于等于)眷柔、GL_GREATER(大于)或GL_NOTEQUAL(不等于),其中默認(rèn)值是GL_LESS原朝。這些測試可以在各種應(yīng)用中減少深度緩存處理的的計(jì)算驯嘱。

那么,重點(diǎn)來了:

1喳坠、當(dāng)ZWriteOn時(shí)鞠评,ZTest通過時(shí),該像素的深度才能成功寫入深度緩存壕鹉,同時(shí)因?yàn)?b>ZTest通過了剃幌,該像素的顏色值也會寫入顏色緩存。

2晾浴、當(dāng)ZWriteOn時(shí)负乡,ZTest不通過時(shí),該像素的深度不能成功寫入深度緩存脊凰,同時(shí)因?yàn)?b>ZTest不通過抖棘,該像素的顏色值不會寫入顏色緩存。

3笙各、當(dāng)ZWriteOff時(shí)钉答,ZTest通過時(shí),該像素的深度不能成功寫入深度緩存杈抢,同時(shí)因?yàn)?b>ZTest通過了数尿,該像素的顏色值會寫入顏色緩存。

4惶楼、當(dāng)ZWriteOff時(shí)右蹦,ZTest不通過時(shí)诊杆,該像素的深度不能成功寫入深度緩存,同時(shí)因?yàn)?b>ZTest不通過何陆,該像素的顏色值不會寫入顏色緩存晨汹。

可以看到,像素的深度能否成功寫入深度緩存贷盲,條件是ZWriteOn淘这,ZTest通過;

寫入深度緩存的作用就是為ZTest的比較做準(zhǔn)備巩剖。

因?yàn)閆Write默認(rèn)值為On铝穷,ZTest默認(rèn)值為LEqual,所以這很好地解釋了為什么在unity中佳魔,距離相機(jī)近的東西會阻擋住距離相機(jī)遠(yuǎn)的東西曙聂。如果我們先繪制一個(gè)距離較近的物體,再繪制距離較遠(yuǎn)的物體鞠鲜,則距離遠(yuǎn)的物體因?yàn)楹罄L制宁脊,會把距離近的物體覆蓋掉,這時(shí)我們可以通過修改ZWrite和ZTest來改變物體的遮擋關(guān)系贤姆!

測試環(huán)境(藍(lán)色方塊距離相機(jī)較近榆苞,注意這個(gè)不是Game視圖):

測試的Shader代碼(兩個(gè)方塊的shader代碼起始都是一樣的,測試時(shí)修改的是測試區(qū)里的代碼):

Shader "Custom/ZTest" {

Properties {

_MainTex("Base(RGB)",2D)= "white" {}

}

SubShader {

Tags { "RenderType"="Opaque" }

LOD 200

/////////////////////////////////////////測試區(qū)

Tags{ "Queue" = "Geometry" }

? ? //ZWrite Off

? //ZTest Off

/////////////////////////////////////////測試區(qū)

CGPROGRAM

#pragma surface surf Lambert


sampler2D _MainTex;


struct Input {

float2 uv_MainTex;

};


void surf(Input IN,inout SurfaceOutput o){

half4 c = tex2D(_MainTex,IN.uv_MainTex);

o.Albedo = c.rgb;

o.Alpha = c.a;

}

ENDCG

}?

FallBack "Diffuse"

}

渲染順序:先藍(lán)色方塊再白色方塊(以下簡稱藍(lán)庐氮,白)

注意ZWrite默認(rèn)值為On语稠,ZTest默認(rèn)值為LEqual,沒有渲染物體時(shí)弄砍,深度緩存中的深度可以理解為無限大

1.

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

Tags{ "Queue" = "Geometry+200" }

? ? ? ? ZWrite Off

//ZTest Off

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

/////////////////////////////////////////白色方塊測試區(qū)

Tags{ "Queue" = "Geometry+300" }

//ZWrite Off

? ? ? ? //ZTest Off

/////////////////////////////////////////白色方塊測試區(qū)

結(jié)果:白在前面

分析:藍(lán)沒有將像素寫進(jìn)深度緩存中仙畦,ZTest通過了,顏色緩存中存放了藍(lán)的顏色值

白將像素寫進(jìn)深度緩存中音婶,ZTest通過了慨畸,顏色緩存的值變?yōu)榘椎模燥@示白

2.

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

Tags{ "Queue" = "Geometry+200" }

? ? ? ? //ZWrite Off

//ZTest Off

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

/////////////////////////////////////////白色方塊測試區(qū)

Tags{ "Queue" = "Geometry+300" }

//ZWrite Off

? ? ? ? //ZTest Off

/////////////////////////////////////////白色方塊測試區(qū)

結(jié)果:藍(lán)在前面

分析:藍(lán)將像素寫進(jìn)深度緩存中衣式,ZTest通過了寸士,顏色緩存中存放了藍(lán)的顏色值

而白的像素深度大于藍(lán)的,既沒有成功將像素寫進(jìn)深度緩存碴卧,同時(shí)ZTest不通過弱卡,像素被舍棄,所以顯示藍(lán)

3.

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

Tags{ "Queue" = "Geometry+200" }

? ? ? ? ZWrite Off

ZTest Off

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

/////////////////////////////////////////白色方塊測試區(qū)

Tags{ "Queue" = "Geometry+300" }

//ZWrite Off

? ? ? ? //ZTest Off

/////////////////////////////////////////白色方塊測試區(qū)

結(jié)果:白在前面

分析:藍(lán)沒有將像素寫進(jìn)深度緩存中住册,ZTest通過了婶博,顏色緩存中存放了藍(lán)的顏色值

白將像素寫進(jìn)深度緩存中,ZTest通過了荧飞,顏色緩存中存放為白的顏色值

4.

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

Tags{ "Queue" = "Geometry+200" }

? ? //ZWrite Off

//ZTest Off

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

/////////////////////////////////////////白色方塊測試區(qū)

Tags{ "Queue" = "Geometry+300" }

//ZWrite Off

? ? ZTest Off

/////////////////////////////////////////白色方塊測試區(qū)

結(jié)果:白在前面

分析:藍(lán)將像素寫進(jìn)了深度緩存中

白將像素寫進(jìn)了深度緩存中凡人,ZTest通過了名党,白將顏色緩存中的藍(lán)的像素顏色值替換了。

5.

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

Tags{ "Queue" = "Geometry+200" }

? ? ? ? //ZWrite Off

//ZTest Off

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

/////////////////////////////////////////白色方塊測試區(qū)

Tags{ "Queue" = "Geometry+300" }

ZWrite Off

? ? ? ? ZTest Off

/////////////////////////////////////////白色方塊測試區(qū)

結(jié)果:白在前面

分析:藍(lán)將像素寫進(jìn)了深度緩存中

白沒能將像素寫進(jìn)了深度緩存中(ZWrite為off)挠轴,但ZTest通過了传睹,此時(shí)顏色緩存的值變?yōu)榘椎模巧疃染彺娴闹凳撬{(lán)的

6.

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

Tags{ "Queue" = "Geometry+200" }

? ? ? ? //ZWrite Off

ZTest Off

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

/////////////////////////////////////////白色方塊測試區(qū)

Tags{ "Queue" = "Geometry+300" }

//ZWrite Off

? ? ? ? ZTest Off

/////////////////////////////////////////白色方塊測試區(qū)

結(jié)果:白在前面

分析:藍(lán)將像素寫進(jìn)了深度緩存中

白將像素寫進(jìn)了深度緩存中岸晦,ZTest通過了欧啤,此時(shí)顏色緩存的值變?yōu)榘椎?/p>

7.

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

Tags{ "Queue" = "Geometry+200" }

? ? ? ? ZWrite Off

//ZTest Off

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

/////////////////////////////////////////白色方塊測試區(qū)

Tags{ "Queue" = "Geometry+300" }

ZWrite Off

? ? ? ? //ZTest Off

/////////////////////////////////////////白色方塊測試區(qū)

結(jié)果:白在前面

分析:白、藍(lán)都沒有將像素寫入深度緩存中委煤,所以深度緩存中的深度值為無窮大堂油,最后因?yàn)榘字衂Test默認(rèn)值的原因,所以顯示白

8.

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

Tags{ "Queue" = "Geometry+200" }

ZWrite Off

ZTest Off

/////////////////////////////////////////藍(lán)色方塊測試區(qū)

/////////////////////////////////////////白色方塊測試區(qū)

Tags{ "Queue" = "Geometry+300" }

ZWrite Off

ZTest Off

/////////////////////////////////////////白色方塊測試區(qū)

結(jié)果:白在前面

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末碧绞,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子吱窝,更是在濱河造成了極大的恐慌讥邻,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件院峡,死亡現(xiàn)場離奇詭異兴使,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)照激,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進(jìn)店門发魄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人俩垃,你說我怎么就攤上這事励幼。” “怎么了口柳?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵苹粟,是天一觀的道長。 經(jīng)常有香客問我跃闹,道長嵌削,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任望艺,我火速辦了婚禮苛秕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘找默。我一直安慰自己艇劫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布啡莉。 她就那樣靜靜地躺著港准,像睡著了一般旨剥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上浅缸,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天轨帜,我揣著相機(jī)與錄音,去河邊找鬼衩椒。 笑死蚌父,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的毛萌。 我是一名探鬼主播苟弛,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼阁将!你這毒婦竟也來了膏秫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤做盅,失蹤者是張志新(化名)和其女友劉穎缤削,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吹榴,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡亭敢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了图筹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帅刀。...
    茶點(diǎn)故事閱讀 38,683評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖远剩,靈堂內(nèi)的尸體忽然破棺而出扣溺,到底是詐尸還是另有隱情,我是刑警寧澤民宿,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布娇妓,位于F島的核電站,受9級特大地震影響活鹰,放射性物質(zhì)發(fā)生泄漏哈恰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一志群、第九天 我趴在偏房一處隱蔽的房頂上張望着绷。 院中可真熱鬧,春花似錦锌云、人聲如沸荠医。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彬向。三九已至兼贡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間娃胆,已是汗流浹背遍希。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留里烦,地道東北人凿蒜。 一個(gè)月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像胁黑,于是被迫代替她去往敵國和親废封。 傳聞我的和親對象是個(gè)殘疾皇子先改,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,566評論 2 349

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