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 混合等式为加法操作,默认情况
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"
}
测试结果对比: