unity shader-透明效果

深度测试:

实现效果:

透明度测试

将纹理图片中的小于0.5的部分剔除掉,所以我们看到黑色的边缘不见了。
代码:

透明度测试的Tags设置为
Tags{“Queue”=“AlphaTest” “IgnoreProjector”=“True” “RenderType”=“TransparentCutout”}
分别表示渲染顺序为深度测试,忽略物体的阴影影响,渲染的模式是TransparentCutout

Shader "Custom/Chapter8-AlphaTest"
{
    Properties{
        _Color("Color Tint",color)=(1,1,1,1)
        _MainTex("Main Tex",2D)="white"{}
        //透明度测试范围
        _Cutoff("Alpha Cutoff",Range(0,1))=0.5
    }

    SubShader{
        //第一个是透明度测试队列,第二个是不受投射器的影响,第三个指定这个shader用了透明度测试
        Tags{"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}

        Pass{
            Tags{"LightMode"="ForwardBase"}

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.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;
                float4 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);
                o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
                return o;
            }

            fixed4 frag(v2f i):SV_Target{
                fixed3 worldNormal =normalize(i.worldNormal);
                fixed3 lightDir =normalize(UnityWorldSpaceLightDir(i.worldPos));

                fixed4 texColor =tex2D(_MainTex,i.uv);
                //判断透明度
                //如果小于_Cutoff则舍弃片元
                //如果大于则当成不透明物体
                clip(texColor-_Cutoff);

                fixed3 albedo =texColor.rgb*_Color.rgb;
                fixed3 ambient0 =UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
                fixed3 diffuse0 =_LightColor0.rgb*albedo*saturate(dot(worldNormal,lightDir));

                return fixed4(ambient0+diffuse0,1.0);
            }
            ENDCG
        }
    }
    FallBack "Transparent/Cutout/VertexLit"
}

透明度混合

实现效果:

unity shader透明度混合

代码:

透明度混合的Tags设置
Tags{“Queue”=“Transparent” “IgnoreProjector”=“True” “RenderType”=“Transparent”}

Shader "Custom/Chapter8_8_4"
{
    Properties{
        _Color("Color Tint",color)=(1,1,1,1)
        _MainTex("Main Tex",2D)="white"{}
        //透明度
        _AlphaScale("Alpha Scale",Range(0,1))=1
    }

    SubShader{
        //第一个是透明度混合队列,第二个是不受投射器的影响,第三个指定这个shader用了透明度测试
        Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}

        Pass{
            Tags{"LightMode"="ForwardBase"}
            //深度写入关闭
            ZWrite Off
            //混合因子
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.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;
                float4 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);
                o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
                return o;
            }

            fixed4 frag(v2f i):SV_Target{
                fixed3 worldNormal =normalize(i.worldNormal);
                fixed3 lightDir =normalize(UnityWorldSpaceLightDir(i.worldPos));

                fixed4 texColor =tex2D(_MainTex,i.uv);

                fixed3 albedo =texColor.rgb*_Color.rgb;
                fixed3 ambient0 =UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
                fixed3 diffuse0 =_LightColor0.rgb*albedo*saturate(dot(worldNormal,lightDir));

                //透明度由纹理的透明度和透明度系数混合
                return fixed4(ambient0+diffuse0,texColor.a*_AlphaScale);
            }
            ENDCG
        }
    }
    FallBack "Transparent/VertexLit"
}

开启深度写入的透明度混合

没有深度写入的话,会产生一些排序错误而产生的错误的透明效果。
解决方法:
使用两个pass:

  1. 第一个Pass开启深度写入,但是不输出颜色,目的是为了把模型的深度信息写入深度缓冲中。
  2. 第二个Pass进行正常的透明度混合

实现效果:
在这里插入图片描述

代码:

Shader "Custom/NewSurfaceShader"
{
    Properties{
        _Color("Color Tint",color)=(1,1,1,1)
        _MainTex("Main Tex",2D)="white"{}
        //透明度
        _AlphaScale("Alpha Scale",Range(0,1))=1
    }

    SubShader{
        //第一个是透明度混合队列,第二个是不受投射器的影响,第三个指定这个shader用了透明度测试
        Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
        Pass{
            ZWrite On
            //ColorMask为0意味着不写入任何颜色通道
            ColorMask 0
        }
        Pass{
            Tags{"LightMode"="ForwardBase"}
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.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;
                float4 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);
                o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
                return o;
            }

            fixed4 frag(v2f i):SV_Target{
                fixed3 worldNormal =normalize(i.worldNormal);
                fixed3 lightDir =normalize(UnityWorldSpaceLightDir(i.worldPos));

                fixed4 texColor =tex2D(_MainTex,i.uv);

                fixed3 albedo =texColor.rgb*_Color.rgb;
                fixed3 ambient0 =UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
                fixed3 diffuse0 =_LightColor0.rgb*albedo*saturate(dot(worldNormal,lightDir));

                return fixed4(ambient0+diffuse0,texColor.a*_AlphaScale);
            }
            ENDCG
        }
    }
    FallBack "Transparent/VertexLit"
}

双面渲染的透明效果

在之前的渲染中我们可以看到我们只能看到表面的效果,但是看不到cube的内部以及背面的效果,这是因为在默认的情况下,渲染是剔除了背面的,如果我们想要得到更加真实的效果,我们需要对背面也进行渲染。
实现方式:
使用两个Pass,一个Pass渲染前面,另外一个渲染背面。
实现效果:

双面渲染的透明度混合

代码:

Shader "Custom/Chapter8-AlphaBlendBothSided"
{
    Properties{
        _Color("Color Tint",color)=(1,1,1,1)
        _MainTex("Main Tex",2D)="white"{}
        //透明度
        _AlphaScale("Alpha Scale",Range(0,1))=1
    }

    SubShader{
        //第一个是透明度混合队列,第二个是不受投射器的影响,第三个指定这个shader用了透明度测试
        Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}

         Pass{
            Tags{"LightMode"="ForwardBase"}
            ZWrite Off
            //剔除前面的渲染,只渲染背对着摄像头的
            Cull Front
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.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;
                float4 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);
                o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
                return o;
            }

            fixed4 frag(v2f i):SV_Target{
                fixed3 worldNormal =normalize(i.worldNormal);
                fixed3 lightDir =normalize(UnityWorldSpaceLightDir(i.worldPos));

                fixed4 texColor =tex2D(_MainTex,i.uv);

                fixed3 albedo =texColor.rgb*_Color.rgb;
                fixed3 ambient0 =UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
                fixed3 diffuse0 =_LightColor0.rgb*albedo*saturate(dot(worldNormal,lightDir));

                return fixed4(ambient0+diffuse0,texColor.a*_AlphaScale);
            }
            ENDCG
        }
        Pass{
            Tags{"LightMode"="ForwardBase"}
            //剔除背对摄像头的,只渲染前面的
            Cull Back
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.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;
                float4 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);
                o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
                return o;
            }

            fixed4 frag(v2f i):SV_Target{
                fixed3 worldNormal =normalize(i.worldNormal);
                fixed3 lightDir =normalize(UnityWorldSpaceLightDir(i.worldPos));

                fixed4 texColor =tex2D(_MainTex,i.uv);

                fixed3 albedo =texColor.rgb*_Color.rgb;
                fixed3 ambient0 =UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
                fixed3 diffuse0 =_LightColor0.rgb*albedo*saturate(dot(worldNormal,lightDir));

                return fixed4(ambient0+diffuse0,texColor.a*_AlphaScale);
            }
            ENDCG
        }
    }
    FallBack "Transparent/VertexLit"
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值