簡(jiǎn)介
在渲染階段革砸,引擎所做的工作是把所有場(chǎng)景中的對(duì)象按照一定的策略(順序)進(jìn)行渲染。最早的是畫(huà)家算法糯累,顧名思義算利,就是像畫(huà)家畫(huà)畫(huà)一樣,先畫(huà)后面的物體泳姐,如果前面還有物體效拭,那么就用前面的物體把物體覆蓋掉,不過(guò)這種方式由于排序是針對(duì)物體來(lái)排序的胖秒,而物體之間也可能有重疊缎患,所以效果并不好。所以目前更加常用的方式是z-buffer算法阎肝,類似顏色緩沖區(qū)緩沖顏色挤渔,z-buffer中存儲(chǔ)的是當(dāng)前的深度信息,對(duì)于每個(gè)像素存儲(chǔ)一個(gè)深度值风题,這樣判导,我們屏幕上顯示的每個(gè)像素點(diǎn)都會(huì)進(jìn)行深度排序,就可以保證繪制的遮擋關(guān)系是正確的沛硅。而控制z-buffer就是通過(guò)ZTest眼刃,和ZWrite來(lái)進(jìn)行。但是有時(shí)候需要更加精準(zhǔn)的控制不同類型的對(duì)象的渲染順序稽鞭,所以就有了渲染隊(duì)列鸟整。今天就來(lái)學(xué)習(xí)一下渲染隊(duì)列,ZTest朦蕴,ZWrite的基本使用以及分析一下Unity為了Early-Z所做的一些優(yōu)化篮条。
Unity中的幾種渲染隊(duì)列
首先看一下Unity中的幾種內(nèi)置的渲染隊(duì)列,按照渲染順序吩抓,從先到后進(jìn)行排序涉茧,隊(duì)列數(shù)越小的,越先渲染疹娶,隊(duì)列數(shù)越大的伴栓,越后渲染。
Background(1000) 最早被渲染的物體的隊(duì)列雨饺。
Geometry (2000) 不透明物體的渲染隊(duì)列钳垮。大多數(shù)物體都應(yīng)該使用該隊(duì)列進(jìn)行渲染,也是Unity Shader中默認(rèn)的渲染隊(duì)列额港。
AlphaTest (2450) 有透明通道饺窿,需要進(jìn)行Alpha Test的物體的隊(duì)列,比在Geomerty中更有效移斩。
Transparent(3000) 半透物體的渲染隊(duì)列肚医。一般是不寫(xiě)深度的物體绢馍,Alpha Blend等的在該隊(duì)列渲染。
Overlay (4000) 最后被渲染的物體的隊(duì)列肠套,一般是覆蓋效果舰涌,比如鏡頭光暈,屏幕貼片之類的你稚。
Unity中設(shè)置渲染隊(duì)列也很簡(jiǎn)單瓷耙,我們不需要手動(dòng)創(chuàng)建,也不需要寫(xiě)任何腳本入宦,只需要在shader中增加一個(gè)Tag就可以了哺徊,當(dāng)然,如果不加乾闰,那么就是默認(rèn)的渲染隊(duì)列Geometry落追。比如我們需要我們的物體在Transparent這個(gè)渲染隊(duì)列中進(jìn)行渲染的話,就可以這樣寫(xiě):
Tags { "Queue" = "Transparent"}
我們可以直接在shader的Inspector面板上看到shader的渲染隊(duì)列:
另外涯肩,我們?cè)趯?xiě)shader的時(shí)候還經(jīng)常有個(gè)Tag叫RenderType轿钠,不過(guò)這個(gè)沒(méi)有Render Queue那么常用,這里順便記錄一下:
Opaque: 用于大多數(shù)著色器(法線著色器病苗、自發(fā)光著色器疗垛、反射著色器以及地形的著色器)。
Transparent:用于半透明著色器(透明著色器硫朦、粒子著色器贷腕、字體著色器、地形額外通道的著色器)咬展。
TransparentCutout: 蒙皮透明著色器(Transparent Cutout泽裳,兩個(gè)通道的植被著色器)。
Background: 天空盒著色器破婆。
Overlay: GUITexture涮总,鏡頭光暈,屏幕閃光等效果使用的著色器祷舀。
TreeOpaque: 地形引擎中的樹(shù)皮瀑梗。
TreeTransparentCutout: 地形引擎中的樹(shù)葉。
TreeBillboard: 地形引擎中的廣告牌樹(shù)裳扯。
Grass: 地形引擎中的草抛丽。
GrassBillboard: 地形引擎何中的廣告牌草。
相同渲染隊(duì)列中不透明物體的渲染順序
拿出Unity饰豺,創(chuàng)建三個(gè)立方體亿鲜,都使用默認(rèn)的bump diffuse shader(渲染隊(duì)列相同),分別給三個(gè)不同的材質(zhì)(相同材質(zhì)的小頂點(diǎn)數(shù)的物體引擎會(huì)動(dòng)態(tài)合批)哟忍,用Unity5帶的Frame Debug工具查看一下Draw Call狡门。(Unity5真是好用得多了,如果用4的話锅很,還得用NSight之類的抓幀)
可以看出其馏,Unity中對(duì)于不透明的物體,是采用了從前到后的渲染順序進(jìn)行渲染的爆安,這樣叛复,不透明物體在進(jìn)行完vertex階段,進(jìn)行Z Test扔仓,然后就可以得到該物體最終是否在屏幕上可見(jiàn)了褐奥,如果前面渲染完的物體已經(jīng)寫(xiě)好了深度,深度測(cè)試失敗翘簇,那么后面渲染的物體就直接不會(huì)再去進(jìn)行fragment階段撬码。(不過(guò)這里需要把三個(gè)物體之間的距離稍微拉開(kāi)一些,本人在測(cè)試時(shí)發(fā)現(xiàn)版保,如果距離特別近呜笑,就會(huì)出現(xiàn)渲染次序比較亂的情況晌梨,因?yàn)槲覀儾恢繳nity內(nèi)部具體排序時(shí)是按照什么標(biāo)準(zhǔn)來(lái)判定的哪個(gè)物體離攝像機(jī)更近悄晃,這里我也就不妄加猜測(cè)了)
相同渲染隊(duì)列中半透明物體的渲染順序
透明物體的渲染一直是圖形學(xué)方面比較蛋疼的地方击奶,對(duì)于透明物體的渲染铭乾,就不能像渲染不透明物體那樣多快好省了锡宋,因?yàn)橥该魑矬w不會(huì)寫(xiě)深度盟猖,也就是說(shuō)透明物體之間的穿插關(guān)系是沒(méi)有辦法判斷的州藕,所以半透明的物體在渲染的時(shí)候一般都是采用從后向前的方法進(jìn)行渲染纽门,由于透明物體多了森篷,透明物體不寫(xiě)深度输钩,那么透明物體之間就沒(méi)有所謂的可以通過(guò)深度測(cè)試來(lái)剔除的優(yōu)化,每個(gè)透明物體都會(huì)走像素階段的渲染疾宏,會(huì)造成大量的Over Draw张足。這也就是粒子特效特別耗費(fèi)性能的原因。
我們實(shí)驗(yàn)一下Unity中渲染半透明物體的順序坎藐,還是上面的三個(gè)立方體为牍,我們把材質(zhì)的shader統(tǒng)一換成粒子最常用的Particle/Additive類型的shader,再用Frame Debug工具查看一下渲染的順序:
半透明的物體渲染的順序是從后到前岩馍,不過(guò)由于半透相關(guān)的內(nèi)容比較復(fù)雜碉咆,就先不在這篇文章中說(shuō)了,打算另起一篇蛀恩。
自定義渲染隊(duì)列
Unity支持我們自定義渲染隊(duì)列疫铜,比如我們需要保證某種類型的對(duì)象需要在其他類型的對(duì)象渲染之后再渲染,就可以通過(guò)自定義渲染隊(duì)列進(jìn)行渲染双谆。而且超級(jí)方便壳咕,我們只需要在寫(xiě)shader的時(shí)候修改一下渲染隊(duì)列中的Tag即可席揽。比如我們希望我們的物體要在所有默認(rèn)的不透明物體渲染完之后渲染,那么我們就可以使用Tag{“Queue” = “Geometry+1”}就可以讓使用了這個(gè)shader的物體在這個(gè)隊(duì)列中進(jìn)行渲染谓厘。
還是上面的三個(gè)立方體幌羞,這次我們分別給三個(gè)不同的shader,并且渲染隊(duì)列不同竟稳,通過(guò)上面的實(shí)驗(yàn)我們知道属桦,默認(rèn)情況下,不透明物體都是在Geometry這個(gè)隊(duì)列中進(jìn)行渲染的他爸,那么不透明的三個(gè)物體就會(huì)按照cube1,cube2,cube3進(jìn)行渲染聂宾。這次我們希望將渲染的順序反過(guò)來(lái),那么我們就可以讓cube1的渲染隊(duì)列最大诊笤,cube3的渲染隊(duì)列最小系谐。貼出其中一個(gè)的shader:
Shader "Custom/RenderQueue1" {
SubShader
{
Tags { "RenderType"="Opaque" "Queue" = "Geometry+1"}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 pos : SV_POSITION;
};
v2f vert(appdata_base v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
return fixed4(0,0,1,1);
}
ENDCG
}
}
//FallBack "Diffuse"
}
其他的兩個(gè)shader類似,只是渲染隊(duì)列和輸出顏色不同盏混。
通過(guò)渲染隊(duì)列蔚鸥,我們就可以自由地控制使用該shader的物體在什么時(shí)機(jī)渲染。比如某個(gè)不透明物體的像素階段操作較費(fèi)许赃,我們就可以控制它的渲染隊(duì)列止喷,讓其渲染更靠后,這樣可以通過(guò)其他不透明物體寫(xiě)入的深度剔除該物體所占的一些像素混聊。
PS:這里貌似發(fā)現(xiàn)了個(gè)問(wèn)題弹谁,我們?cè)谛薷膕hader的時(shí)候一般不需要什么其他操作就可以直接看到修改后的變化,但是本人改完渲染隊(duì)列后句喜,有時(shí)候會(huì)出現(xiàn)從shader的文件上能看到渲染隊(duì)列的變化预愤,但是從渲染結(jié)果以及Frame Debug工具中并沒(méi)有看到渲染結(jié)果的變化,重啟Unity也沒(méi)有起到作用咳胃,直到我把shader重新賦給材質(zhì)之后植康,變化才起了效果...(猜測(cè)是個(gè)bug,因?yàn)榭吹骄W(wǎng)上還有和我一樣的倒霉蛋被這個(gè)坑了展懈,本人的版本是5.3.2销睁,害我差點(diǎn)懷疑昨天是不是喝了,剛實(shí)驗(yàn)完的結(jié)果就完全不對(duì)了...)
**ZTest(深度測(cè)試)和ZWrite(深度寫(xiě)入) **
上一個(gè)例子中存崖,雖然渲染的順序反了過(guò)來(lái)冻记,但是物體之間的遮擋關(guān)系仍然是正確的,這就是z-buffer的功勞来惧,不論我們的渲染順序怎樣冗栗,遮擋關(guān)系仍然能夠保持正確。而我們對(duì)z-buffer的調(diào)用就是通過(guò)ZTest和ZWrite來(lái)實(shí)現(xiàn)的。
首先看一下ZTest隅居,ZTest即深度測(cè)試钠至,所謂測(cè)試,就是針對(duì)當(dāng)前對(duì)象在屏幕上(更準(zhǔn)確的說(shuō)是frame buffer)對(duì)應(yīng)的像素點(diǎn)胎源,將對(duì)象自身的深度值與當(dāng)前該像素點(diǎn)緩存的深度值進(jìn)行比較棕洋,如果通過(guò)了,本對(duì)象在該像素點(diǎn)才會(huì)將顏色寫(xiě)入顏色緩沖區(qū)乒融,否則否則不會(huì)寫(xiě)入顏色緩沖。ZTest提供的狀態(tài)較多摄悯。ZTest Less(深度小于當(dāng)前緩存則通過(guò)赞季, ZTest Greater(深度大于當(dāng)前緩存則通過(guò)),ZTest LEqual(深度小于等于當(dāng)前緩存則通過(guò))奢驯,ZTest GEqual(深度大于等于當(dāng)前緩存則通過(guò))申钩,ZTest Equal(深度等于當(dāng)前緩存則通過(guò)),ZTest NotEqual(深度不等于當(dāng)前緩存則通過(guò))瘪阁,ZTest Always(不論如何都通過(guò))撒遣。注意,ZTest Off等同于ZTest Always管跺,關(guān)閉深度測(cè)試等于完全通過(guò)义黎。
下面再看一下ZWrite,ZWrite比較簡(jiǎn)單豁跑,只有兩種狀態(tài)廉涕,ZWrite On(開(kāi)啟深度寫(xiě)入)和ZWrite Off(關(guān)閉深度寫(xiě)入)。當(dāng)我們開(kāi)啟深度寫(xiě)入的時(shí)候艇拍,物體被渲染時(shí)針對(duì)物體在屏幕(更準(zhǔn)確地說(shuō)是frame buffer)上每個(gè)像素的深度都寫(xiě)入到深度緩沖區(qū)狐蜕;反之,如果是ZWrite Off卸夕,那么物體的深度就不會(huì)寫(xiě)入深度緩沖區(qū)层释。但是,物體是否會(huì)寫(xiě)入深度快集,除了ZWrite這個(gè)狀態(tài)之外贡羔,更重要的是需要深度測(cè)試通過(guò),也就是ZTest通過(guò)碍讨,如果ZTest都沒(méi)通過(guò)治力,那么也就不會(huì)寫(xiě)入深度了。就好比默認(rèn)的渲染狀態(tài)是ZWrite On和ZTest LEqual勃黍,如果當(dāng)前深度測(cè)試失敗宵统,說(shuō)明這個(gè)像素對(duì)應(yīng)的位置,已經(jīng)有一個(gè)更靠前的東西占坑了,即使寫(xiě)入了马澈,也沒(méi)有原來(lái)的更靠前瓢省,那么也就沒(méi)有必要再去寫(xiě)入深度了。所以上面的ZTest分為通過(guò)和不通過(guò)兩種情況痊班,ZWrite分為開(kāi)啟和關(guān)閉兩種情況的話勤婚,一共就是四種情況:
1.深度測(cè)試通過(guò),深度寫(xiě)入開(kāi)啟:寫(xiě)入深度緩沖區(qū)涤伐,寫(xiě)入顏色緩沖區(qū)馒胆;
2.深度測(cè)試通過(guò),深度寫(xiě)入關(guān)閉:不寫(xiě)深度緩沖區(qū)凝果,寫(xiě)入顏色緩沖區(qū)祝迂;
3.深度測(cè)試失敗,深度寫(xiě)入開(kāi)啟:不寫(xiě)深度緩沖區(qū)器净,不寫(xiě)顏色緩沖區(qū)型雳;
4.深度測(cè)試失敗,深度寫(xiě)入關(guān)閉:不寫(xiě)深度緩沖區(qū)山害,不寫(xiě)顏色緩沖區(qū)纠俭;
Unity中默認(rèn)的狀態(tài)(寫(xiě)shader時(shí)什么都不寫(xiě)的狀態(tài))是ZTest LEqual和ZWrite On,也就是說(shuō)默認(rèn)是開(kāi)啟深度寫(xiě)入浪慌,并且深度小于等于當(dāng)前緩存中的深度就通過(guò)深度測(cè)試冤荆,深度緩存中原始為無(wú)限大,也就是說(shuō)離攝像機(jī)越近的物體會(huì)更新深度緩存并且遮擋住后面的物體权纤。如下圖所示匙赞,前面的正方體會(huì)遮擋住后面的物體:
寫(xiě)幾個(gè)簡(jiǎn)單的小例子來(lái)看一下ZTest,ZWrite以及Render Queue這幾個(gè)狀態(tài)對(duì)渲染結(jié)果的控制妖碉。
讓綠色的對(duì)象不被前面的立方體遮擋涌庭,一種方式是關(guān)閉前面的藍(lán)色立方體深度寫(xiě)入:
通過(guò)上面的實(shí)驗(yàn)結(jié)果,我們知道欧宜,按照從前到后的渲染順序坐榆,首先渲染藍(lán)色物體,藍(lán)色物體深度測(cè)試通過(guò)冗茸,顏色寫(xiě)入緩存席镀,但是關(guān)閉了深度寫(xiě)入,藍(lán)色部分的深度緩存值仍然是默認(rèn)的Max夏漱,后面渲染的綠色立方體豪诲,進(jìn)行深度測(cè)試仍然會(huì)成功,寫(xiě)入顏色緩存挂绰,并且寫(xiě)入了深度屎篱,因此藍(lán)色立方體沒(méi)有起到遮擋的作用。
另一種方式是讓綠色強(qiáng)制通過(guò)深度測(cè)試:
這個(gè)例子中其他立方體的shader使用默認(rèn)的渲染方式,綠色的將ZTest設(shè)置為Always交播,也就是說(shuō)不管怎樣重虑,深度測(cè)試都通過(guò),將綠色立方體的顏色寫(xiě)入緩存秦士,如果沒(méi)有其他覆蓋了缺厉,那么最終的輸出就是綠色的了。
那么如果紅色的也開(kāi)了ZTest Always會(huì)怎么樣隧土?
在紅色立方體也用了ZTest Always后提针,紅色遮擋了綠色的部分顯示為了紅色。如果我們換一下渲染隊(duì)列曹傀,讓綠色在紅色之前渲染关贵,結(jié)果就又不一樣了:
更換了渲染隊(duì)列,讓綠色的渲染隊(duì)列+1卖毁,在默認(rèn)隊(duì)列Geometry之后渲染,最終重疊部分又變回了綠色落萎『ダ玻可見(jiàn),當(dāng)ZTest都通過(guò)時(shí)练链,上一個(gè)寫(xiě)入顏色緩存的會(huì)覆蓋上一個(gè)翔脱,也就是說(shuō)最終輸出的是最后一個(gè)渲染的對(duì)象顏色。
再看一下Greater相關(guān)的部分有什么作用媒鼓,這次我們其他的都使用默認(rèn)的渲染狀態(tài)届吁,綠色的立方體shader中ZTest設(shè)置為Greater:
這個(gè)效果就比較好玩了,雖然我們發(fā)現(xiàn)在比較深度時(shí)绿鸣,前面被藍(lán)色立方體遮擋的部分疚沐,綠色的最終覆蓋了藍(lán)色,是想要的結(jié)果潮模,不過(guò)其他部分哪里去了呢亮蛔?簡(jiǎn)單分析一下,渲染順序是從前到后擎厢,也就是說(shuō)藍(lán)色最先渲染究流,默認(rèn)深度為Max,藍(lán)色立方體的深度滿足LEqual條件动遭,就寫(xiě)入了深度緩存芬探,然后綠色開(kāi)始渲染,重疊的部分的深度緩存是藍(lán)色立方體寫(xiě)入的厘惦,而綠色的深度值滿足大于藍(lán)色深度的條件偷仿,所以深度測(cè)試通過(guò),重疊部分顏色更新為綠色;而與紅色立方體重合的部分炎疆,紅色立方體最后渲染卡骂,與前面的部分進(jìn)行深度測(cè)試,小于前面的部分形入,深度測(cè)試失敗全跨,重疊部分不會(huì)更新為紅色,所以重疊部分最終為綠色亿遂。而綠色立方體沒(méi)有與其他部分重合的地方為什么消失了呢浓若?其實(shí)是因?yàn)榫G色立方體渲染時(shí),除了藍(lán)色立方體渲染的地方是有深度信息的蛇数,其他部分的深度信息都為Max挪钓,藍(lán)色部分用Greater進(jìn)行判斷,肯定會(huì)失敗耳舅,也就不會(huì)有顏色更新碌上。
有一個(gè)好玩的效果其實(shí)就可以考ZTest Greater來(lái)實(shí)現(xiàn),就是游戲里面經(jīng)常出現(xiàn)的浦徊,當(dāng)玩家被其他場(chǎng)景對(duì)象遮擋時(shí)馏予,遮擋的部分會(huì)呈現(xiàn)出X-光的效果;其實(shí)是在渲染玩家時(shí)盔性,增加了一個(gè)Pass霞丧,默認(rèn)的Pass正常渲染,而增加的一個(gè)Pass就使用Greater進(jìn)行深度測(cè)試冕香,這樣蛹尝,當(dāng)玩家被其他部分遮擋時(shí),遮擋的部分才會(huì)顯示出來(lái)悉尾,用一個(gè)描邊的效果渲染突那,其他部分仍然使用原來(lái)的Pass即可。
Early-Z技術(shù)
傳統(tǒng)的渲染管線中构眯,ZTest其實(shí)是在Blending階段陨收,這時(shí)候進(jìn)行深度測(cè)試,所有對(duì)象的像素著色器都會(huì)計(jì)算一遍鸵赖,沒(méi)有什么性能提升务漩,僅僅是為了得出正確的遮擋結(jié)果,會(huì)造成大量的無(wú)用計(jì)算它褪,因?yàn)槊總€(gè)像素點(diǎn)上肯定重疊了很多計(jì)算饵骨。因此現(xiàn)代GPU中運(yùn)用了Early-Z的技術(shù),在Vertex階段和Fragment階段之間(光柵化之后茫打,fragment之前)進(jìn)行一次深度測(cè)試居触,如果深度測(cè)試失敗妖混,就不必進(jìn)行fragment階段的計(jì)算了,因此在性能上會(huì)有很大的提升轮洋。但是最終的ZTest仍然需要進(jìn)行制市,以保證最終的遮擋關(guān)系結(jié)果正確。前面的一次主要是Z-Cull為了裁剪以達(dá)到優(yōu)化的目的弊予,后一次主要是Z-Check祥楣,為了檢查,如下圖:
Early-Z的實(shí)現(xiàn)汉柒,主要是通過(guò)一個(gè)Z-pre-pass實(shí)現(xiàn)误褪,簡(jiǎn)單來(lái)說(shuō),對(duì)于所有不透明的物體(透明的沒(méi)有用碾褂,本身不會(huì)寫(xiě)深度)兽间,首先用一個(gè)超級(jí)簡(jiǎn)單的shader進(jìn)行渲染,這個(gè)shader不寫(xiě)顏色緩沖區(qū)正塌,只寫(xiě)深度緩沖區(qū)嘀略,第二個(gè)pass關(guān)閉深度寫(xiě)入,開(kāi)啟深度測(cè)試乓诽,用正常的shader進(jìn)行渲染帜羊。其實(shí)這種技術(shù),我們也可以借鑒问裕,在渲染透明物體時(shí),因?yàn)殛P(guān)閉了深度寫(xiě)入孵坚,有時(shí)候會(huì)有其他不透明的部分遮擋住透明的部分粮宛,而我們其實(shí)不希望他們被遮擋,僅僅希望被遮擋的物體半透卖宠,這時(shí)我們就可以用兩個(gè)pass來(lái)渲染巍杈,第一個(gè)pass使用Color Mask屏蔽顏色寫(xiě)入,僅寫(xiě)入深度扛伍,第二個(gè)pass正常渲染半透筷畦,關(guān)閉深度寫(xiě)入。
關(guān)于Early-Z技術(shù)可以參考ATI的論文Applications of Explicit Early-Z Culling以及PPT刺洒,還有一篇Intel的文章鳖宾。
Unity渲染順序總結(jié)
如果我們先繪制后面的物體,再繪制前面的物體逆航,就會(huì)造成over draw鼎文;而通過(guò)Early-Z技術(shù),我們就可以先繪制較近的物體因俐,再繪制較遠(yuǎn)的物體(僅限不透明物體)拇惋,這樣周偎,通過(guò)先渲染前面的物體,讓前面的物體先占坑撑帖,就可以讓后面的物體深度測(cè)試失敗蓉坎,進(jìn)而減少重復(fù)的fragment計(jì)算,達(dá)到優(yōu)化的目的胡嘿。Unity中默認(rèn)應(yīng)該就是按照最近距離的面進(jìn)行繪制的蛉艾,我們可以看一下Unity官方的文檔中顯示的:
從文檔給出的流程來(lái)看,這個(gè)Depth-Test發(fā)生在Vertex階段和Fragment階段之間灶平,也就是上面所說(shuō)的Early-Z優(yōu)化伺通。
簡(jiǎn)單總結(jié)一下Unity中的渲染順序:先渲染不透明物體,順序是從前到后逢享;再渲染透明物體罐监,順序是從后到前。
Alpha Test(Discard)在移動(dòng)平臺(tái)消耗較大的原因
從本人剛剛開(kāi)始接觸渲染瞒爬,就開(kāi)始聽(tīng)說(shuō)移動(dòng)平臺(tái)Alpha Test比較費(fèi)弓柱,當(dāng)時(shí)比較納悶,直接discard了為什么會(huì)費(fèi)呢侧但,應(yīng)該更省才對(duì)笆缚铡?這個(gè)問(wèn)題困擾了我好久禀横,今天來(lái)刨根問(wèn)底一下屁药。還是跟我們上面講到的Early-Z優(yōu)化。正常情況下柏锄,比如我們渲染一個(gè)面片酿箭,不管是否是開(kāi)啟深度寫(xiě)入或者深度測(cè)試,這個(gè)面片的光柵化之后對(duì)應(yīng)的像素的深度值都可以在Early-Z(Z-Cull)的階段判斷出來(lái)了趾娃;而如果開(kāi)啟了Alpha Test(Discard)的時(shí)候缭嫡,discard這個(gè)操作是在fragment階段進(jìn)行的,也就是說(shuō)這個(gè)面片光柵化之后對(duì)應(yīng)的像素是否可見(jiàn)抬闷,是在fragment階段之后才知道的妇蛀,最終需要靠Z-Check進(jìn)行判斷這個(gè)像素點(diǎn)最終的顏色。其實(shí)想象一下也能夠知道笤成,如果我們開(kāi)了Alpha Test并且還用Early-Z的話评架,一塊本來(lái)應(yīng)該被剃掉的地方,就仍然寫(xiě)進(jìn)了深度緩存炕泳,這樣就會(huì)造成其他部分被一個(gè)完全沒(méi)東西的地方遮擋古程,最終的渲染效果肯定就不對(duì)了。所以喊崖,如果我們開(kāi)啟了Alpha Test挣磨,就不會(huì)進(jìn)行Early-Z雇逞,Z Test推遲到fragment之后進(jìn)行,那么這個(gè)物體對(duì)應(yīng)的shader就會(huì)完全執(zhí)行vertex shader和fragment shader茁裙,造成over draw塘砸。有一種方式是使用Alpha Blend代替Alpha Test,雖然也很費(fèi)晤锥,但是至少Alpha Blend雖然不寫(xiě)深度掉蔬,但是深度測(cè)試是可以提前進(jìn)行的,因?yàn)椴粫?huì)在fragment階段再?zèng)Q定是否可見(jiàn)矾瘾,因?yàn)槎际强梢?jiàn)的女轿,只是透明度比較低罷了。不過(guò)這樣只是權(quán)宜之計(jì)壕翩,Alpha Blend并不能完全代替Alpha Test蛉迹。
關(guān)于Alpha Test對(duì)于Power VR架構(gòu)的GPU性能的影響,簡(jiǎn)單引用一下官方的鏈接以及一篇討論帖:
最后再附上兩篇參考文章
http://blog.csdn.net/candycat1992/article/details/41599167
http://blog.csdn.net/arundev/article/details/7895839