【貓貓的Unity Shader之旅】之Blend語句
上回說過,片段經過fragment處理後,會經過混合處理,最終變為緩衝區中的顏色資料。這裡的混合,指的是處理後的片段顏色與已經存在於緩衝區中的顏色進行混合。具體的混合規則使用Blend語句來指定。
Blend {code for SrcFactor} {code for DstFactor}
這裡的code for SrcFactor和DstFactor指的是下面表格的內容:
當使用Blend時,最終顏色被計算為result = fragment_color * SrcFactor + pixel_color * DstFactor,這個fragment_color即是經過處理的片段顏色,也就是fragment返回的結果,pixel_color是原本存在於緩衝區的顏色,因為可能渲染過其他模型嘛~這個result顏色被重新寫入緩衝區,等待被其他片段Blend或者變成最終顏色(如果沒有被其他Blend)。
利用Blend實現透明效果
Blend的一個基本的用法就是用來實現透明。對於一個半透明物體,我們需要根據透明度將顏色分為兩部分,比如透明度為70%,可以認為最終顏色是70%的該片段顏色和30%的背景顏色。所以Blend語句應該為Blend SrcAlpha OneMinusSrcAlpha,完整程式碼如下:
Shader "Custom/SimpleAlpha" {
Properties {
_MainTint ("Main Color", Color) = (1, 1, 1, 1)
}
SubShader {
Tags { "Queue" = "Transparent" }
LOD 200
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
uniform float4 _MainTint;
float4 vert(float4 vertPos : POSITION) : SV_POSITION
{
return mul(UNITY_MATRIX_MVP, vertPos);
}
float4 frag(float4 vertPos : SV_POSITION) : COLOR
{
return _MainTint;
}
ENDCG
}
}
FallBack "Diffuse"
}
注意到這裡有一句ZWrite Off,用來關閉寫入深度緩衝區。深度緩衝區用來判斷哪些片段被遮擋,被遮擋的話就不會被渲染,對於透明物體,我們不需要這樣,因為我麼需要看到透明物體背後的東西。具體效果如下:
顏色疊加效果
顏色疊加常用於粒子特效,多個粒子的顏色疊加後會產生更亮的顏色,Blend語句為Blend One One,下面是個簡單的例子:
Shader "Custom/Additive" {
Properties {
_MainTint ("Main Color", Color) = (1, 1, 1, 1)
}
SubShader {
Tags { "Queue" = "Geometry" }
LOD 200
Pass
{
Blend One One
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
uniform float4 _MainTint;
float4 vert(float4 vertPos : POSITION) : SV_POSITION
{
return mul(UNITY_MATRIX_MVP, vertPos);
}
float4 frag(float4 vertPos : SV_POSITION) : COLOR
{
return _MainTint;
}
ENDCG
}
}
FallBack "Diffuse"
}
這次我們用粒子系統展示下實際效果:
注意看顏色會隨著疊加的粒子數增多而變亮,直至變成白色。
結束語
使用Blend語句進行混合操作可以非常靈活地實現多種效果。比較難的是需要某種效果的時能夠想到使用Blend以及如果正確地使用SrcFactor和DstFactor。另外值得注意的一點是:Blend語句不是Cg程式碼,而是ShaderLab語法,類似於Tags,所以寫在CGPROGRAM和ENDCG外面。