Unity3d 如何使三维对象在墙后可见,但在墙后和地下不可见

Unity3d 如何使三维对象在墙后可见,但在墙后和地下不可见,unity3d,shader,hlsl,cg,Unity3d,Shader,Hlsl,Cg,首先,我想说我的着色器编码知识非常有限。我知道基本知识,我最终能够理解着色器的工作原理,但仅此而已 请看下图: 我在上面的场景中有4个对象。地面(米色),左侧的一个红色立方体位于地面上方,右侧的一个红色立方体位于地面上方和下方,两个立方体前面有一面墙(蓝色)。红色立方体仅在墙后渲染,因此如果我要删除墙,它们将不可见 我想要实现的是,当红色立方体在墙后面时,它是可见的,而不是在地下的区域。因此,右立方体应该只渲染顶部的红色部分,而不是底部的米色部分。我假设底部的米色部分是墙后面立方体所在区域的地

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

请看下图:

我在上面的场景中有4个对象。地面(米色),左侧的一个红色立方体位于地面上方,右侧的一个红色立方体位于地面上方和下方,两个立方体前面有一面墙(蓝色)。红色立方体仅在墙后渲染,因此如果我要删除墙,它们将不可见

我想要实现的是,当红色立方体在墙后面时,它是可见的,而不是在地下的区域。因此,右立方体应该只渲染顶部的红色部分,而不是底部的米色部分。我假设底部的米色部分是墙后面立方体所在区域的地面渲染

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

立方体:

理由:

墙:

为了给你一个场景,我将使用类似的东西,想象一个RTS游戏,你希望墙后面的单位或其他对象是可见的,所以立方体着色器将像一个轮廓或轮廓着色器。现在想象一下,你也希望这些单位通过进入地下来隐藏。目前,如果他们进入地下,但也在墙后,他们将是可见的


提前非常感谢

如果其他人遇到这个问题,答案已发布在此处:

这是更新的着色器:

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
        }
    }
}
Shader“ZTest Shaders/Cube”
{
性质
{
ObjectColor(“对象颜色”,颜色)=(1,1,1,1)
}
子阴影
{
标签{
“队列”=“透明+10”
}
通过
{
写在
ZTest大酒店
CGP程序
#pragma顶点顶点
#布拉格碎片碎片
#包括“UnityCG.cginc”
结构appdata
{
浮动4顶点:位置;
};
结构v2f
{
固定颜色4:颜色;
浮动4顶点:SV_位置;
浮动3世界位置:TEXCOORD0;
};
均匀固定4色;
v2f垂直(appdata v)
{
v2fo;
o、 顶点=UnityObjectToClipPos(v.vertex);
o、 颜色=对象颜色;
o、 worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
返回o;
}
固定4框架(v2f i):SV_目标
{
如果(i.worldPos.y<0.0)丢弃;
返回i.颜色;
}
ENDCG
}
}
}

如果其他人遇到此问题,答案已发布在此处:

这是更新的着色器:

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
        }
    }
}
Shader“ZTest Shaders/Cube”
{
性质
{
ObjectColor(“对象颜色”,颜色)=(1,1,1,1)
}
子阴影
{
标签{
“队列”=“透明+10”
}
通过
{
写在
ZTest大酒店
CGP程序
#pragma顶点顶点
#布拉格碎片碎片
#包括“UnityCG.cginc”
结构appdata
{
浮动4顶点:位置;
};
结构v2f
{
固定颜色4:颜色;
浮动4顶点:SV_位置;
浮动3世界位置:TEXCOORD0;
};
均匀固定4色;
v2f垂直(appdata v)
{
v2fo;
o、 顶点=UnityObjectToClipPos(v.vertex);
o、 颜色=对象颜色;
o、 worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
返回o;
}
固定4框架(v2f i):SV_目标
{
如果(i.worldPos.y<0.0)丢弃;
返回i.颜色;
}
ENDCG
}
}
}

一种方法是比较输出颜色,如果它不是红色,则不输出任何内容,但我不太确定如何编写它以使其工作:(.如果你看右边的立方体,它一半在地上,一半在地下,顶部打印为红色,这就是我想要保留的全部内容。如果其他人遇到这个问题,答案已经发布在这里:一个想法可能是比较输出颜色,如果它不是红色,则不输出任何内容,但我不太确定如何写不(如果你看右边的立方体,它一半在地上,一半在地下,顶部打印为红色,这就是我想保留的全部内容。如果其他人遇到这个问题,答案已发布在这里:
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
        }
    }
}
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
        }
    }
}