URP 渲染实战 / 第 2 章 URP 架构与一帧的流程 / 案例 2.7
案例 2.7第一人称手持物:清不清深度入门
目标:用 Overlay 相机渲染一个“拿在手里”的物体,对比 Clear Depth 关闭和开启的效果。
Assets/Cookbook/Ch02/Editor/Ch02Shots.cs(节选:stack)
s.Cam.cullingMask = ~(1 << overlayLayer); // Base 相机不画“手持物”层 if (s.Panel == 0) return; // 叠加相机:只画手持物这一层,挂到 Base 相机的 Stack 里 var go = new GameObject("Overlay Camera"); go.transform.SetPositionAndRotation(s.Cam.transform.position, s.Cam.transform.rotation); var cam = go.AddComponent<Camera>(); cam.fieldOfView = s.Cam.fieldOfView; cam.nearClipPlane = 0.05f; cam.aspect = 640f / 420f; cam.cullingMask = 1 << overlayLayer; var data = go.AddComponent<UniversalAdditionalCameraData>(); data.renderType = CameraRenderType.Overlay; // clearDepth 在 URP 14 里只有 getter,Inspector 上的 Clear Depth 勾选框对应序列化字段 m_ClearDepth var so = new SerializedObject(data); so.FindProperty("m_ClearDepth").boolValue = s.Panel == 2; // 面板 1 不清深度,面板 2 清深度 so.ApplyModifiedPropertiesWithoutUndo(); s.CamData.cameraStack.Add(cam); var item = s.Knot(s.Lit(new Color(1f, 0.6f, 0.15f), 1f, 0.8f), Vector3.zero, 0.3f); item.layer = overlayLayer; item.transform.SetParent(s.Cam.transform, false); item.transform.localPosition = new Vector3(0.36f, -0.2f, 1.25f); item.transform.localRotation = Quaternion.Euler(20, 40, 0);

中图里,Overlay 相机沿用了 Base 相机的深度缓冲,于是手持物和场景做了正常的深度测试,右下部分被离相机很近的柱子挡住——第一人称游戏里“枪管插进墙里”就是这个样子。勾上 Clear Depth 后,Overlay 相机开始渲染前把深度清空,手持物永远画在场景之上。代码里通过 SerializedObject 修改 m_ClearDepth,是因为 URP 14 的 UniversalAdditionalCameraData.clearDepth 只有 getter;在编辑器里直接勾选 Overlay 相机 Rendering 面板中的 Clear Depth 即可。
提示手持物常用比场景更小的 FOV 来避免透视畸变。不同 FOV 的两台相机,深度值的含义不同,这时混用深度缓冲(不清深度)就失去了物理意义——再一次说明手持物的 Overlay 相机通常应该清深度。
本案例出自《URP 渲染实战》第 2 章「URP 架构与一帧的流程」。在章节中阅读上下文 →