如何使 3d 对象在墙后可见,但在墙后和地下不可见

How to make 3d object visible behind wall, but invisible if behind wall and under ground

首先我想说我的着色器编码知识非常有限。我知道基础知识,我最终可以理解着色器的工作原理,但仅此而已。

请看下图:

我在上面的场景中有 4 个对象。地面(米色),左侧有一个红色立方体,高于地面,右侧有一个红色立方体,一半在地上,一半在地下,两个立方体前面有一堵墙(蓝色)。红色立方体只有在墙后面时才会渲染,所以如果我要删除墙,它们就会变得不可见。

我想要实现的是让红色立方体在墙后可见,而不是地下区域。所以正确的立方体应该只渲染顶部的红色部分而不是底部的米色部分。我假设底部的米色部分是立方体后面区域墙后的地面渲染。

这是我正在使用的 3 个着色器:

立方体:https://pastebin.com/msuyi1zj

Shader "ZTest Shaders/Cube"
{
    Properties
    {
        ObjectColor("Object Color", Color) = (1, 1, 1, 1)
    }
    SubShader
    {
        Tags {
            "Queue" = "Transparent+10"
        }

        Pass
        {

            ZWrite On
            ZTest Greater

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                fixed4 color : COLOR;
                float4 vertex : SV_POSITION;
            };

            uniform fixed4 ObjectColor;

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

            fixed4 frag (v2f i) : SV_Target
            {
                return i.color;
            }
            ENDCG
        }
    }
}

地面:https://pastebin.com/ttL45Gjm

Shader "ZTest Shaders/Ground"
{
    Properties
    {
        ObjectColor("Object Color", Color) = (1, 1, 1, 1)
    }
    SubShader
    {
        Tags {
            "Queue" = "Transparent+15"
        }

        Pass
        {

            ZWrite On
            ZTest Less

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                fixed4 color : COLOR;
                float4 vertex : SV_POSITION;
            };

            uniform fixed4 ObjectColor;

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

            fixed4 frag (v2f i) : SV_Target
            {
                return i.color;
            }
            ENDCG
        }
    }
}

墙:https://pastebin.com/QcL0uY8j

Shader "ZTest Shaders/Wall"
{
    Properties
    {
        ObjectColor("Object Color", Color) = (1, 1, 1, 1)
    }
    SubShader
    {
        Tags {
            "Queue" = "Transparent+5"
        }

        Pass
        {

            ZWrite On

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                fixed4 color : COLOR;
                float4 vertex : SV_POSITION;
            };

            uniform fixed4 ObjectColor;

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

            fixed4 frag (v2f i) : SV_Target
            {
                return i.color;
            }
            ENDCG
        }
    }
}

为了给你一个场景,我会使用这样的东西,想象一个 RTS 游戏,你希望墙壁或其他物体后面的单位可见,这样立方体着色器就像轮廓或轮廓着色器。现在想象一下,您还希望这些单位通过地下隐藏起来。目前,如果他们去地下但也在墙后,他们将是可见的。

非常感谢您!

如果其他人遇到这个问题,答案已发布在这里:https://forum.unity.com/threads/need-help-with-my-outline-shaders-visibility-behind-walls.718499/

这是更新后的着色器:

Shader "ZTest Shaders/Cube"
{
    Properties
    {
        ObjectColor("Object Color", Color) = (1, 1, 1, 1)
    }
    SubShader
    {
        Tags {
            "Queue" = "Transparent+10"
        }

        Pass
        {

            ZWrite On
            ZTest Greater

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                fixed4 color : COLOR;
                float4 vertex : SV_POSITION;
                float3 worldPos : TEXCOORD0;
            };

            uniform fixed4 ObjectColor;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.color = ObjectColor;
                o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                if (i.worldPos.y < 0.0) discard;
                return i.color;
            }
            ENDCG
        }
    }
}