使用SubShader的Queue标签来决定我们的模型将归于哪个渲染队列。Unity内部使用了一系列整数索引来表示每个渲染队列,索引号越小表示越早被渲染。
名称 | 队列索引号 | 描述 |
---|---|---|
Background | 1000 | 这个渲染队列会在任何其他队列之前被渲染,通常使用该队列来渲染那些需要绘制在背景的物体 |
Geometry | 2000 | 默认的渲染队列,大多数物体都使用这个队列。不透明物体使用这个队列 |
AlphaTest | 2450 | 需要透明度测试的物体使用这个队列。在Unity5种,它从Geometry队列中单独分出来,这是因为在所有不透明物体渲染之后再渲染它们会更加高效 |
Transparent | 3000 | 这个队列中的物体在所有Geometry和AlphaTest物体渲染后,再按从后往前的顺序进行渲染。任何使用了透明度混合(例如关闭了深度写入的shader)的物体都应该使用该队列 |
Overlay | 4000 | 该队列用于实现一些叠加效果。任何需要在最后渲染的物体都应该使用该队列 |
SubShader{
Tags{ "Queue"="AlphaTest"}
Pass{
···
}
}
SubShader{
Tags{ "Queue"="Transparent"}
Pass{
···
}
}
会在片元着色器中使用clip函数进行透明度测试
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
Shader "Unlit/AlphaTest"
{
Properties{
_Color("Main Tint",Color) = (1,1,1,1)
_MainTex("Main Tex",2D) = "white"{}
_Cutoff("Alpha Cutoff",Range(0,1)) = 0.5
}
SubShader{
Tags{ "Queue"="AlphaTest" "IgnoreProject"="True" "RenderType"="TransparentCutout" }
Pass{
Tags{"LightModel"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "UnityCG.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _Cutoff;
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
float4 texcoord:TEXCOORD0;
};
struct v2f{
float4 pos:SV_POSITION;
float3 worldNormal:TEXCOORD0;
float3 worldPos:TEXCOORD1;
float2 uv:TEXCOORD2;
};
v2f vert(a2v v){
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i):SV_TARGET{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texColor = tex2D(_MainTex,i.uv);
clip(texColor.a - _Cutoff);
// Equal to
// if(texColor.a - _Cutoff < 0.0){
// discard; //忽略这个片元
//}
fixed3 albedo = texColor.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
}
}
}
语义 | 描述 |
---|---|
Blend Off | 关闭混合 |
Blend SrcFactor DstFactor | 开启混合,并设置混合因子。源颜色(该片元产生的颜色)会乘以SrcFactor,而目标颜色(已经存在于颜色缓存的颜色)会乘以DstFactor,然后把两者相加后再存入颜色缓冲中 |
Blend SrcFactor DSTFactor,SrcFactorA DstFactorA | 和上面几乎一样,只是使用不同的因子来混合透明通道 |
BlendOp BlendOperation | 并非是把源颜色和目标颜色简单的相加后混合,而是使用BlendOpertion 对它们进行其他操作 |
Shader "Unlit/AlphaBlend"
{
Properties{
_Color("Main Tint",Color) = (1,1,1,1)
_MainTex("Main Tex",2D) = "white"{}
_AlphaScale("Alpha Scale",Range(0,1)) = 0.5
}
SubShader{
Tags{ "Queue"="Transparent" "IgnoreProject"="True" "RenderType"="Transparent" }
Pass{
Tags{"LightModel"="ForwardBase"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "UnityCG.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _AlphaScale;
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
float4 texcoord:TEXCOORD0;
};
struct v2f{
float4 pos:SV_POSITION;
float3 worldNormal:TEXCOORD0;
float3 worldPos:TEXCOORD1;
float2 uv:TEXCOORD2;
};
v2f vert(a2v v){
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i):SV_TARGET{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texColor = tex2D(_MainTex,i.uv);
fixed3 albedo = texColor.rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffuse = _LightColor0.rgb * albedo * max(0,dot(worldNormal,worldLightDir));
return fixed4(ambient+diffuse,texColor.a * _AlphaScale);
}
ENDCG
}
}
}
由于关闭深度写入而造成的错误排序的情况,有解决方案:
Shader ""
{
Properties{
···
}
SubShader{
···
Pass{
ZWrite On
//ColorMask用于设置颜色通道的写掩码,语义如下
//ColorMask RGB | A | 0 | 其他任何R、G、B、A的组合
//允许定义好的颜色通道显示出来
ColorMask 0
}
Pass{
···
}
}
···
}
设置混合状态时,相当于设置混合等式中的操作和因子
命令 | 描述 |
---|---|
Blend SrcFactor DstFactor | 开启混合,并设置混合因子。源颜色(该片元产生的颜色)会乘以SrcFactor,而目标颜色(已经存在于颜色缓存的颜色)会乘以DstFactor,然后把两者相加后再存入颜色缓冲中 |
Blend SrcFactor DstFactor,SrcFactorA DstFactorA | 和上面几乎一样,只是使用不用的因子来混合透明通道 |
参数 | 描述 |
---|---|
One | 因子为1 |
Zero | 因子为0 |
SrcColor | 因子为源颜色值。当用于混合RGB的混合等式时,使用SrcColor的RGB分量作为混合因子;当用于混合A的混合等式时,使用SrcColor的A分量作为混合因子 |
SrcAlpha | 因子为源颜色的透明度值A(A通道) |
DstColor | 因子为源颜色值。当用于混合RGB通道的混合等式时,使用DstColor的RGB分量作为混合因子;当用于混合A通道时,使用DstColor的A分量作为混合因子。 |
DstAlpha | 因子为目标颜色的透明度值(A通道) |
OneMinusSrcColor | 因子为(1-源颜色)。当用于混合RGB的混合等式时,使用结果的RGB分量作为混合因子;当用于混合A的混合等式时,使用结果的A分量作为混合因子 |
OneMinusSrcAlpha | 因子为(1-源颜色的透明度值) |
OneMinusDstColor | 因子为(1-目标颜色)。当用于混合RGB的混合等式时,使用结果的RGB分量作为混合因子;当用于混合A的混合等式时,使用结果的A分量作为混合因子 |
OneMinusDstAlpha | 因子为(1-目标颜色的透明度值) |
当我们希望使用不同的参数混合A通道时,可以利用Blend SrcFactor DstFactor,SrcFactorA DstFactorA
案例:(输出颜色的透明度值就是源颜色的透明度值)
Blend SrcAlpha OneMinusSrcAlpha,One Zero
混合操作命令
操作 | 描述 |
---|---|
Add | 将混合后的源颜色和目的颜色相加。默认的混合操作。使用的混合等式是: Orbg = SrcFactor * Srgb + DstFactor * Drgb Oa = SrcFactorA * Sa + DstFactorA * Da |
Sub | 用混合后的源颜色减去混合后的目的颜色,使用的混合等式是: Orbg = SrcFactor * Srgb - DstFactor * Drgb Oa = SrcFactorA * Sa - DstFactorA * Da |
RevSub | 用混合后的目的颜色减去混合后的源颜色,使用的混合等式是: Orbg =DstFactor * Drgb - SrcFactor * Srgb Oa =DstFactorA * Da - SrcFactorA * Sa |
Min | 使用源颜色和目的颜色中较小的值,是逐分量比较的。使用的混合等式是: Orgba = (min(Sr , Dr) , min(Sg , Dg) , min(Sb , Db) , min(Sa , Da)) |
Max | 使用源颜色和目的颜色中较大的值,是逐分量比较的。使用的混合等式是: Orgba = (max(Sr , Dr) , max(Sg , Dg) , max(Sb , Db) , max(Sa , Da)) |
Blend SrcAlpha OneMinusSrcAlpha //正常(normal),即透明度混合
Blend OneMinusDstColor One //柔和相加(Soft Additive)
Blend DstColor Zero //正片叠底(Multiply) , 即相乘
//变暗(Darken)
BlendOp Min
Blend One One
//变亮(Lighten)
BlendOp Max
Blend One One
Blend OneMinusDstColor One //滤色(Screen)
Blend One OneMinusSrcColor //滤色(Screen)
Blend One One //线性减淡(Linear Dodge)
Cull Back | Front | Off //设置剔除哪个面的渲染图元