You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity URP透视效果异常:物体B在A前方仍可见的解决问询

问题描述

使用Unity 2022.3.16f版本搭配URP,目标效果是透过物体A看到其后方的物体B,但当前出现异常:当物体B位于物体A前方时,仍能透过A看到B,不符合预期。

当前物体A使用的Shader代码如下:

Shader "Custom/Mask"
{
    Properties{}
 
    SubShader{
        Tags {
            "RenderType" = "Opaque"
        }
 
        Pass {
            ZWrite Off
        }
    }
}

之前参考的英文教程核心思路(已翻译为中文):利用模板缓冲实现透视物体效果,核心逻辑是先渲染遮挡物并标记模板缓冲,再让透视物体仅在模板缓冲未标记的区域显示透视效果。

解决方案

问题核心在于当前Mask Shader未正确处理深度测试与模板缓冲逻辑,导致无论物体B在A前后,都能被穿透显示。以下是修正方案:

1. 修改物体A的Mask Shader

给Shader添加深度测试和模板缓冲逻辑,确保只有A未被遮挡的区域才会标记模板缓冲,同时让深度测试正常工作,避免前方物体被穿透。

修正后的Shader代码:

Shader "Custom/StencilMask"
{
    Properties{}
 
    SubShader{
        Tags {
            "RenderType" = "Opaque"
            "Queue" = "Geometry-100" // 确保在普通几何体之前渲染
        }
 
        Pass {
            ZWrite On // 开启深度写入,保障深度测试有效性
            ZTest LEqual // 仅渲染未被遮挡的像素(当前深度之前的区域)
 
            // 模板缓冲配置:标记未被遮挡的区域
            Stencil {
                Ref 1
                Comp Always
                Pass Replace
                ZFail Keep // 被遮挡的像素不修改模板缓冲
            }
 
            ColorMask 0 // 不输出颜色,仅处理深度与模板缓冲
        }
    }
}

2. 适配物体B的透视Shader(若需特殊透视效果)

如果物体B需要在透过A时显示半透明/高亮等特殊效果,需在其Shader中添加模板缓冲读取逻辑,仅在A未被遮挡的区域后方显示透视效果:

示例透视Shader代码片段:

Shader "Custom/SeeThroughObject"
{
    Properties{
        _BaseColor("基础颜色", Color) = (1,1,1,1)
        _SeeThroughColor("透视颜色", Color) = (0,1,0,0.5)
    }
 
    SubShader{
        Tags {
            "RenderType" = "Transparent"
            "Queue" = "Geometry+100" // 在Mask之后渲染
        }
 
        // 正常渲染通道(非透视区域)
        Pass {
            ZWrite On
            ZTest LEqual
 
            Stencil {
                Ref 1
                Comp NotEqual // 仅渲染模板值≠1的区域(不在A后方的部分)
            }
 
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
            #include "UnityCG.cginc"
 
            struct appdata {
                float4 vertex : POSITION;
            };
 
            struct v2f {
                float4 pos : SV_POSITION;
            };
 
            v2f vert (appdata v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                return o;
            }
 
            fixed4 _BaseColor;
 
            fixed4 frag (v2f i) : SV_Target {
                return _BaseColor;
            }
            ENDCG
        }
 
        // 透视效果通道(透过A看到的区域)
        Pass {
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha // 开启半透明混合
 
            Stencil {
                Ref 1
                Comp Equal // 仅渲染模板值=1的区域(A后方的部分)
            }
 
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
            #include "UnityCG.cginc"
 
            struct appdata {
                float4 vertex : POSITION;
            };
 
            struct v2f {
                float4 pos : SV_POSITION;
            };
 
            v2f vert (appdata v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                return o;
            }
 
            fixed4 _SeeThroughColor;
 
            fixed4 frag (v2f i) : SV_Target {
                return _SeeThroughColor;
            }
            ENDCG
        }
    }
}

3. URP渲染管线设置检查

确保URP模板缓冲与深度纹理正常启用:

  • 打开UniversalRenderPipelineAsset设置面板
  • 在Rendering选项卡中,确认Stencil Buffer Format设置为8 bits
  • 确保相机的Depth Texture选项已勾选(若需更复杂的深度依赖逻辑)

关键逻辑说明

  • 物体A的Mask Shader优先渲染,开启深度写入与测试,仅未被遮挡的像素会将模板缓冲设为1,被遮挡像素(ZFail)保持模板值不变
  • 物体B的Shader分两个通道:正常通道渲染不在A后方的部分,透视通道仅渲染A后方的区域,从而实现「B在A前方时正常显示,B在A后方时透过A显示透视效果」的预期逻辑

内容的提问来源于stack exchange,提问作者QingYu Mu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 02:28:25