Cg 程式設計/Unity/順序無關透明度

本教程涵蓋順序無關混合。
它延續了“透明度”部分的討論,並解決了一些標準透明度問題。如果您還沒有閱讀過本教程,請先閱讀。

正如“透明度”部分所述,混合的結果通常(特別是對於標準 Alpha 混合)取決於三角形渲染的順序,因此如果三角形沒有從後到前排序(通常不是),則會導致渲染偽影。術語“順序無關透明度”描述了各種避免此問題的技術。其中一種技術是順序無關混合,即使用不依賴於三角形光柵化的順序的混合方程。有兩種基本方法:疊加混合和乘積混合。
疊加混合的標準示例是雙重曝光,就像本節中的影像一樣:顏色被疊加,以至於不可能(或者至少非常難)說照片拍攝的順序。疊加混合可以用“透明度”部分中介紹的混合方程來描述
float4 result = SrcFactor * fragment_output + DstFactor * pixel_color;
其中fragment_output是片段著色器的輸出,pixel_color是幀緩衝區中已有的顏色,而SrcFactor和DstFactor由 Unity 的 ShaderLab 語法中的行確定
Blend {SrcFactor 的程式碼} {DstFactor 的程式碼}
對於疊加混合,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 UnityObjectToClipPos(vertexPos);
}
float4 frag(void) : COLOR
{
return float4(1.0, 0.0, 0.0, 0.2);
}
ENDCG
}
}
}
攝影中乘積混合的一個例子是使用多個均勻灰度濾鏡:濾鏡放置在相機上的順序對影像的最終衰減沒有影響。在三角形光柵化的意義上,影像對應於在三角形光柵化之前幀緩衝區的內容,而濾鏡對應於三角形。
在 Unity 中使用以下行指定乘積混合時
Blend {SrcFactor 的程式碼} {DstFactor 的程式碼}
SrcFactor 的程式碼必須為Zero,而DstFactor 的程式碼必須依賴於片段顏色;也就是說,它可以是SrcColor、SrcAlpha、OneMinusSrcColor或OneMinusSrcAlpha。使用OneMinusSrcAlpha作為DstFactor 的程式碼,用於使用片段的 alpha 分量指定的透明度來衰減背景,是一個典型的例子。
Shader "Cg shader using multiplicative 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 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 UnityObjectToClipPos(vertexPos);
}
float4 frag(void) : COLOR
{
return float4(1.0, 0.0, 0.0, 0.2);
}
ENDCG
}
}
}
最後,將用於衰減背景的乘積混合和用於新增三角形顏色的疊加混合結合在一個著色器中,將上述兩個通道組合起來是很有意義的。如果忽略了三角形網格自身顏色的衰減,這可以被認為是對小透明度(即小的 alpha 值)的 Alpha 混合的一種近似。
Shader "Cg shader using order-independent 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 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 UnityObjectToClipPos(vertexPos);
}
float4 frag(void) : COLOR
{
return float4(1.0, 0.0, 0.0, 0.2);
}
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 UnityObjectToClipPos(vertexPos);
}
float4 frag(void) : COLOR
{
return float4(1.0, 0.0, 0.0, 0.2);
}
ENDCG
}
}
}
請注意,這兩個通道的順序很重要:首先衰減背景,然後新增顏色。
恭喜您已經完成本教程。我們已經瞭解了
- 什麼是順序無關透明度和順序無關混合。
- 兩種最重要的順序無關混合型別(疊加和乘積)。
- 如何實現疊加混合和乘積混合。
- 如何組合兩個通道用於疊加和乘積混合,以實現順序無關的 Alpha 混合近似。
如果您想了解更多