关于 web3d-runtime
面向使用 three.js 构建 Web 3D 场景的开发者,提供 WebGPU 与 WebGL2 渲染、着色器、性能测量及降级处理的操作指导。内容针对 three.js r186,重点提示容易导致场景静默出错的兼容性问题。
主要功能
- 01检查版本、渲染器与动画循环
- 02指导 WebGPU 和 WebGL2 降级
- 03提供 TSL 与计算着色器指导
- 04覆盖预热、性能测量与资源释放
- 05标记未实际执行的验证项
适用场景
- 01排查 WebGPU 场景渲染异常
- 02将 ShaderMaterial 迁移到 TSL
- 03为较弱设备测量和优化帧时间
- 04规划设备丢失和无 WebGPU 时的降级
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ssheleg/ web3d-dev --skill web3d-runtime安装后在 Claude Code 中输入/web3d-runtime确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/performance-and-r3f.mdrenderer-and-loop.mdtsl-and-compute.md详细介绍
web3d-runtime——场景在每块 GPU 上都能运行,而且你可以证明它有多快
three.js 的 WebGPU 发展很快:r186 会抛出异常,而 r180 只会发出警告;后处理入口点已重命名,Clock 已弃用,而且同一 API 下仍提供 WebGL2 后端。
这里的大多数错误都悄无声息——场景会渲染,只是渲染错了。因此,这项技能先介绍故障,再介绍模式。
第一步——检查,然后报告
- 版本。 从
package.json中查看three、@react-three/fiber、@react-three/drei。这里的事实以 r186 为准;若使用其他版本,在相信某个名称前,先查看references/renderer-and-loop.md→ 版本说明。 - 渲染器。 使用的是
three/webgpu中的WebGPURenderer,还是经典的WebGLRenderer?是否有自定义的ShaderMaterial、RawShaderMaterial或onBeforeCompile?这些在 WebGPU 上都无法运行(注意事项)。 - 循环。 由谁负责每一帧:
setAnimationLoop、R3F 的useFrame,还是多个requestAnimationFrame(这是个错误——每个场景只能有一个时钟)。 - 速度证据。 是否有任何测量数据(Inspector、时间戳、在性能最弱的目标设备上负载运行时的 fps),还是只有主观感受?
以表格形式报告——领域 · 当前情况 · 问题 · 修复方案——并且只给出一个下一步行动。
能力阶梯
按场景从上到下选择合适的阶梯;每一阶都必须仍然是可运行的页面。
- WebGPU——
new WebGPURenderer(),然后执行await renderer.init()。 - 同一渲染器的 WebGL2 后端——WebGPU 不可用时自动启用(会记录
running under WebGL2 backend);使用forceWebGL: true强制启用。此处需要为计算密集型功能提供更轻量的路径:在init()后通过renderer.backend.isWebGPUBackend进行检测。 - 静态降级——完全不使用 WebGL、减少动态效果,或设备丢失且无法恢复时,使用静态图片或 CSS/SVG 静态画面,并确保内容清晰易读。这是将
sheleg-design的平静降级规则应用到 3D 场景。
注意事项 — r186,每一项都可能静默发生或出人意料
render()会在await renderer.init()之前抛出异常(因此clear()、hasFeature()、initTexture()也会如此);setAnimationLoop会自行等待初始化。自 r181 起,renderAsync及相关方法已弃用。positionNode会在蒙皮、变形和实例化之后替换位置。positionLocal.add(offset)会保留它们;单独使用positionGeometry.add(...)或buffer.element(instanceIndex)会让每个实例都坍缩到一个点。粒子请使用官方模式:在精灵或点材质上设置positionNode = buffer.toAttribute()。- JS 重新赋值并不会写入着色器存储。 在
Fn中,a = a.add(1)会重新绑定 JS 名称, 不会生成任何内容;请先使用.toVar(),再调用.assign()/.addAssign()。对节点使用 JSif或三元表达式 也会导致同样的问题——请使用If/select。 - 原子操作需要在
atomicAdd之前调用storage(buf, 'uint', n).toAtomic()。 computeAsync()不会等待 GPU 完成。 只有renderer.getArrayBufferAsync()会将结果读回 CPU(r186 中可复用THREE.ReadbackBuffer)。ShaderMaterial、RawShaderMaterial和onBeforeCompile没有 WebGPU 映射——该对象会作为普通节点材质渲染,并报出「不兼容」错误。请移植到 TSL。大约 20 个 drei 组件基于这些功能构建,因此也会以同样方式失败。- 适配器会以兼容模式请求;如果设备只提供这种模式,MSAA 会被静默禁用。
- WebGPURenderer 中的
alpha默认值为true(WebGLRenderer 中为 false):依赖不透明画布的移植代码会透出页面内容。 PostProcessing现已更名为RenderPipeline;Clock已弃用——请使用Timer(core); WebGPU 上已移除PCFSoftShadowMap(自 r183 起,PCFShadowMap为软阴影);renderer.dispose()是异步的。- **设备丢失:**使用
renderer.onDeviceLost(验证错误和内存不足错误则使用renderer.onError)。两个后端都支持它;直接挂接 WebGPU 设备会在 WebGL2 回退时失效。 - **R3F 9.8.1 的默认值与 three.js 不同:**启用 ACES 色调映射,
shadows={true}会选择已移除的软阴影贴图(请使用shadows="percentage"),且useFrame的 delta 不会被钳制。
操作流程
- 渲染器和循环——一个渲染器、
await init()、一个setAnimationLoop、一个Timer(references/renderer-and-loop.md)。 - 使用 TSL 编写材质和着色器;对任何逐粒子或逐实例的计算使用 compute
(
references/tsl-and-compute.md)。 - **预热:**在首个可见帧之前调用
await renderer.compileAsync(scene, camera)(compute 则调用compileComputeAsync),避免首次交互时卡顿。 - 在性能最弱的目标设备上测量,使用 Inspector 或时间戳查询,然后分配性能预算
(
references/performance-and-r3f.md)。 - **降级:**减少动态效果、不支持 WebGPU、设备丢失和标签页隐藏,都要有明确的代码分支——并且每个分支都经过实际验证。
- **清理:**释放几何体、材质、纹理和渲染目标;
await renderer.dispose()。
缺少条件时的处理
- 此环境中完全没有工具 → 写出命令和代码,绝不伪造执行结果。未经测量的大小、通过结果、帧时间或「已完成」都属于伪造证据;将每项此类检查标记为
NOT_RUN,并说明需要由人执行什么。 - 此环境中没有浏览器或 GPU → 构建、进行类型检查并审查;将视觉效果和帧时间门槛报告为
NOT_RUN,并注明需要由人使用的页面和设备。绝不要仅凭阅读代码就声称「流畅」。 - 项目使用较旧版本的 three.js → 指明版本差距;不要不加判断地套用 r186 的名称,也不要未经操作者同意就升级依赖。
- R3F 项目需要使用 WebGPU → 使用
references/performance-and-r3f.md中的异步gl工厂模式;切换之前,列出场景所用且无法在 WebGPU 上运行的 drei 组件。
参考资料
| 阅读 | 适用场景 |
|---|---|
references/renderer-and-loop.md | 创建渲染器、回退方案、循环和时钟、色彩与色调映射、后期处理、设备丢失、释放资源 |
references/tsl-and-compute.md | 编写 TSL 材质或着色器、计算通道、粒子、原子操作、回读,或移植 GLSL |
references/performance-and-r3f.md | 测量或修复帧时间、绘制调用和内存;在 WebGPU 上运行 React Three Fiber;在 WebGPU 上使用 drei |
资源文件和预算见 web3d-assets;制作动画见 web3d-animation。公开的 webgpu-threejs-tsl 技能(dgreenheck)启发了本文优先讲解常见问题的结构;重新依据 r186 核验其示例时发现的勘误,也列在上面的常见问题中。
触发词
其他会将请求路由到此处的短语:“WGSL”、“compute shader” / “компьют-шейдер”、“particles collapsed” / “частицы схлопнулись”、“device lost” / “потеря устройства”、“React Three Fiber”、“post-processing” / “постобработка”、“WebGL fallback”。
这些短语于 0.2.4 版本从描述中移至此处:“three.js WebGPU”、“the 3D scene is slow”。