跳轉到內容

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

來自 Wikibooks,開放世界的開放書籍
“你去了哪裡”由 flickr 使用者 Ombligotron 上傳。標題中的拼寫錯誤指的是雕塑“雲門”,又稱“豆子”。

本教程涵蓋順序無關混合

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

“84 – 父子”由 Ben Newton 上傳。雙重曝光的示例。

順序無關混合

[編輯 | 編輯原始碼]

正如“透明度”部分所述,混合的結果通常(特別是對於標準 Alpha 混合)取決於三角形渲染的順序,因此如果三角形沒有從後到前排序(通常不是),則會導致渲染偽影。術語“順序無關透明度”描述了各種避免此問題的技術。其中一種技術是順序無關混合,即使用不依賴於三角形光柵化的順序的混合方程。有兩種基本方法:疊加混合和乘積混合。

疊加混合

[編輯 | 編輯原始碼]

疊加混合的標準示例是雙重曝光,就像本節中的影像一樣:顏色被疊加,以至於不可能(或者至少非常難)說照片拍攝的順序。疊加混合可以用“透明度”部分中介紹的混合方程來描述

float4 result = SrcFactor * fragment_output + DstFactor * pixel_color;

其中fragment_output是片段著色器的輸出,pixel_color是幀緩衝區中已有的顏色,而SrcFactorDstFactor由 Unity 的 ShaderLab 語法中的行確定

Blend {SrcFactor 的程式碼} {DstFactor 的程式碼}

對於疊加混合,DstFactor 的程式碼必須為One,而SrcFactor 的程式碼不能依賴於幀緩衝區中的畫素顏色;也就是說,它可以是OneSrcColorSrcAlphaOneMinusSrcColorOneMinusSrcAlpha

一個例子是

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 的程式碼必須依賴於片段顏色;也就是說,它可以是SrcColorSrcAlphaOneMinusSrcColorOneMinusSrcAlpha。使用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 混合近似。

進一步閱讀

[編輯 | 編輯原始碼]

如果您想了解更多

  • 關於著色器程式碼,您應該閱讀“透明度”部分.
  • 關於另一種順序無關透明度技術,即深度剝離,您可以閱讀 Cass Everitt 的技術報告:“互動式順序無關透明度”,可以在網上獲取。

< Cg 程式設計/Unity

除非另有說明,本頁面上的所有示例原始碼均歸屬於公共領域。
華夏公益教科書