命令行工具
gkjohnson/three-mesh-bvh avatar
gkjohnson/three-mesh-bvh

three-mesh-bvh 评测:把 three.js 射线检测从秒级拉到 60fps 的 BVH 方案

该项目围绕「gkjohnson/three-mesh-bvh」构建,面向真实业务场景提供可复用的开源实践方案,支持稳定落地与可扩展的项目实践。

3,486 个 Star333 个 ForkJavaScriptMIT

秒懂

它是什么?
three-mesh-bvh 为 three.js 网格提供 BVH 加速的射线检测与空间查询,官方宣称可在 8 万多边形模型上以 60fps 投射 500 条射线。本文基于其 README 与仓库信息,拆解它的用法、机制与边界。
适合谁用?
three-mesh-bvh 适合那些在 three.js 中需要频繁射线检测或复杂空间查询的开发者,尤其是游戏物理、编辑器拾取、路径追踪等场景。如果你只是偶尔做一次射线检测,或者网格三角形数量很少,那么引入这个库带来的构建开销和 API 学习成本可能不值。
能商用吗?
可以。MIT 是宽松许可证:你可以使用、修改并销售基于它的软件,只需保留版权和许可证声明。
还在维护吗?
在维护。仓库最近一次提交在 6 天前。
用什么语言写的?
主要是 JavaScript(依据 GitHub 的语言统计)。

以上回答依据项目的 GitHub 数据(最近同步于 2026年9月14日)和我们的分析,不构成法律意见。

开源项目深度解析

它解决的是 three.js 射线检测的瓶颈

three.js 默认的 Mesh.raycast 会遍历几何体的每一个三角形,当模型有数万甚至数十万三角形时,每次射线检测都会产生明显的卡顿。three-mesh-bvh 通过构建包围体层次结构,将射线检测的复杂度从 O(n) 降到接近 O(log n)。README 中给出的例子是:在 80,000 多边形模型上以 60fps 投射 500 条射线。这个数字来自项目描述,我没有亲自跑过,但它点明了这个库的定位:让射线检测不再是性能瓶颈。适合的人群很明确,做编辑器拾取、游戏碰撞、路径追踪或者任何需要频繁射线查询的 three.js 开发者。

机制:预计算 BVH 树,替换默认 raycast

核心思路是预计算。你调用 computeBoundsTree 或 new MeshBVH(geometry) 时,库会分析几何体的三角形分布,构建一棵包围体层次树。之后射线检测不再遍历所有三角形,而是从树的根节点开始,递归地判断射线是否与节点的包围盒相交,快速剔除不可能命中的分支。README 展示了两种集成方式:一种是扩展 BufferGeometry 和 Mesh 的原型方法,把 acceleratedRaycast 挂到 Mesh.prototype.raycast 上;另一种是手动创建 MeshBVH 实例并赋给 geometry.boundsTree。后一种方式更灵活,你可以在需要时重新构建 BVH。另外,设置 raycaster.firstHitOnly = true 会让 raycast 使用 bvh.raycastFirst,只返回第一个命中点,进一步提速。

上手:三行代码接入,但需注意几何体变化

最简单的用法是扩展原型:从 'three-mesh-bvh' 导入 computeBoundsTree、disposeBoundsTree 和 acceleratedRaycast,然后分别赋给 THREE.BufferGeometry.prototype 和 THREE.Mesh.prototype。之后调用 geometry.computeBoundsTree() 即可。手动方式则是 new MeshBVH(geom) 并赋给 geom.boundsTree。需要注意,BVH 是预计算的,如果几何体的顶点或索引发生变化,你必须重新调用 computeBoundsTree 或重新构建 MeshBVH。如果几何体是动态的,每次更新都重建 BVH 可能会抵消性能收益。README 没有明确说明重建的增量策略,所以对于频繁变形的网格,你需要自己评估重建成本。

不止三角形:点云、线条、蒙皮网格都有对应 BVH

这个库没有停留在三角形网格上。README 列出了 PointsBVH、LineBVH、LineLoopBVH 和 LineSegmentsBVH,分别对应 THREE.Points 和三种线条类型。使用方式类似,通过 computeBoundsTree 的 type 选项指定,例如 geometry.computeBoundsTree({ type: PointsBVH }),或者直接 new PointsBVH(geometry)。对于 SkinnedMesh,有 SkinnedMeshBVH;对于整个场景的对象层级,有 ObjectBVH。这些额外的 BVH 都实现了 shapecast 和 raycastObject3D 接口。但 README 明确说,像 WebWorker 生成和序列化这些功能,在部分 BVH 类型上暂不支持。所以如果你依赖异步生成 BVH,需要确认你用的类型是否支持。

shapecast 与空间查询:不只是射线

除了 raycast,库还提供了 shapecast 方法,可以自定义查询形状与 BVH 节点的相交测试。README 中的示例包括 SDF 生成、几何体体素化、裁剪边等,这些本质上都是空间查询。比如 SDF 生成,你可以通过 shapecast 对每个体素位置做距离计算,而不必逐三角形计算。这种能力让 three-mesh-bvh 成为工具类库,而不只是射线加速器。不过,shapecast 需要你理解 BVH 的遍历逻辑,自己写回调函数,学习曲线比直接调用 raycast 要陡。文档里没有给出 shapecast 的完整代码示例,具体用法需要查 API 文档或示例源码。

限制:WebGPU 示例未完成,部分功能缺失

README 中有一个 WebGPU Compute Shaders 的示例区块,但被 HTML 注释注释掉了,说明 GPU 路径追踪相关功能尚未正式公开。如果你打算用 WebGPU 做高性能计算,这个库目前可能不是最佳选择。另外,前面提到的 PointsBVH 等类型不支持 WebWorker 生成和序列化,这意味着在大型点云场景中,你无法在后台线程构建 BVH,可能导致主线程阻塞。还有一点,SkinnedMeshBVH 和 ObjectBVH 被标记为“近期新增,API 可能变化”,这意味着升级版本时你的代码可能需要调整。这些限制在 README 中都有提及,但容易被忽略。

替代方案:three.js 官方 BVH 与自研实现

three.js 本身没有内置 BVH,但官方示例中有基于 BVH 的射线检测实现,比如 three.js 仓库中的 MeshBVH 示例(如果存在的话)。更实际的替代是使用 three-mesh-bvh 的姊妹项目,如 three-gpu-pathtracer,它在内部使用 BVH 但面向 GPU 路径追踪。另一个方向是自研 BVH,如果你只需要简单的射线检测,可以自己实现一个粗糙的包围盒加速结构,但维护成本高。与 three-mesh-bvh 相比,官方或自研方案可能在集成度上不如它,因为 three-mesh-bvh 直接替换 Mesh.raycast,使用起来几乎无侵入。但如果你需要 WebGPU 支持,可能需要等待这个库的 WebGPU 示例正式发布,或者转向其他专注于 WebGPU 的库。

编辑结论

three-mesh-bvh 适合那些在 three.js 中需要频繁射线检测或复杂空间查询的开发者,尤其是游戏物理、编辑器拾取、路径追踪等场景。如果你只是偶尔做一次射线检测,或者网格三角形数量很少,那么引入这个库带来的构建开销和 API 学习成本可能不值。若你的项目使用 WebGPU 或需要更底层的控制,建议先验证其 WebGPU 相关示例是否满足需求,因为 README 中相关示例仍处于注释状态。采用前,先确认你的 three.js 版本与库的兼容性,并检查 SkinnedMeshBVH 和 ObjectBVH 的 API 是否稳定,因为 README 明确标注这些是近期新增,API 可能变化。

官方来源

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
社区笔记

社区笔记