【本系列文章系学习 唐福幸《Unity ShaderLab 新手宝典》的笔记,包含个人理解,如有错误欢迎批评指出
一句话总结:之前的混合透明是渲染顺序加上贴图透明度实现透明效果,这次透明测试是通过图片的透明通道来剔除透明部分。前者要考虑物体前后的渲染,后者要考虑图片的锯齿以及无法半透明
7.4 透明测试
7.4.1透明测试
遇到像树叶,栏杆这种部分透明,部分不透明的情况:如果继续使用混合透明方式,在延迟着色器渲染路径中物体将无法接受投影,凸起或重叠会出现渲染顺序错误的问题
存在问题:
透明度测试得到的透明效果比较极端——要么全部透明,要么全部不透明,得到的透明效果由于在边界处纹理的透明度的变化精度导致在边缘上往往处理不到位,存在锯齿的情况。
代码模板:
SubShader
{
Tags
{
"Queue" = "AlphaTest"
"RenderType" = "TransparentCutout"
"IgnoreProjector" = "True"
}
Pass
{
CGPROGRAM
//CG代码
clip(textureColor.a - alphaCutoffValue);
//CG代码
ENDCG
}
}
在Lambert基础上修改
Shader "Chapter7/TransImg5"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_AlphaTest("Alpha Test", Range(0,1)) = 0
}
SubShader
{
Tags
{
"Queue" = "AlphaTest"
"RenderType"="TransparentCutuot"
"IgnoreProjector" = "True"
}
Pass
{
Tags{"LightMode" = "ForwardBase"}
Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
#include "UnityLightingCommon.cginc"
struct v2f
{
float4 worldPos : TEXCOORD0;
float4 pos : SV_POSITION;
float2 texcoord : TEXCOORD1;
float3 worldNormal : TEXCOORD2;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _AlphaTest;
v2f vert (appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld,v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
float3 worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldNormal = normalize(worldNormal);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float3 worldLight = UnityWorldSpaceLightDir(i.worldPos.xyz);
worldLight = normalize(worldLight);
fixed Ndotl = saturate(dot(i.worldNormal, worldLight));
fixed4 color = tex2D(_MainTex, i.texcoord);
clip(color.a - _AlphaTest);//开启Alpha测试, 利用Alpha通道信息剔除透明部分,其他不变
color.rgb *= Ndotl * _LightColor0;
color.rgb += unity_AmbientSky;
return color;
}
ENDCG
}
}
}
完成shader编写,附到材质上后,还要调一下_AlphaTest的值(大于0即可),因为clip()指令必须小于0才能产生透明效果
与混合透明(左)效果对比
注:测试图片是带有alpha通道的tga贴图
7.2抗锯齿
当把_AlphaTest值调大后,把图片放大后会在交界处出现许许多多的锯齿,当图片像素低时候锯齿就会很模糊
可以在Pass中添加AlphaToMask On指令开启(alpha-to-coverage)功能,提高多重采样边界覆盖范围,从而消除透明测试器上的锯齿现象(我开完没看出啥区别)