<轉(zhuǎn)>我也忘了轉(zhuǎn)自哪里,抱歉,感謝原作者
(1)什么是深度?
?深度其實就是該像素點在3d世界中距離攝像機的距離。離攝像機越遠(yuǎn),則深度值(Z值)越大。
(2)什么是深度緩存?
深度緩存中存儲著準(zhǔn)備要繪制在屏幕上的像素點的深度值。如果啟用了深度緩沖區(qū),在繪制每個像素之前,OpenGL會把該像素的深度值和深度緩存的深度值進(jìn)行比較。如果新像素深度值<深度緩存深度值,則新像素值會取代原先的;反之,新像素值被遮擋,其顏色值和深度將被丟棄。(深度主要起的是比較的作用)
(3)什么是深度測試?
在深度測試中,默認(rèn)情況是將要繪制的新像素的z值與深度緩沖區(qū)中對應(yīng)位置的z值進(jìn)行比較,如果比深度緩存中的值小,那么用新像素的顏色值更新深度緩存中對應(yīng)像素的顏色值。
(4)為什么需要深度?
在不使用深度測試的時候,如果我們先繪制一個距離較近的物體,再繪制距離較遠(yuǎn)的物體,則距離遠(yuǎn)的物體因為后繪制,會把距離近的物體覆蓋掉,這樣的效果并不是我們所希望的。而有了深度緩沖以后,繪制物體的順序就不那么重要了,都能按照遠(yuǎn)近(Z值)正常顯示,這很關(guān)鍵。
那么,在unity中,如果知道了渲染隊列,ZWrite,ZTest,如何確定哪個物體先顯示呢?
首先,unity先將渲染隊列中較前的進(jìn)行渲染,然后再執(zhí)行ZWrite,ZTest
ZWrite可以取的值為:On/Off,默認(rèn)值為On,代表是否要將像素的深度寫入深度緩存中(同時還要看ZTest是否通過)。
ZTest可以取的值為:Greater/GEqual/Less/LEqual/Equal/NotEqual/Always/Never/Off,默認(rèn)值為LEqual,代表通過比較深度來更改顏色緩存的值。例如當(dāng)取默認(rèn)值的情況下,如果將要繪制的新像素的z值小于等于深度緩存中的值,則將用新像素的顏色值更新深度緩存中對應(yīng)像素的顏色值。需要注意的是,當(dāng)ZTest取值為Off時,表示的是關(guān)閉深度測試,等價于取值為Always,而不是Never!Always指的是直接將當(dāng)前像素顏色(不是深度)寫進(jìn)顏色緩沖區(qū)中;而Never指的是不要將當(dāng)前像素顏色寫進(jìn)顏色緩沖區(qū)中,相當(dāng)于消失。
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
那么,重點來了:
1.當(dāng)ZWrite為On時,ZTest通過時,該像素的深度才能成功寫入深度緩存,同時因為ZTest通過了,該像素的顏色值也會寫入顏色緩存。
2.當(dāng)ZWrite為On時,ZTest不通過時,該像素的深度不能成功寫入深度緩存,同時因為ZTest不通過,該像素的顏色值不會寫入顏色緩存。
3.當(dāng)ZWrite為Off時,ZTest通過時,該像素的深度不能成功寫入深度緩存,同時因為ZTest通過了,該像素的顏色值會寫入顏色緩存。
4.當(dāng)ZWrite為Off時,ZTest不通過時,該像素的深度不能成功寫入深度緩存,同時因為ZTest不通過,該像素的顏色值不會寫入顏色緩存。
可以看到,像素的深度能否成功寫入深度緩存,條件是ZWrite為On,ZTest通過;
寫入深度緩存的作用就是為ZTest的比較做準(zhǔn)備。
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
因為ZWrite默認(rèn)值為On,ZTest默認(rèn)值為LEqual,所以這很好地解釋了為什么在unity中,距離相機近的東西會阻擋住距離相機遠(yuǎn)的東西。如果我們先繪制一個距離較近的物體,再繪制距離較遠(yuǎn)的物體,則距離遠(yuǎn)的物體因為后繪制,會把距離近的物體覆蓋掉,這時我們可以通過修改ZWrite和ZTest來改變物體的遮擋關(guān)系!
測試環(huán)境(藍(lán)色方塊距離相機較近,注意這個不是Game視圖):
測試的Shader代碼(兩個方塊的shader代碼起始都是一樣的,測試時修改的是測試區(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,沒有渲染物體時,深度緩存中的深度可以理解為無限大
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)深度緩存,同時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通過了,此時顏色緩存的值變?yōu)榘椎模巧疃染彺娴闹凳撬{(lán)的
6.
/////////////////////////////////////////藍(lán)色方塊測試區(qū)??
????????Tags{?"Queue"?=?"Geometry+200"?}??
????????//ZWrite?Off??
????????ZTest?Off??
/////////////////////////////////////////藍(lán)色方塊測試區(qū)??
結(jié)果:白在前面
分析:藍(lán)將像素寫進(jìn)了深度緩存中
白將像素寫進(jìn)了深度緩存中,ZTest通過了,此時顏色緩存的值變?yōu)榘椎?/p>
7.
結(jié)果:白在前面
分析:白、藍(lán)都沒有將像素寫入深度緩存中,所以深度緩存中的深度值為無窮大,最后因為白中ZTest默認(rèn)值的原因,所以顯示白
8.
結(jié)果:白在前面
分析:與7類似