【翻譯】第七章節:順序無關的透明度(關於順序無關的混合)
轉載地址:http://www.omuying.com/article/95.aspx
本部落格中還有篇詳解,可以去看看那篇先做了解。
在《透明度》章節中,我們討論並解決了在著色器上呈現透明度一些標準的問題,如果你還沒有閱讀這個章節,那麼你應該先去閱讀它。
順序無關的混合
在《透明度》章節中,我們知道,混合的結果取決於三角形的呈現順序(尤其是 alpha 混合),如果三角形不是按從背面到前面的呈現方式,這樣可能會導致渲染問題,術語“order-independent transparency”一詞描述各種技術來避免這個問題,其中的一個技術便是“order-independent”混合,即使用一個不依賴於三角形柵格化順序的混合公式,他們是:加法(additive )blending 和乘法(multiplicative) blending。
我們不可能(至少很難)說是照片以何種順序拍攝。additive blending 的特點可以依據《透明度》章節的混合公式:
1 |
float4
result = SrcFactor * fragment_output + DstFactor * pixel_color; |
其中 SrcFactor 和 DstFactor 由 Unity 的語法決定:
1 |
Blend
{code for SrcFactor}
{code for DstFactor} |
對於 additive blending,DstFactor 必須是 One,SrcFactor 的值不能取決於幀緩衝區裡面的畫素顏色,它可以是 One、SrcColor、SrcAlpha、 OneMinusSrcColor 或者 OneMinusSrcAlpha。
Shader "Cg shader using additive blending" { SubShader { Tags { "Queue" = "Transparent" } // draw after all opaque geometry has been drawn在所有不透明幾何物體後繪製 Pass { Cull Off // draw front and back faces ZWrite Off // don't write to depth buffer // in order not to occlude other objects Blend SrcAlpha One // additive blending CGPROGRAM #pragma vertex vert #pragma fragment frag float4 vert(float4 vertexPos : POSITION) : SV_POSITION { return mul(UNITY_MATRIX_MVP, vertexPos); } float4 frag(void) : COLOR { return float4(1.0, 0.0, 0.0, 0.3); } ENDCG } } }
Multiplicative Blending
multiplicative blending 使用的例子是在攝影中使用多個均勻(uniform)的灰色濾波器:攝像機濾波器的順序對於影象的衰減是無關緊要的,在三角形的柵格化方面,影象對應於在三角形柵格化之前幀緩衝區中的內容,而濾波器對應於三角形。
可以像下面的格式來指定 multiplicative blending:
1 |
Blend
{code for SrcFactor}
{code for DstFactor} |
對於 SrcFactor 必須是 Zero,並且 DstFactor 必須取決於片段顏色,所以可能的值是 SrcColor、SrcAlpha、OneMinusSrcColor 或者 OneMinusSrcAlpha。典型的例子是 DstFactor 使用 OneMinusSrcAlpha 來表示用片段的 alpha 分量來指定不透明背景的衰減:
最後,我們可以在一個著色器中使用兩個 Pass 來合併 multiplicative blending(指定背景的衰減)和 additive blending(給三角形新增顏色),如果忽略三角形網格本身的顏色衰減,這可以被認為是一種近似小不透明體(small opacities)的 alpha 混合,即小的 alpha 值。
Shader "Custom/Blending1"
{
SubShader
{
Tags{ "Queue" = "Transparent" }
// draw after all opaque geometry has been drawn
Pass
{
Cull Off // draw front and back faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend Zero OneMinusSrcAlpha // multiplicative blending
// for attenuation by the fragment's alpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float4 vert(float4 vertexPos : POSITION) : SV_POSITION
{
return mul(UNITY_MATRIX_MVP, vertexPos);
}
float4 frag(void) : COLOR
{
return float4(0.0, 0.0, 1.0, 0.3);
}
ENDCG
}
Pass
{
Cull Off // draw front and back faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend SrcAlpha One // additive blending to add colors
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float4 vert(float4 vertexPos : POSITION) : SV_POSITION
{
return mul(UNITY_MATRIX_MVP, vertexPos);
}
float4 frag(void) : COLOR
{
return float4(0.0, 0.0, 1.0, 0.5);
}
ENDCG
}
}
}
去掉第二個通道的註釋,效果如圖所示: