天天看點

【翻譯】第六章節:透明度(關于混合)

轉載位址:http://www.omuying.com/article/94.aspx

原文連結:http://en.wikibooks.org/wiki/Cg_Programming/Unity/Transparency

具體的說,本篇文章關于渲染透明對象,例如:透明的玻璃、塑膠、織物等等(實際上是半透明的對象,他們不一定完全透明)。透過(半)透明的對象我們可以看到他們身後的顔色,其時是它們的顔色與它們身後的顔色進行了混合。

混合

在《Programmable Graphics Pipeline》章節中提到,片段着色器為每個片段(除非片段被擦除)計算 RGB 顔色值(在片段輸出參數使用語義詞 COLOR,包括紅、綠、藍、透明分量),片段的處理細節可以檢視《Per-Fragment Operations》章節,其中一個操作是混合階段,主要用來合并片段的顔色(由片段輸出參數指定),這被稱為“source color”,與之相應的是已存在幀緩沖區的像素顔色,這被成為“destination color”(因為幀緩沖區的顔色是顔色混合結果)。

混合是一個固定階段,你可以通過混合公式對它進行配置但你無法對它程式設計,你可以通過公式像下面那樣來混合 RGBA 顔色值:

1

float4 result = SrcFactor * fragment_output + DstFactor * pixel_color;

其中 fragment_output 是通過片段着色器計算的 RGBA 顔色,pixel_color 是目前幀緩沖區的顔色,result 是混合結果(混合輸出階段),SrcFactor 和 DstFactor 是可配置的 RGBA 顔色(類型是 float4),并且片段顔色和幀顔色的各個分量分别相乘,SrcFactor 和 DstFactor 的值在 Unity ShaderLab 中可以用下面文法指定 :

1

Blend {code 

for

SrcFactor} {code 

for

DstFactor}

比較常用的混合因子(factor)可以檢視下表,更詳細的混合因子(factor)可以檢視《Unity's ShaderLab reference about blending》:

Code Resulting Factor (SrcFactor or DstFactor)
One float4(1.0, 1.0, 1.0, 1.0)
Zero float4(0.0, 0.0, 0.0, 0.0)
SrcColor fragment_output
SrcAlpha fragment_output.aaaa
DstColor pixel_color
DstAlpha pixel_color.aaaa
OneMinusSrcColor float4(1.0, 1.0, 1.0, 1.0) - fragment_output
OneMinusSrcAlpha float4(1.0, 1.0, 1.0, 1.0) - fragment_output.aaaa
OneMinusDstColor float4(1.0, 1.0, 1.0, 1.0) - pixel_color
OneMinusDstAlpha float4(1.0, 1.0, 1.0, 1.0) - pixel_color.aaaa

由于 alpha 混合的流行,即使沒有采用 alpha 混合,顔色的 alpha 分量也通常被稱為不透明。此外,請注意計算機圖形學中透明度的常見計算公式為 1 - 不透明度。

預乘 alpha 混合

alpha 混合還有一個非常重要的公式,有時候片段輸出顔色已經預乘過顔色分量的 alpha 分量,在這種情況下,alpha 不應該被再次相乘,正确的混合是:

Blend One OneMinusSrcAlpha

這對應于:

1

float4 result = float4(1.0, 1.0, 1.0, 1.0) * fragment_output + (float4(1.0, 1.0, 1.0, 1.0) - fragment_output.aaaa) * pixel_color;

附加(Additive)混合

下面是另一種混合方式:

Blend One One

這對應于:

1

float4 result = float4(1.0, 1.0, 1.0, 1.0) * fragment_output + float4(1.0, 1.0, 1.0, 1.0) * pixel_color;

這隻是給幀緩沖區的顔色添加片段輸出顔色,注意這兒 alpha 并沒有被使用,盡管如此,這個混合方式在處理一些透明效果時非常有用,比如,它經常被用在粒子系統中處理火或者透明物體發出的光。

Shader "Custom/Blending"

{

Properties

{

_Opacity("alpha opacity", Range(0.0,1.0)) = 0.3

}

SubShader //第一個 pass 使用前臉剔除來渲染背面(内部),第二個 pass 使用後臉剔除來渲染前面(外部)。

{ //這個着色器适合凸起的網格(封閉網無凹痕,例如球體或者立方體)或者近似的網格。

Tags { "Queue" = "Transparent" }//在不透明物體已繪制之後繪制

Pass

{

Cull Front //第一個渲染通道僅背面

Zwrite off //不寫入深度緩沖區

Blend Zero SrcAlpha//乘法的混合,用于減少alpha值

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

float _Opacity;

struct vertexOutput

{

float4 pos : SV_POSITION;

float4 posInObjectCoords : TEXCOORD0;//測試使用,可以删除

};

vertexOutput vert (float4 vertexPos:POSITION) 

{

vertexOutput output;

output.pos = mul(UNITY_MATRIX_MVP, vertexPos);

output.posInObjectCoords = vertexPos;

return output;

}

fixed4 frag (vertexOutput input) : COLOR

{

if (input.posInObjectCoords.y > 0.0)

{

discard;

}

return float4(1.0, 0.0, 0.0, _Opacity);

}

ENDCG

}

Pass

{

Cull Back //第一個渲染通道僅背面

Zwrite off

Blend Zero SrcAlpha 

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

float _Opacity;

struct vertexOutput

{

float4 pos : SV_POSITION;

float4 posInObjectCoords : TEXCOORD0;

};

vertexOutput vert(float4 vertexPos:POSITION) 

{

vertexOutput output;

output.pos = mul(UNITY_MATRIX_MVP, vertexPos);

output.posInObjectCoords = vertexPos;

return output;

}

fixed4 frag(vertexOutput input) : COLOR

{

if (input.posInObjectCoords.y >0.0)

{

discard;

}

return float4(0.0, 1.0, 0.0, _Opacity);

}

ENDCG

}

}

}

【翻譯】第六章節:透明度(關于混合)

繼續閱讀