如何使用 Unity3d 着色器来屏蔽另一个两遍着色器?

问题描述

我正在开发一个游戏,我想在其中可视化用户路径 - 还显示轨道重叠的位置(比正常的“未重叠”轨道颜色更深)。很久以前,我找到了 this 答案,建议使用模板创建两遍着色器。那天很有帮助。

但最近我遇到了一个额外的要求:我想暴露一些不规则区域内的路径(网格的一部分)。对于路径的其余部分,根据运行时中的用户选择,有两个选项:

  1. 应该用任何其他不同的颜色(例如更深)进行标记
  2. 应该根本不可见。

我发现 that 答案是建议在另一个着色器中使用模板,该模板将被放置到某些网格中以创建“蒙版”。我做了一些调整,最终得到了这些着色器:

遮罩着色器:

Shader "Custom/AreaValidator"
{
    Properties
    {
        _Color ("Color",Color) = (1,1,1)
        _MainTex ("Albedo (RGB)",2D) = "white" {}
        _Glossiness ("Smoothness",Range(0,1)) = 0.5
        _Metallic ("Metallic",1)) = 0.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" "Queue"="Geometry-1" }
        ColorMask 0
        ZWrite off
        Stencil{
            Ref 3
            Comp always
            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;

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

和路径着色器:

Shader "Unlit/Path"
{
    Properties
    {
        _MainTex ("Texture",2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            Stencil {
                Ref 0
                Comp Equal
            }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = fixed4(0.545,0.780,0.341,0.8);
                return col;
            }
            ENDCG
        }

        Pass
        {
            Stencil {
                Ref 3
                Comp Equal
                Pass IncrSat
                Fail IncrSat
            }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = fixed4(0.710,0.859,0.580,1);
                return col;
            }
            ENDCG
        }

        Pass
        {
            Stencil {
                Ref 4
                Comp Less
            }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = fixed4(0.545,0.8);
                return col;
            }
            ENDCG
        }
    }
}

正如你在蒙版着色器中看到的,我有

    Stencil{
        Ref 3
        Comp always
        Pass replace
    }

但在路径着色器中,我有 3 个通道:对于“外部验证区域”、“内部验证区域 - 没有重叠”、“内部验证区域 - 重叠”。

1. 模板{ 参考 0 比较相等 }

2. 模板{ 参考文献 3 比较相等 通过 IncrSat 失败增量卫星 }

3. 模板{ 参考文献 4 比较少 }

我不完全理解着色器是如何渲染的 - 我正在展示最接近我的目标的解决方案。一般来说,它在一些简单的情况下“有效”:

  1. here - 所有轨道可见(有效区域外的颜色更深,如 在重叠期间),
  2. here - 当我从着色器代码删除负责第一次传递的完整部分时,区域外的轨道被删除 - 这很好,

但是有 3 个主要问题我无法解决

  1. First problem - 当 2 个不同的网格重叠时“闪烁/闪烁”:
  2. Another problem- 因为模板 2) 在通过/失败两种情况下都会增加缓冲区,当用户走动几次时,甚至会呈现“有效”区域之外的轨道。
  3. 第三个问题是,我不知道如何在运行时在“可见外部轨道”和“不可见外部轨道”渲染选项之间切换。

总结:

我想要一个网格:

  1. 重叠时呈现不同,
  2. 只能在特定的“遮罩”区域内渲染,
  3. 用户可以动态显示/隐藏遮罩区域外的网格,可见网格外有其他颜色,

但我不知道如何在没有故障和一些奇怪的工件的情况下实现这一目标。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)