Unity Shader入门精要 阅读笔记十二

透明效果一
一、基础

要在模型中实现透明效果,可以通过两种方式来实现:透明测试和透明混合。
透明测试:这种方式其实是通过透明度来判断哪些地方需要去渲染,如果透明度低于设定的值就不去渲染。其实这里和遮罩有点相似。透明测试主要去判断一张贴图的透明通道,然后将低于该透明通道的部分取消渲染。
透明度混合:这种方式可以实现半透明效果。

二、一些关键词
深度缓冲(z-buffer):深度缓冲对应深度测试中的一环。缓冲其实是指对应内存空间的一块区域。
深度写入(z-write):是指能够写入深度缓冲区域。如果关闭则不能写入。
深度测试(z-test):深度测试是逐片元渲染中一个测试环节,每个片元需要经过不同的测试才能被最终渲染,而深度测试就是其中之一。如果开启了深度测试,那么片元会与已有的深度缓存区进行比较。深度测试流程为:
这里写图片描述
在有透明效果的渲染流程中,深度测试的设置显得尤为重要。如果一个片元没有通过深度测试,但是我们还是能够通过配置去决定是否写入到深度缓存区。
颜色缓冲(ColorBuffer):

三、透明测试
在透明测试实现中,我们不需要去考虑是否需要关闭深度写入,可以按照不透明物体来设置。
这里写图片描述
代码:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/4.1.1" {//渐变纹理
    Properties{
        _Color("Color Tint", Color) = (1, 1, 1, 1)
        _MainTex("Main Tex",2D) = "white"{}
        _CutOff("CutOff Value",Range(0,1)) = 0.5
        }
        SubShader{
        Tags{"Queue"="AlphaTest" "IgnoreProjector" = "True" "RenderType"="TransparentCutout"}//透明度测试的标签
        Pass{
            Tags{ "LightMode" = "ForwardBase" }
            Cull Off
            CGPROGRAM

    #pragma vertex vert
    #pragma fragment frag

    #include "Lighting.cginc"

            fixed4 _Color;
            sampler2D _MainTex;
            float4 _MainTex_ST;//一张贴图就应该对应一个_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.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;//缩放后再位移

                //为之后计算凹凸纹理做准备先将光线和视线方向转到切线空间
                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 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
                fixed4 texColor = tex2D(_MainTex, i.uv);

                //开始剔除
                clip(texColor.a - _CutOff);
                fixed3 albedo = texColor.rgb * _Color;
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;//环境光

                fixed3 diffuse = _LightColor0.rgb * ambient * max(0, dot(worldNormal, lightDir));//漫反射

                return fixed4(ambient + diffuse, 1.0);
            }

        ENDCG
    }
    }
        FallBack "Specular"
}

与之前计算漫反射效果不同的是,这里添加了一句:clip(texColor.a - _CutOff);
这一句话决定,低于某个值的片元将会被剔除,因此才有了上图效果。相比于书上的例子,我这里添加了一句Cull Off来实现双面渲染效果。这样看起来会更好一些。

在透明效果实现的时候我们会强调关闭深度写入,注意渲染队列等

猜你喜欢

转载自blog.csdn.net/u011618339/article/details/79372677