Three.js教程
进阶
nullgraph-webgpu-renderer-trend
nullgraph-webgpu-renderer-trend

一个 59 star 的 WebGPU 项目,暴露了 Three.js 之外的新机会

最近 Three.js 社区里有个帖子热度不错。

标题很直接:A WebGPU renderer for the ages

作者展示了自己的项目 NullGraph,一个基于 WebGPU 的数据导向渲染框架。帖子发布约 9 天,拿到了 209 个 upvotes、31 条评论。对应的 GitHub 仓库目前 59 stars、6 forks,最近一次提交在 2026 年 5 月 9 日。

这些数字不算大。

但它有意思的地方不在“又一个开源库”,而在它暴露出一个趋势:

浏览器 3D 正在从“用 Three.js 做场景”分出另一条路:直接面向 GPU 写引擎。

这不是说 Three.js 不行。

恰恰相反,Three.js 仍然是 Web 3D 里最成熟、最通用、最适合业务落地的框架。问题是,WebGPU 把浏览器图形能力往底层打开之后,一些原本不适合在 Three.js 这类场景图框架里做的事情,开始有人想单独拿出来重做。

NullGraph 就是这种动向的一个样本。

它不是另一个 Three.js

NullGraph 的作者自己也说,它不是 Three.js 的竞争者。

这句话很关键。

因为如果你把它理解成“下一个 Three.js”,很容易误判。Three.js 的价值在于抽象足够完整:场景、相机、材质、灯光、模型加载、后处理、生态插件、学习资料,全部都有人踩过坑。大多数网站、可视化、产品展示、交互页面,用 Three.js 更合理。

NullGraph 的方向不是“让普通开发者更容易做 3D”。

它反而更偏底层:零 scene graph、数据导向、原生 WebGPU、render batch、GPU compute、indirect drawing。

这意味着它牺牲了一部分易用性,换来的是更直接地控制 GPU。

传统 Three.js 项目里,一个物体通常是一个对象,挂在场景树上。每一帧,框架遍历场景,更新矩阵,判断可见性,再提交绘制命令。

这套模式非常适合常规 3D 应用。

但如果你做的是几十万粒子、体素世界、MMO、大量动态实体,问题会变得明显:

  • JavaScript 对象太多,遍历和状态同步会变重;
  • 对象频繁变化,GC 抖动可能影响帧率;
  • CPU 端判断可见性和组织绘制命令,容易成为瓶颈;
  • WebGPU 的 compute shader、storage buffer、indirect draw 等能力,没有被充分吃干榨尽。

NullGraph 的回答是:那就不要从“对象树”开始。

直接从“数据怎么排布、怎么喂给 GPU、怎么批量绘制”开始。

真正的变化是:WebGPU 让前端开始关心数据布局

过去很多前端 3D 开发,核心关注点是“怎么把东西画出来”。

模型怎么加载,材质怎么调,镜头怎么动,交互怎么写。

到了 WebGPU 这一层,问题开始变成:

数据在内存里怎么排,GPU 才能最快地吃进去?

这就是 NullGraph 这类项目的底层逻辑。

它主张用连续的数据结构,把实体属性组织成 GPU 友好的 buffer,再用 batch 的方式提交给渲染管线。这样做的好处是,CPU 不再需要像传统场景图那样逐个对象处理,GPU 也可以更直接地进行并行计算。

比如可见性判断。

传统做法里,CPU 会判断哪些物体在摄像机视野里,再决定要画哪些。场景小的时候没问题,场景大了以后,这件事本身就会变成负担。

WebGPU 的思路可以更激进:把剔除逻辑放到 compute shader 里,让 GPU 自己筛选可见实例,并写入 indirect draw 参数。CPU 不再逐个实体发号施令,而是提交一批数据,让 GPU 自己决定实际绘制多少。

用 WGSL 写出来大概是这样:

@compute @workgroup_size(64)
fn cullInstances(@builtin(global_invocation_id) id: vec3<u32>) {
  let i = id.x;
  if (i >= uniforms.instanceCount) { return; }
 
  let pos = vec4<f32>(transforms[i * 16 + 12],
                      transforms[i * 16 + 13],
                      transforms[i * 16 + 14], 1.0);
 
  if (isInFrustum(pos, uniforms.frustumPlanes)) {
    let slot = atomicAdd(&indirectArgs.instanceCount, 1u);
    visibleIndices[slot] = i;
  }
}

CPU 只提交一次 dispatch,GPU 自己扫描所有实例,把可见的写进 visibleIndices,再用 indirectArgs 直接驱动绘制,完全绕过 CPU 的逐帧遍历。

这就是为什么 NullGraph 这种项目会反复强调:

  • GPU compute culling
  • indirect drawing
  • multi-pass rendering
  • data-oriented design
  • zero scene graph

这些词听起来不像前端框架文档,更像游戏引擎和图形编程里的词。

这恰恰说明,WebGPU 把浏览器 3D 的门槛往下挪了一层。

不是更低,而是更深。

NullGraph 近期变得更完整了

我之前也记录过 NullGraph,当时它更像一个展示数据导向渲染思路的实验项目。

这次重新看 GitHub,项目已经往“可用引擎骨架”方向补了不少东西。

README 里现在能看到这些能力:

  • GLB / GLTF 解析;
  • Standard PBR Material;
  • Cook-Torrance PBR;
  • 硬件加速骨骼动画;
  • SkeletonManager 和 Animator;
  • multi-pass rendering;
  • GPU compute culling;
  • indirect drawing;
  • 后处理和 alpha blending;
  • debug UI 和 profiler。

这说明它已经不只是“我能把很多粒子画出来”的 demo,而是在补 3D 引擎必需的几个模块:资产加载、材质系统、动画系统、渲染管线、性能工具。

当然,它离成熟生态还很远。

GitHub 只有几十个 stars,没有发布正式 release,API 还可能变化,文档和社区都很早期。生产项目现在直接押上去,风险很大。

但作为趋势样本,它已经足够有价值。

它说明有人正在尝试回答这个问题:

如果浏览器拥有接近现代图形 API 的能力,Web 端 3D 引擎还一定要长得像 Three.js 吗?

NullGraph 的答案是:不一定。

为什么这件事值得前端开发者关注

底层范式变化通常不会只停留在底层,它会往上渗透,最后改变上层工具的设计。

React Three Fiber 接 WebGPU 渲染器时,已经需要处理异步 renderer 初始化、TSL 节点材质、WebGPU 后处理管线。WebGIS 方向也出现了 mapgpu 这种用 WebGPU + Rust/WASM 重写地图渲染和空间计算的项目。现在 NullGraph 又在 Three.js 社区里讨论“为什么要直接做 WebGPU renderer”。

这些项目放在一起看,信号很清楚:

前端图形技术正在从 API 使用阶段,进入渲染架构阶段。

以前的学习路径是:

学 Three.js 怎么创建 scene、camera、mesh、material。

现在如果你想继续往前走,就要开始理解:

  • WebGPU 和 WebGL 的管线差异;
  • WGSL shader 怎么组织;
  • buffer、bind group、pipeline 是什么;
  • compute shader 能把哪些 CPU 工作搬到 GPU;
  • 数据布局为什么会影响帧率;
  • 什么时候场景图是好抽象,什么时候它会成为瓶颈。

这不是要求每个前端都去写渲染器。

但它会决定你能不能看懂下一代 Web 3D 工具为什么这么设计。

真正值得写的是这条分叉

NullGraph 本身还小。

但它背后的分叉很重要。

一条路是继续把 WebGPU 包进现有框架,让开发者用熟悉的 scene、mesh、material 写法逐步迁移。这是 Three.js、R3F、Babylon.js 更自然的路线。

另一条路是直接面向 WebGPU 重写渲染框架,把数据布局、批处理、compute、indirect draw 当成第一原则。这是 NullGraph、mapgpu 这类项目正在尝试的路线。

前者解决“让更多人用上 WebGPU”。

后者解决“WebGPU 到底能把浏览器 3D 推到哪里”。

这两条路都需要。

如果只有第一条,WebGPU 可能只是 WebGL 的更现代后端。

如果有第二条,浏览器才有机会进入更高性能、更大场景、更接近原生引擎的 3D 应用阶段。

NullGraph 现在还不是答案。

但它提出了一个很好的问题:

当浏览器终于有了更接近 GPU 的能力,我们还要继续用旧抽象去理解 3D 吗?

这个问题,可能比项目本身更值得关注。


参考资料: