如何实现可隐藏自身重叠、支持穿模可见的Unity Oculus手部透明Shader
Unity Oculus手部透明Shader修复方案
你需要的是在保留ZTest Always的前提下避免手部自身面片重叠导致的透明异常,可通过模板缓冲标记或者深度预写入两种方案实现,以下是具体实现代码和说明:
方案1:模板缓冲方案(推荐,不影响多手交互)
代码实现
Shader "Custom/TransparentOculusHand" { Properties{ _Color("Main Color", Color) = (1,1,1,1) _MainTex("Base (RGB) Trans (A)", 2D) = "white" {} } SubShader{ Tags {"RenderType" = "Transparent" "Queue" = "Transparent" } Blend SrcAlpha OneMinusSrcAlpha ZTest Always ZWrite Off // 新增模板缓冲配置,避免同一只手重复绘制 Stencil { Ref 1 Comp NotEqual Pass Replace } Pass { ColorMask 0 } UsePass "Transparent/Diffuse/FORWARD" } Fallback "Transparent/VertexLit" }
逻辑说明
- 模板缓冲会为每个绘制过手部的像素标记为1,后续同位置的手部面片检测到标记就会跳过绘制,从根源避免自身重叠导致的透明度叠加
- 完全保留
ZTest Always配置,手部穿模到固体物体后方时仍然可见 - 多手同时显示时,只需给左右手材质分别设置不同的
Ref值(如左手1、右手2)即可避免交叉剔除问题
方案2:深度预写入方案
代码实现
Shader "Custom/TransparentOculusHand" { Properties{ _Color("Main Color", Color) = (1,1,1,1) _MainTex("Base (RGB) Trans (A)", 2D) = "white" {} } SubShader{ Tags {"RenderType" = "Transparent" "Queue" = "Transparent" } Blend SrcAlpha OneMinusSrcAlpha // 预写入Pass:仅写入手部自身正确深度,不输出颜色 Pass { ZWrite On ColorMask 0 ZTest LEqual } // 透明绘制Pass:保留ZTest Always实现穿模可见 Pass { ZTest Always ZWrite Off SetTexture [_MainTex] { constantColor [_Color] combine texture * constant } } } Fallback "Transparent/VertexLit" }
逻辑说明
- 第一个Pass先把手部最靠近相机的面片深度写入缓冲,确定手部自身的前后遮挡关系
- 第二个透明绘制Pass只会和预写入的深度匹配,仅绘制最外层的手部面片,不会出现自身重叠异常
内容的提问来源于stack exchange,提问作者María Román
相关产品推荐
相关产品推荐

