透明度測試
QUEUE標籤用於決定模型用於哪個渲染隊列(隊列索引號越小越先渲染越適合背景一類)
名稱
隊列索引號 描述
Background 1000 適合背景物體
Geometry 2000 不透明物體,默認的
AlphaTest 2450 需要透明度測試的物體
Transparent 3000 半透明物體,使用透明度混合的物體
Overlay 4000 疊加特效,需要最後渲染的物體
SubShader
{
//Queue標籤用於決定模型用於哪個渲染隊列(隊列索引號越小越先渲染越適合背景一類)
Tags { "Queue"="AlphaTest" }
pass{...}
}
Shader "LT/AlphaTest"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color("Color",Color) = (1,1,1,1)
_Cutoff("Cutoff",Range(0,1)) = 0.5
}
SubShader
{
//Queue標籤用於決定模型用於哪個渲染隊列(隊列索引號越小越先渲染越適合背景一類)
Tags { "QUEUE"="AlphaTest" "IGNOREPROJECTOR"="True" "RenderType"="TransparentCutout" }
//這一行千萬要注意空格,不然模型會出現一會兒部分透明一會兒不透明的問題
Pass
{
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color;
fixed _Cutoff;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal :NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 worldNormal :TEXCOORD1;
float3 worldPos :TEXCOORD2;
};
//座標系轉換,模型空間->世界空間
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 col = tex2D(_MainTex, i.uv);
//alpha test
clip(col.a - _Cutoff);
//上面這句等同與下面這個
//if((col.a - _Cutoff)<0.0)
// {
// disscard;
// }
fixed3 albedo = col.rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffuse = _LightColor0.rgb * albedo * max(0,dot(worldNormal,worldLightDir));
return fixed4(ambient + diffuse,1.0);
}
ENDCG
}
}
FallBack "Transparent/Cutout/VertexLit"
}
Blend透明度混合
Blend 混合等式爲加法操作,默認情況
BlendOp BlendOperation混合操作命令
Untiy 官網有詳細說明:https://docs.unity3d.com/Manual/SL-Blend.html
我再根據閱讀《unity shader入門精要》後我的理解詳細說下具體的計算公式:
ShaderLab 中設置混合因子的命令
命令 描述
Blend SrcFactor DstFactor 開啓混合,設置混合因子。Orgba= SrcFactor*Srgba + DstFactor*Drgba
Blend SrcFactor DstFactor, 開啓混合,設置混合因子,但是透明通道使用了不同的混合因子,公式如下:
SrcFactorA DstFactorA Orgb= SrcFactor*Srgb + DstFactor*Drgb,Alpha通道部分SrcFactorA和DstFactorA 公式:
Oa= SrcFactorA*Sa + DstFactorA*Da
公式中的變量:
Srgba:源顏色(該片元產生的顏色),可以理解爲:當前物體的顏色
Drgba:目標顏色(已存在於顏色緩存的顏色),可以暫時理解爲:先寫入顏色緩衝區的顏色
SrcFactor:源顏色的混合因子
DstFactor :目標顏色的混合因子
Blend factors
All following properties are valid for both SrcFactor & DstFactor in theBlend command.Source refers to the calculated color,Destination is the color already on the screen. The blend factors are ignored ifBlendOp is using logical operations.
One |
因子爲1,The value of one - use this to let either the source or the destination color come through fully. |
Zero |
因子爲0,The value zero - use this to remove either the source or the destination values. |
SrcColor |
源顏色值,The value of this stage is multiplied by the source color value. |
SrcAlpha |
源顏色的透明通道(A通道)值The value of this stage is multiplied by the source alpha value. |
DstColor |
目標顏色值The value of this stage is multiplied by frame buffer source color value. |
DstAlpha |
目標顏色的透明通道(A通道)值The value of this stage is multiplied by frame buffer source alpha value. |
OneMinusSrcColor |
1-源顏色值The value of this stage is multiplied by (1 - source color). |
OneMinusSrcAlpha |
1-源顏色的透明通道(A通道)值The value of this stage is multiplied by (1 - source alpha). |
OneMinusDstColor |
1-目標顏色值The value of this stage is multiplied by (1 - destination color). |
OneMinusDstAlpha |
1-目標顏色的透明通道(A通道)值The value of this stage is multiplied by (1 - destination alpha). |
Blend SrcFactor DstFactor, SrcFactorA DstFactorA可以使用不同參數混合透明通道,例如我們想要混合後輸出顏色的透明度值就是源顏色的透明度。
Blend SrcAlpha OneMinusSrcAlpha , One Zero
Blend operations混合操作
The following blend operations can be used:
Add |
Add source and destination together. 源顏色+目標顏色 Orgb = SrcFactor*Srgb + DstFactor*Drgb Oa = SrcFactorA*Sa + DstFactorA*Da |
Sub |
Subtract destination from source. 源顏色-目標顏色 Orgb = SrcFactor*Srgb - DstFactor*Drgb Oa = SrcFactorA*Sa - DstFactorA*Da |
RevSub |
Subtract source from destination. 目標顏色-源顏色 Orgb = DstFactor*Drgb - SrcFactor*Srgb Oa = DstFactorA*Da - SrcFactorA*Sa |
Min |
Use the smaller of source and destination. 取源顏色和目標顏色最小值(與混合因子無關) Orgba =(min(Sr,Cr), min(Sg,Cg), min(Sb,Cb), min(Sa,Ca)) |
Max |
Use the larger of source and destination. 取源顏色和目標顏色最大值(與混合因子無關) Orgba =(max(Sr,Cr), max (Sg,Cg), max (Sb,Cb), max (Sa,Ca)) |
LogicalClear |
Logical operation: Clear (0)DX11.1 only. DX11.1 only(只支持DX11) |
LogicalSet |
Logical operation: Set (1)DX11.1 only. |
LogicalCopy |
Logical operation: Copy (s)DX11.1 only. |
LogicalCopyInverted |
Logical operation: Copy inverted (!s)DX11.1 only. |
LogicalNoop |
Logical operation: Noop (d)DX11.1 only. |
LogicalInvert |
Logical operation: Invert (!d)DX11.1 only. |
LogicalAnd |
Logical operation: And (s & d)DX11.1 only. |
LogicalNand |
Logical operation: Nand !(s & d)DX11.1 only. |
LogicalOr |
Logical operation: Or (s | d)DX11.1 only. |
LogicalNor |
Logical operation: Nor !(s | d)DX11.1 only. |
LogicalXor |
Logical operation: Xor (s ^ d)DX11.1 only. |
LogicalEquiv |
Logical operation: Equivalence !(s ^ d)DX11.1 only. |
LogicalAndReverse |
Logical operation: Reverse And (s & !d)DX11.1 only. |
LogicalAndInverted |
Logical operation: Inverted And (!s & d)DX11.1 only. |
LogicalOrReverse |
Logical operation: Reverse Or (s | !d)DX11.1 only. |
LogicalOrInverted |
Logical operation: Inverted Or (!s | d)DX11.1 only. |
//正常混合,透明度混合
Blend SrcAlpha OneMinusSrcAlpha
//柔和相加
Blend OneMinusSrcAlpha
//正片疊底,源顏色和目標顏色相乘
Blend DstColor Zero
//兩倍相乘
Blend DstColor SrcColor
//變暗取當前顏色最小值,後面這句Blend One One不會對結果產生影響
BlendOp Min
Blend One One // Blend Zero Zero效果也是一樣的
//變亮
BlendOp Max
Blend One One
//濾色
Blend OneMinusDstColor One //等同於
Blend One OneMinusSrcColor
//線性減淡
Blend One One
shader 實例
Shader "LT/AlphaBlend"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color("Color",Color) = (1,1,1,1)
_AlphaScale("Alpha Scale",Range(0,1)) = 1
}
SubShader
{
Tags { "QUEUE"="Transparent" "IGNOREPROJECTOR"="True" "RenderType"="Transparent" }//這一行千萬要注意空格,不然模型會出現一會兒部分透明一會兒不透明的問題
Pass
{
Tags{"LightMode" = "ForwardBase"}
ZWrite off //如果不關閉深度寫入,半透明物體離相機更近的話,進行深度測試後會將其後的物體表面剔除。導致沒有半透效果了,因此關閉深度寫入。
Blend SrcAlpha OneMinusSrcAlpha //透明度混合
// Blend OneMinusDstColor One //柔和相加
// Blend DstColor Zero //正片疊底,目標顏色*源顏色
// BlendOp Min //取顏色最小值
// Blend Zero Zero
// BlendOp Max ////取顏色最大值
// Blend One One
// Blend OneMinusDstColor One //濾色,與下面這句等價
// Blend One OneMinusSrcColor
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color;
fixed _AlphaScale;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal :NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 worldNormal :TEXCOORD1;
float3 worldPos :TEXCOORD2;
};
//座標系轉換,模型空間->世界空間
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 col = tex2D(_MainTex, i.uv);
//alpha test
// clip(col.a - _Cutoff);
//上面這句等同與下面這個
//if((col.a - _Cutoff)<0.0)
// {
// disscard;
// }
fixed3 albedo = col.rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffuse = _LightColor0.rgb * albedo * max(0,dot(worldNormal,worldLightDir));
return fixed4(ambient + diffuse,col.a * _AlphaScale);
}
ENDCG
}
}
FallBack "Transparent/VertexLit"
}
測試結果對比: