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

Unity VR HDRP中可遮罩且渲染于GameObject前的World Space UI问题

解决方案:VR HDRP下World Space HUD的遮罩与置顶渲染

核心逻辑

利用**模板缓冲(Stencil Buffer)**实现HUD的区域遮罩,同时通过渲染队列和深度测试设置让HUD显示在所有物体之上。具体分为两步:让玻璃面板在模板缓冲中标记出可视区域,再让HUD仅在标记区域内渲染。

步骤1:定制遮罩与HUD的Shader

玻璃面板的遮罩Shader

这个Shader会在模板缓冲中写入标记值,只有遮罩图片alpha符合阈值的区域才会被标记:

Shader "Custom/HUDMask"
{
    Properties
    {
        _MainTex ("遮罩纹理", 2D) = "white" {}
        _MaskCutoff ("遮罩阈值", Range(0,1)) = 0.5
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue"="Transparent" }
        LOD 100

        // 模板设置:将符合条件的区域标记为1
        Stencil
        {
            Ref 1
            Comp Always
            Pass Replace
        }

        HLSLINCLUDE
        #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl"
        ENDHLSL

        Pass
        {
            Name "Forward"
            Tags { "LightMode" = "Forward" }

            Blend SrcAlpha OneMinusSrcAlpha
            ZWrite Off
            ZTest LEqual

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            struct Attributes
            {
                float4 positionOS : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct Varyings
            {
                float4 positionHCS : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _MaskCutoff;

            Varyings vert(Attributes input)
            {
                Varyings output;
                output.positionHCS = TransformObjectToHClip(input.positionOS.xyz);
                output.uv = TRANSFORM_TEX(input.uv, _MainTex);
                return output;
            }

            half4 frag(Varyings input) : SV_Target
            {
                half4 col = tex2D(_MainTex, input.uv);
                // 裁剪遮罩区域,只有alpha大于阈值的部分才会写入模板缓冲
                clip(col.a - _MaskCutoff);
                return col;
            }
            ENDHLSL
        }
    }
}

HUD元素的Shader

这个Shader会跳过深度测试(确保显示在所有物体之上),同时只在模板缓冲标记为1的区域内渲染:

Shader "Custom/WorldSpaceHUD"
{
    Properties
    {
        _MainTex ("纹理", 2D) = "white" {}
        _Color ("色调", Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue"="Overlay" } // Overlay队列确保最后渲染
        LOD 100

        // 模板测试:仅在标记为1的区域渲染
        Stencil
        {
            Ref 1
            Comp Equal
        }

        HLSLINCLUDE
        #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl"
        ENDHLSL

        Pass
        {
            Name "Forward"
            Tags { "LightMode" = "Forward" }

            Blend SrcAlpha OneMinusSrcAlpha
            ZWrite Off
            ZTest Always // 关闭深度测试,强制显示在所有物体之上

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            struct Attributes
            {
                float4 positionOS : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct Varyings
            {
                float4 positionHCS : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _Color;

            Varyings vert(Attributes input)
            {
                Varyings output;
                output.positionHCS = TransformObjectToHClip(input.positionOS.xyz);
                output.uv = TRANSFORM_TEX(input.uv, _MainTex);
                return output;
            }

            half4 frag(Varyings input) : SV_Target
            {
                half4 col = tex2D(_MainTex, input.uv) * _Color;
                return col;
            }
            ENDHLSL
        }
    }
}

步骤2:场景配置

  • 将World Space Canvas放置在飞行器前方足够远的位置,缩放至合适大小模拟无限视距。
  • 创建玻璃面板(如Plane),赋予Custom/HUDMask Shader,将遮罩图片赋值给_MainTex,调整_MaskCutoff控制遮罩的生效范围。
  • 把Canvas内所有HUD元素(Text、Image等)的材质替换为Custom/WorldSpaceHUD,确保它们使用定制Shader。
  • 将玻璃面板绑定到VR相机的子对象,固定在视野前方的特定位置——只有当头部处于正确姿态时,遮罩区域才会覆盖HUD的可视范围。

关键注意事项

  • 确保玻璃面板的渲染队列(Transparent)早于HUD的渲染队列(Overlay),这样模板缓冲会先被遮罩标记,再被HUD读取。
  • 如果HDRP下Shader出现兼容性问题,可直接复制HDRP内置的UI/Default Shader代码,再添加模板测试和深度测试的修改,保证管线兼容。
  • VR模式下,可通过脚本动态调整玻璃面板的激活状态或位置,进一步优化头部位置的判定逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 16:07:06