【入門精要】008-透明效果
透明度有兩種實(shí)現(xiàn)方法:一種是透明度測(cè)試(AlphaTest),一種是透明度混合(AlphaBlending)。
透明度測(cè)試:如果片元不滿足條件,則該片元就會(huì)被舍棄。被舍棄的片元不會(huì)對(duì)顏色緩沖有任何影響。如果滿足條件,則會(huì)按照普通的不透明物體來(lái)進(jìn)行渲染。透明度測(cè)試不需要關(guān)閉深度寫(xiě)入。其結(jié)果要么完全透明,要么完全不透明。
透明度混合:實(shí)現(xiàn)半透明效果,需關(guān)閉深度寫(xiě)入。他會(huì)將當(dāng)前的半透明片元與顏色緩沖中的顏色值做混合,得到新顏色。由于關(guān)閉了深度寫(xiě)入,需格外注意渲染順序。雖然關(guān)閉了深度寫(xiě)入,但這不代表我們關(guān)閉了深度測(cè)試。當(dāng)深度測(cè)試檢測(cè)不透明物體在半透明物體之前,則會(huì)掩蓋半透明物體。
為什么渲染順序很重要?
因?yàn)槿绻覀兊陌胪该魑矬w被提前渲染,則會(huì)導(dǎo)致深度測(cè)試時(shí),半透明物體后的不透明物體因深度測(cè)試通過(guò)而覆蓋渲染結(jié)果,造成渲染的排序錯(cuò)誤。
半透明物體,要從后往前渲染,先渲染遠(yuǎn)的,再渲染近的。

渲染順序:
unity為了解決相關(guān)問(wèn)題提供了渲染隊(duì)列(Render Queue),我們可以在Tag中添加Queue標(biāo)簽決定物體的渲染隊(duì)列。
Background(1000):在其他物體之前渲染,多用于背景。
Geometry(2000):默認(rèn)渲染隊(duì)列,不透明物體渲染隊(duì)列。
AlphaTest(2450):需要進(jìn)行透明度測(cè)試的物體的隊(duì)列。
Transparent(3000):在小于3000的隊(duì)列渲染完成后,從后往前渲染,用于半透明物體。
Overlay(4000):用于實(shí)現(xiàn)一些疊加效果,需要在最后渲染的物體的隊(duì)列。
因此,如果我們想實(shí)現(xiàn)半透明效果,應(yīng)該為shader添加如下條件:
Tags{ "Queue" = "AlphaTest" } 或?Tags{ "Queue" = "Transparent"?}
ZWrite Off(關(guān)閉深度寫(xiě)入):關(guān)閉深度寫(xiě)入,用于半透明物體,常寫(xiě)于Pass通道內(nèi)。

透明度測(cè)試:
透明度測(cè)試是CG語(yǔ)言中的一個(gè)函數(shù)(Clip),如果傳入Clip的值中(如:float4)任何一個(gè)值小于0,則舍棄該片元,用于片元著色器中。
首先聲明標(biāo)簽:
Tags {
? ? ? ? ? ? "Queue" = "AlphaTest" ? ? ? ? ? ? ? //設(shè)置渲染隊(duì)列
? ? ? ? ? ? "RenderType"="TransparentCutout" ? ?//對(duì)應(yīng)改為Cutout
? ? ? ? ? ? "ForceNoShaderCasting"="True" ? ? ? //關(guān)閉陰影投射
? ? ? ? ? ? "IgnoreProjector"="True" ? ? ? ? ? ?//不響應(yīng)投射器
}
然后在Pass通道內(nèi)聲明標(biāo)簽
Tags { "LightMode"="ForwardBase" }
最后在片元著色器中添加方法:
clip(“傳入的值”);
設(shè)置好合適的Fallback,即可。

透明度混合:
透明度混合和透明度測(cè)試不一樣,兩者可共存。
透明度混合可以實(shí)現(xiàn)真正的透明度效果。他會(huì)使用當(dāng)前片元的透明度作混合因子,與顏色緩沖中的顏色值做混合,得到結(jié)果。但由于我們關(guān)閉了深度寫(xiě)入,這使得我們要格外注意排序。
為了實(shí)現(xiàn)效果,unity為我們提供了一個(gè)混合命令:Blend。
Blend的工作就是把當(dāng)前自身的顏色與顏色緩沖中的顏色作混合,混合的方法由相應(yīng)指令決定。
舉例:
BlendOp Add????????????????????????????????????????//混合方法為Add
Blend SrcAlpha OneMinusSrcAlpha????//(當(dāng)前源的透明度乘以當(dāng)前源顏色) 與 (一減當(dāng)前源的透明度的值乘以顏色緩沖后的值) 相加
實(shí)現(xiàn)方法:
添加Tag:
Tags {
? ? ? ? ? ? "Queue" = "Transparent" ? ? ? ? ? ? //修改渲染順序
? ? ? ? ? ? "RenderType"="Transparent" ? ? ? ? ?//對(duì)應(yīng)改為Transparent
? ? ? ? ? ? "ForceNoShaderCasting"="True" ? ? ? //關(guān)閉陰影投射
? ? ? ? ? ? "IgnoreProjector"="True" ? ? ? ? ? ?//不響應(yīng)投射器
}
關(guān)閉深度寫(xiě)入:
ZWrite Off
Pass通道內(nèi)添加混合模式:
BlendOp [“計(jì)算方法”]
Blend [“當(dāng)前源顏色”] [“深度緩沖顏色”]
設(shè)置好合適的Fallback,即可。

開(kāi)啟深度寫(xiě)入的半透明效果:
由于關(guān)閉了深度寫(xiě)入,造成了模型渲染排序的錯(cuò)誤。如何解決這個(gè)問(wèn)題呢?
我們可以用兩個(gè)Pass通道來(lái)解決。
第一個(gè)Pass通道不渲染,開(kāi)啟深度寫(xiě)入,只輸出深度值。
第二個(gè)Pass通道關(guān)閉深度寫(xiě)入,正常渲染。
實(shí)現(xiàn)方法:
Pass{
????ZWrite On? ? ????????????????//開(kāi)啟深度寫(xiě)入
????ColorMask 0????????????????//當(dāng)ColorMask為0時(shí),不輸出任何顏色
}
Pass{
????同透明度混合;
}
設(shè)置好合適的Fallback,完成。

ShaderLab混合命令:
之前提到了Blend,現(xiàn)在我們來(lái)詳細(xì)了解一下。
混合是如何實(shí)現(xiàn)的:當(dāng)片元著色器產(chǎn)生一個(gè)顏色時(shí),可以選擇與顏色緩存中的顏色進(jìn)行混合,得到混合后的結(jié)果。
Blend [源顏色x混合因子] [顏色緩存x混合因子]
命令:
Blend SrcFactor DstFactor:開(kāi)啟混合,源顏色乘以SrcFactor,顏色緩存乘以DstFactor,兩者默認(rèn)相加。
Blend?SrcFactor?DstFactor,SrcFactorA?DstFactorA:開(kāi)啟混合,源顏色(rgb)乘以SrcFactor,顏色緩存(rgb)乘以DstFactor,兩者默認(rèn)相加。源顏色透明度(a)乘以SrcFactorA,顏色緩存透明度(a)乘以DstFactorA,兩者默認(rèn)相加。兩者區(qū)別只是將顏色通道和透明度分開(kāi)計(jì)算。
混合參數(shù)(Blend):
One:因子為1
Zero:因子為0
SrcColor:因子為源顏色值,RGB通道與A通道分開(kāi)混合。
SrcAlpha:因子為源顏色的A通道。
DstColor:因子為目標(biāo)顏色值,RGB通道與A通道分開(kāi)混合。
DstAlpha:因子為目標(biāo)顏色的A通道。
OneMinusSrcColor:因子為(1-源顏色值),RGB通道與A通道分開(kāi)混合。
OneMinusSrcAlpha:因子為(1-源顏色的A通道)。
OneMinusDstColor:因子為(1-目標(biāo)顏色值),RGB通道與A通道分開(kāi)混合。
OneMinusDstAlpha:因子為(1-目標(biāo)顏色的A通道)。
混合操作(BlendOp):
Add:將混合后的源顏色和目標(biāo)顏色相加
Sub:將混合后的源顏色減去目標(biāo)顏色
RevSub:將混合后的目標(biāo)顏色減去源顏色
Min:取二者最小(逐分量比較取值)
Max:取二者最大(逐分量比較取值)
常見(jiàn)混合類型:
Blend SrcAlpha OneMinusSrcAlpha:正常的透明度混合
Blend OneMinusDstColor One:柔和相加
Blend DstColor Zero:正片疊底
Blend DstColor SrcColor:兩倍相乘
Blend One One(BlendOp Min):變暗
Blend One One(BlendOp Max):變亮
Blend OneMinusDstColor One:濾色
Blend One OneMinusSrcColor:濾色
Blend One One:線性減淡

雙面渲染:
大多渲染情況下,我們只渲染了物體正面。而想要渲染反面,或者兩面都渲染,則需要使用Cull指令來(lái)完成。
Cull有三種指令:Front(剔除正面)、Back(剔除反面)、Off(不剔除)
使用方法同Blend,如
Cull Off
即可。