在Quest3实现MR透视遮挡
解读
Quest3的**透视模式(Passthrough)**本质是黑白+彩色双摄像头立体视觉,系统把实时画面作为背景纹理喂给Unity。
国内面试问“透视遮挡”并不是让你写OpenGL,而是考察三件事:
- 是否知道OVR API已经提供了OVRCameraRig + Passthrough Layer;
- 能否把虚拟物体正确地**“塞进”真实世界**——即深度测试(ZTest)与深度提交(Depth Submission);
- 会不会处理半透明像素、动态遮挡物和性能边界,让策划随便摆模型也不会把帧率拉爆。
一句话:用Unity2022.3 LTS + Oculus XR Plugin ≥56.0官方方案,把虚拟物体写成**“遮挡物”而不是“被遮挡物”,并打开Depth API**提交Z-Buffer,Quest3就能在端侧完成虚实深度合成。
知识点
- OVRManager.trackingOriginType = Floor 与 OVRCameraRig.usePerEyeCamera = true 的绑定关系
- OVRPassthroughLayer的projectionSurfaceType=Reconstructed时,系统会自动生成一张16-bit depth texture
- XR_OCULUS_passthrough扩展的Require Depth Submission开关:PlayerSettings→XR Plug-in Management→Oculus→Depth Sharing
- ShaderLab中ZWrite On/Off、Queue、RenderType对深度提交的影响;透明队列(3000+)默认不写深度,必须手动ZWrite On并ColorMask 0做“隐形遮罩”
- Vulkan/多视图(Multiview)下,gl_DepthRange与Unity_StereoEyeIndex的匹配,防止左右眼深度错位
- GPU耗时红线:Quest3单眼1832×1920,2.5 ms是官方建议的帧预算;遮挡物Shader里只要有一次GrabPass或alpha blend就可能超标
- 国内版号合规:如果App最终要上架Pico Store或影创等国产头显,需保留OpenXR后端切换能力,不能写死Oculus宏
答案
- 新建Unity2022.3 LTS工程,安装XR Interaction Toolkit 2.5与Oculus XR Plugin 56.0,在XR Plug-in Management里勾选Oculus并打开Depth Sharing。
- 场景里拖入OVRCameraRig,在OVRManager面板把Tracking Origin设为Floor,Use Position Tracking与Use Rotation Tracking保持默认。
- 在OVRCameraRig/TrackingSpace/CenterEyeAnchor上挂OVRPassthroughLayer,Placement=Underlay,Projection Surface Type=Reconstructed,Depth Texture Format=R16。
- 对需要遮挡真实世界的虚拟物体:
a. 创建新Shader,Tags{ "Queue"="Geometry+1" "RenderType"="Opaque" },ZWrite On,ColorMask 0,Cull Back;
b. 把该Shader赋给一个新的Material,再赋给模型;
c. 模型Layer设为PassthroughOverlay0(OVRPassthroughLayer默认层),这样系统会把它的深度值写进Depth API,而颜色不输出。 - 运行后,Quest3的Composition Engine会把虚拟深度与双目摄像头重建的真实深度做逐像素Z-Test,虚拟像素深度小的地方就挡住真实画面,实现“透视遮挡”。
- 验证:在OVR Metrics Tool里打开GPU Utilization与Depth Submission Rate,确保Depth Submission=100%且GPU<2.5 ms;若出现Depth Rejection,检查是否有透明材质误写深度或RenderQueue>2500的物体未关ZWrite。
拓展思考
- 动态遮挡网格:策划想在运行时把桌子任意挪动,可以在Awake()时给桌子挂OVRMeshRenderer+OVRPassthroughMesh,把meshFilter.sharedMesh提交到OVRPassthroughLayer.AddSurfaceGeometry(),这样遮挡体随真实物体一起动,无需每帧回读深度。
- 混合透明特效:如果角色需要“半透红色护盾”且同时遮挡真实背景,可用两Pass方案——Pass1 ZWrite On ColorMask 0写深度,Pass2 ZWrite Off Blend SrcAlpha OneMinusSrcAlpha写颜色,并保证Pass1 Queue=Geometry+1,Pass2 Queue=Transparent+1,既满足深度提交又不破坏透明队列。
- WebGL导出:Quest3项目后期若需做微信小游戏云渲染版本,透视遮挡逻辑要完全在服务器端完成,客户端只收视频流,此时应把上述Shader改成H.264 Alpha通道方案,避免深度贴图带宽爆炸。