← ALL NOTES
METHOD·2026.09·4 MIN READ
3D 场景中 2D 覆盖层的遮挡关系
3d-visualization3d-design
问题

在 3D 场景里,用 SVG 或 HTML 叠加描边、标签和提示,是一种很常见的实现方式。它们比在 Three.js 里创建真实几何体更容易控制,也更适合做细线、文字和交互反馈。

但 2D 覆盖层有一个基础限制:它没有 3D 深度信息。 只要画在这一层里的内容,默认都会出现在场景最上方,不会自动被前面的模型遮挡。

我之前在一个立方体工具 demo 里遇到过这个问题。未选中的立方体用 SVG 画一圈细描边,用来和背景区分。物体少的时候没有明显问题,但多个立方体密集摆放后,后方立方体的轮廓会直接穿透到前方立方体表面上。

这并不是描边坐标算错了,而是实现层级不对:SVG 只知道每条线在屏幕上的位置,并不知道它属于远处还是近处的 3D 对象。

根因诊断和后续实现方案主要来自 Claude Code,我负责在密集场景中验证修改后的遮挡结果是否符合预期。

按遮挡语义选择实现层

最终没有继续给 SVG 增加遮挡判断,而是重新分配了不同描边的实现层。

未选中物体的普通描边改成 3D 线框。 使用立方体自身的 EdgesGeometry 生成边线。它是真实存在于 3D 场景里的对象,会参与深度测试,因此前后遮挡关系可以直接交给渲染器处理。

选中和 Hover 高亮继续保留在 SVG 覆盖层。 这两类反馈的语义不同:即使目标的一部分被别的模型挡住,用户仍然需要明确知道"当前选中的是谁"或"鼠标正指向谁"。它们本来就应该浮在场景上方,因此不参与深度测试反而更合理。

最后使用的判断标准很简单:如果一个视觉效果应该遵守真实空间遮挡,就放进 3D 场景;如果它需要始终可见,再放到 2D 覆盖层。

为什么不在 SVG 里补遮挡判断

理论上也可以继续使用 SVG,然后自己计算每条边是否被别的对象遮挡,再决定哪些线段显示。

但这会把一个原本由深度缓冲天然解决的问题,重新变成一套额外的几何判断逻辑。随着物体数量、相机角度和模型复杂度增加,这套逻辑也会越来越重。

对于普通物体轮廓来说,没有必要复制一遍渲染器已经具备的能力。把视觉效果放回正确的 3D 层级后,遮挡关系可以直接由深度测试得到。

这次调整的重点不是"SVG 做不到",而是没有必要让 2D 层负责它本来不擅长的空间关系。

视觉上的权衡

从 SVG 换到 WebGL 线框后,也失去了一部分原来的视觉控制能力。

SVG 可以精确指定 0.5px 一类的亚像素线宽;WebGL 的基础线条在很多平台上无法稳定控制这么细的宽度,通常会被限制在接近 1px。

这里最终接受了线宽上的差异,因为两个问题的影响程度不同:

  • 遮挡错误会直接破坏空间关系,是明显的视觉 bug;
  • 0.5px 和约 1px 的线宽差异,对当前场景的影响相对较小。

为了让稍粗的 3D 边线仍然保持足够区分度,又重新调整了普通状态和 Hover 状态的不透明度。这样即使失去了原来的精细线宽控制,相邻立方体之间仍然有清楚的边界。

密集场景是必要测试条件

这个问题在少量物体时很难被发现,因为即使后方轮廓始终显示,只要它没有投影到前方物体表面上,视觉上就不会明显出错。

真正暴露问题的是多个物体在屏幕投影中互相重叠。

因此,涉及 3D 对象描边、标签和覆盖层时,除了检查单个对象状态,还需要主动测试:

  • 多个物体前后重叠;
  • 物体密集排列;
  • 相机旋转后遮挡关系发生变化。

这类问题不是单个组件画得对不对,而是它进入完整空间关系以后是否仍然成立。

经验总结
  1. 先判断视觉效果是否应该参与深度测试。 这比先决定用 SVG、HTML 还是 Three.js 更重要。
  2. 普通物体状态尽量遵守真实空间关系。 如果一个描边代表物体本身,它通常也应该被前方物体遮挡。
  3. 强调型反馈可以有意脱离深度关系。 选中、Hover 一类需要稳定可见的状态,更适合使用 2D 覆盖层。
  4. 技术层级切换会带来新的视觉约束。 从 SVG 换到 WebGL 后,需要重新检查线宽、透明度等表现能力。
  5. 遮挡问题要在密集场景里验证。 稀疏布局往往不足以暴露 2D 覆盖层的深度缺失。
关于技术选型

这次具体根因和 EdgesGeometry 的实现方案主要来自 Claude Code,我负责确认哪一类描边应该遵守真实遮挡,以及修改后的视觉结果是否满足设计目标。

对我来说更有用的判断不是记住"SVG 不适合 3D 描边",而是先问一句:这个视觉效果在语义上应该被挡住吗?

同样是描边,普通状态和选中状态的答案并不一样。答案确定以后,实现层其实就很自然了。

CONTINUE READING
从 Figma 组件属性到代码 Props2026.09Figma 设计系统的工程化落地2026.09