Shader

ShadersRoom - Stencil Buffer

2019-11-20  本文已影响0人  雨天到处晃

老规矩,先上一张效果图:

Stencil.gif

这个功能效果的核心点是模板缓存Stencil buffer,和深度缓存类似,模板缓存可以为屏幕上的每个像素点保存一个无符号整数值(通常的话是个8位整数,范围0-255),通过比较这个数值可以控制是否需要更新当前像素的颜色缓存,这个过程叫做模板测试,默认情况下,总是测试通过的,可以通过以下参数来控制这个过程:

好了,有了上述的介绍,再回到场景中,场景分为3个部分,蓝色的区域,黑色的区域和连接两个区域的门,
首先是门,负责显示玩家可以进入的场景,所以门主要的功能就是:把屏幕上对应位置的Ref值刷新为进入的场景的Ref值,本身不需要显示任何颜色;
然后是两个场景,分别有不同的Ref值(黑色场景的Ref为1,蓝色场景的Ref为2)。

下面开始具体的实现,以玩家处于蓝色场景,将要进入黑色场景为例,首先新建3个Surface Shader分别对应蓝色场景,黑色场景,门:

//在SubShader中添加
        stencil
        {
            ref 2
            comp Always
        }

·

//在SubShader中添加
        stencil
        {
            ref 1
            comp Equal
        }

·

//在SubShader中添加
        Zwrite off   //关闭写入深度,防止在深度测试中将门后的场景覆盖
        Cull off     //开启双面显示
        Colormask 0  //屏蔽颜色的输出
        stencil
        {
            Ref 1
            Comp Alawys
            Pass replace  //测试通过则将stencilBufferValue刷新为1
        }

到这一步,就实现了一个静态的效果:从蓝色场景看到门中的黑色场景。

1.png

接下来是动态的实现,穿越了门后,黑色场景全部显示,而蓝色场景则可以从门中看到:

        //新增属性
        _RefValue("Ref",range(0,255)) = 0
        [Enum(UnityEngine.Rendering.CompareFunction)]_StencilComp("Stencil Comp",float) = 3
        //修改stencil
        stencil
        {
            ref [_RefValue]    //替换成修改后的属性
            comp [_StencilComp]   //替换成修改后的属性
            pass replace
        }
         //新增属性
        [Enum(UnityEngine.Rendering.CompareFunction)]_RefValue("Ref Valus",int) = 3
        stencil
        {
            ref 2
            comp [_RefValue]    //替换成新增属性
        }

if(cameraPostionInPortalSpace.z < -0.3) //表示在scene2这边
        {
            scene2Mat.SetInt("_RefValue", (int)CompareFunction.Always);
            scene1Mat.SetInt("_RefValue", (int)CompareFunction.Equal);
            portalMat.SetInt("_RefValue", 1);
        }
        else if (cameraPostionInPortalSpace.z >0.3) //表示在scene1这边
        {
            scene2Mat.SetInt("_RefValue", (int)CompareFunction.Equal);
            scene1Mat.SetInt("_RefValue", (int)CompareFunction.Always);
            portalMat.SetInt("_RefValue", 2);
        }
        else    //这里表示在门口附近,两边场景都需要显示
        {
            scene2Mat.SetInt("_RefValue", (int)CompareFunction.Always);
            scene1Mat.SetInt("_RefValue", (int)CompareFunction.Always);
        }

最后附上完整的shader:
·

Shader "ShadersRoom/StencilPortal" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0

        _RefValue("Ref",range(0,255)) = 0
        [Enum(UnityEngine.Rendering.CompareFunction)]_StencilComp("Stencil Comp",float) = 3
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
        zwrite off
        cull off
        colormask 0


        stencil
        {
            ref [_RefValue]
            comp [_StencilComp]
            pass replace
        }

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // 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;


        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"
}

Shader "ShadersRoom/Scene1" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
        [Enum(UnityEngine.Rendering.CompareFunction)]_RefValue("Ref Valus",int) = 1
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        stencil
        {
            ref 1
            comp [_RefValue]
        }

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // 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;


        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"
}

Shader "ShadersRoom/Scene2" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
        [Enum(UnityEngine.Rendering.CompareFunction)]_RefValue("Ref Valus",int) = 3
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        stencil
        {
            ref 2
            comp [_RefValue]
        }

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // 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;


        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"
}

上一篇 下一篇

猜你喜欢

热点阅读