Unity Shader之AlphaTest透明度测试及正确的阴影

AlphaTest 透明度测试

1.顶点片源着色器实现介绍:

**透明度测试核心原理:

对于Alpha透明通道小于阈值的片元直接舍弃掉,被舍弃掉的这些片元不会对颜色缓冲产生影响,也不会在进行任何处理

下面是两种舍弃阀值外的片元方式:

				//裁掉Alpha小于0的片元
				 clip(texColor.a-_Cutoff);
				//裁掉Alpha小于0的片元
                if(texColor.a-_Cutoff<0)
                {
                    discard;
                }

透明度测试缺点:

透明度测试得到的效果,要么完全透明,要么不透明,不能像透明度混合那样,进行渐渐透明。且得到的透明度效果在边缘处往往参差不齐,有锯齿,这是因为在边界处纹理的透明度的变化精度问题。

Tags

使用了透明度测试的 Shader 都应该在SubShader 中设置这三个标签

Tags { "Queue"="AlphaTest" "RenderType"="TransparentCutout" "IgnoreProjector"="True"}

说明:

"Queue"="AlphaTest"开启透明度测试
"RenderType"="Transparent" 指明该shader是一个使用了透明度的Shader。
"IgnoreProjector"="True" 这个shader忽略投影器(Projectors)的影响。

注意事项:
1.Fallback "Transparent/Cutout/VertexLit"是不能少的,因为我们在处理阴影时他能起到很大的作用。

2.若要该物体附带阴影,需要声明属性 _Cutoff 因为Fallback的 VertexLit Shader在计算透明度测试时使用了**_Cutoff**属性,因此我们的属性中必须要包含 _Cutoff 这个属性,否则会导致无法正常使用阴影功能。

3.若需阴影跟随物体透明化,如下图, 需在属性中声明 _Color 属性,同理Fallback的 VertexLit Shader在计算阴影时使用到了这个属性,否则会导致阴影无法跟随物体透明化。

下图的透明度测试效果图 展示了 通过舍弃alpha通道小于0的片元,实现物体透明效果,以及透明通道的阴影的裁切效果。

点光源+平行光下的阴影
下面附上源shader:

Shader "Unlit/Unity_AlphaTest"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Cutoff("Alpha Cutoff",Range(0,1))=0.5
        _Color("Diffuse",Color) =(1,1,1,1)
    }
    SubShader
    {
        Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="Transparent"}
        LOD 100

        Pass
        {
            Tags{"LightMode"="ForwardBase"}  
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #include "AutoLight.cginc"


            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed _Cutoff; 
            //由于"Transparent/Cutout/VertexLit" 在计算透明阴影时使用了_Color属性 因此我们的Shader中必须包含为_Color的属性 否则阴影无法进行透明化 
            fixed4 _Color;


            struct v2f
            {
                float4 vertex:SV_POSITION;
                float2 uv:TEXCOORD0;
                float3 worldNomal:TEXCOORD1;
                float3 worldPos:TEXCOORD2;
                SHADOW_COORDS(3)
            };

   

            v2f vert (appdata_base v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.worldNomal=UnityObjectToWorldNormal(v.normal);
                o.worldPos=mul(unity_ObjectToWorld,v.vertex);
                //计算阴影纹理坐标
		        TRANSFER_SHADOW(o);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {

                float3 worldNomalDir=normalize(i.worldNomal);
                float3 worldLightDir=normalize(UnityWorldSpaceLightDir(i.worldPos));
                //主贴入图采样
                float4 texColor=tex2D(_MainTex,i.uv);
                float3 albedo=texColor.rgb*_Color.rgb;
                //裁掉透明像素
                //clip(texColor.a-_Cutoff);
                if(texColor.a-_Cutoff<0)
                {
                    discard;
                }
                //提升主UV的反照率 相当于提升清晰度
                fixed3 amnient= UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
                //计算光照衰减
                UNITY_LIGHT_ATTENUATION(atten, i,i.worldPos);
                //计算漫反射
                float3 diffuse=_LightColor0.rgb*albedo*(dot(worldNomalDir,worldLightDir)*0.5+0.5);

                float3 color=diffuse+amnient*atten;

                return fixed4(color,1.0);
            }
            ENDCG
        }
    }
    Fallback "Transparent/Cutout/VertexLit"
}

2.surfaceShader实现介绍:
相比之下使用surface Shader实现更为简单快速,我们基本不用写shader代码,因为我们所需要的功能surfaceShader 都已经给我们提供好了,我们只需要配置下指示命令即可。
配置如下:

// alphatest:_CutOff 根据变量名字来控制透明度混合和透明度测试
//addShadow 给当前透明通道物体使用阴影
//noshadow 关闭自身接收阴影 根据选择开关
#pragma surface surf Standard alphatest:_CutOff addshadow noshadow

开启效果如下图:
在这里插入图片描述
未开启深度测试:
在这里插入图片描述

源码如下:

Shader "Custom/AlphaTest"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _CutOff("CutOut",Range(0,1))=0
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue"="AlphaTest" }
        LOD 200
        Cull Off
 
        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        // alphatest:_CutOff 根据变量名字来控制透明度混合和透明度测试 
        //addShadow 给当前透明通道物体使用阴影  
        //noshadow  关闭自身接收阴影  根据选择开关
        #pragma surface surf Standard  alphatest:_CutOff addshadow noshadow 

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

努力积才能,壹叶便成名!

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铸梦xy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值