前言
第一次跑通WebGPU demo,我的3080终于笑了
前阵子刷知乎,看到一个问题:"WebGPU 出来了,WebGL 是不是快死了?"
底下吵成一锅粥。有人说 WebGPU 是未来,有人说现在连 Safari 都没支持,早着呢。我本来想划过去,但看到一条评论忍不住笑了:
"WebGL 就像手动挡,WebGPU 就像自动挡,但问题是大部分人还在开拖拉机。"
作为一个从 Three.js 刚出就开始折腾的老菜鸟,我决定亲自试试这个传说中的"自动挡"。折腾了一周,我的结论是:WebGPU 不是自动挡,是直接从拖拉机换成了特斯拉。
今天就用我有限的脑容量,给大伙儿聊聊这个下一代 3D 技术到底强在哪儿。
一、WebGL 到底有啥不行?
要说 WebGPU 强在哪儿,得先明白 WebGL 哪儿不行。
WebGL 是基于 OpenGL ES 2.0/3.0 包装的,而 OpenGL 的设计思路是状态机 ------你调一个 gl.enable(),改一个 gl.blendFunc(),GPU 就跟着变。这本身没啥问题,问题出在 JavaScript 和 GPU 之间的通信方式上。
打个比方:
WebGL 时代,你想让 GPU 画一百个三角形,得在 JS 里写一百次 drawArrays。每次调用,浏览器都得做一堆检查、状态验证,然后通过驱动告诉 GPU。CPU 在那儿疯狂喊口号,GPU 还没开始干活,CPU 已经累趴了。
这就是为啥场景里一多 Mesh,帧率就崩------瓶颈不在 GPU,在 CPU 忙着传话。
WebGPU 的思路是:把要画的东西一次性打包好,告诉 GPU"这是清单,你照着画",然后 CPU 就可以去摸鱼了。
二、WebGPU 到底强在哪儿?
1. CPU 开销直线下降
在 WebGPU 里,渲染指令被组织成命令缓冲区。你可以把所有 draw call、状态切换都提前录好,然后一次性提交给 GPU。这样 CPU 只负责"录",GPU 只负责"放",彻底解耦。
我拿一个一万个立方体的场景做了对比(纯属娱乐):
- WebGL:Draw Call 一万次,帧率 25
- WebGPU:Draw Call 一次(实例化),帧率 60 还被 VSync 锁住了
虽然这例子有点极端,但道理是这个道理:WebGPU 能让你更充分地利用 GPU,而不是让 CPU 成为瓶颈。
2. 计算着色器(Compute Shader)来了
这是 WebGL 想都不敢想的东西。
以前你想做粒子系统、物理模拟,要么用 CPU 算(卡成 PPT),要么用奇技淫巧把数据塞给顶点着色器(巨麻烦)。WebGPU 原生支持计算着色器,直接让 GPU 当通用计算单元用。
我试了一个简单的粒子 demo:一万个粒子,每帧更新位置。用 WebGL 跑,CPU 算,帧率 40;用 WebGPU 计算着色器,帧率 120,CPU 占用几乎为 0。
那一刻我的 3080 终于发出了欣慰的笑声。
3. 更低的开销、更精细的控制
WebGPU 的 API 设计更接近现代图形 API(Vulkan、Metal、DirectX 12),你去掉了那些历史包袱。比如:
- 管线状态是预编译的 Pipeline 对象,切换更快
- 资源绑定是显式的,没有那么多隐式状态
- 支持更灵活的着色语言(WGSL)
说白了,WebGPU 让 JS 离"裸金属"更近了,能榨出更多性能。
三、Three.js 怎么用 WebGPU?
Three.js 从 r170 开始正式支持 WebGPU,搞了个 WebGPURenderer。
安装
首先得用最新的 three 版本(r170+),然后引入 WebGPURenderer:
bash
npm install three@next
javascript
import { WebGPURenderer } from 'three/src/renderers/webgpu/WebGPURenderer.js';
const renderer = new WebGPURenderer({
antialias: true,
powerPreference: 'high-performance'
});
await renderer.init(); // 重要!需要异步初始化
document.body.appendChild(renderer.domElement);
注意:材质得换
WebGPU 的材质系统和 WebGL 不太一样,需要用新的 NodeMaterial 体系:
javascript
import { Mesh } from 'three';
import { SphereGeometry } from 'three';
import { MeshBasicNodeMaterial } from 'three/src/nodes/materials/MeshBasicNodeMaterial.js';
const material = new MeshBasicNodeMaterial();
material.colorNode = new THREE.ColorNode(0xff0000); // 用节点的方式定义颜色
const mesh = new Mesh(new SphereGeometry(1), material);
scene.add(mesh);
是的,着色器现在用节点图(Node)来构建,有点类似 Unreal 的材质蓝图。好处是灵活性极高,坏处是......得重新学一套 API。
现有项目迁移成本
如果你想把一个 Three.js 老项目迁移到 WebGPU,目前不建议。因为:
- 所有自定义着色器都得重写成 WGSL 或 Node 形式
- 很多后处理效果还不兼容
- 文档还比较少(不过 Three 团队在拼命填坑)
我的建议是:新项目可以试水,老项目先观望。
四、我跑的第一个 WebGPU demo
为了感受差距,我写了一个最简单的旋转立方体:
javascript
import { Scene, PerspectiveCamera, BoxGeometry } from 'three';
import { WebGPURenderer } from 'three/src/renderers/webgpu/WebGPURenderer.js';
import { MeshBasicNodeMaterial } from 'three/src/nodes/materials/MeshBasicNodeMaterial.js';
import { color } from 'three/src/nodes/tsl/TSLBase.js';
const scene = new Scene();
const camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
const geometry = new BoxGeometry(1);
const material = new MeshBasicNodeMaterial();
material.colorNode = color(0x00ff00);
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
const renderer = new WebGPURenderer({ antialias: true });
await renderer.init();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
function animate() {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
animate();
跑起来的那一刻,说实话没感觉比 WebGL 快------毕竟就一个立方体。但打开 Chrome 的 GPU 面板,我发现 GPU 占用更稳了,CPU 占用几乎为 0。这就是"省电模式"啊!
五、现在能用吗?
浏览器支持
目前(2025 年初):
- Chrome/Edge:默认支持
- Firefox:需要 flag
- Safari:技术预览版支持
可以说,主流浏览器已经铺平了道路,但要全面普及还得等 Safari 正式版。
Three.js 生态
- 核心渲染器已经可用
- 常用材质(Basic、Standard、Phong)都有对应的 NodeMaterial
- 后处理支持还不全
- 社区例子还很少
用是能用,但得做好遇到 bug 自己修的准备。
六、未来已来
有一次我跟朋友聊天,他说:"WebGPU 再牛,跟我有啥关系?我现在 Three.js 用得挺顺。"
我问他:"你用 WebGL 写一万个粒子卡不卡?"
他说:"卡。"
"那 WebGPU 能让你跑十万个还不卡,你想要不?"
他沉默了。
技术的进步,往往就是这样------当你觉得"够用"的时候,新的东西已经在门口等着了。你可以选择继续用 WebGL,直到它像 Flash 一样被扫进历史垃圾堆;也可以现在开始了解 WebGPU,等它普及那天,你就是组里的"先知"。
我选择先当个小白鼠,给大伙儿探探路。
七、总结
WebGPU 不是 WebGL 的替代品,而是下一代 Web 图形的基础设施。它的优势很明显:
- CPU 开销更低
- 支持计算着色器
- 更精细的 GPU 控制
- 更接近现代图形 API
Three.js 已经迈出了第一步,现在就看社区的造化了。
如果你也对 WebGPU 感兴趣,可以去看看 Three.js 官方的 examples/webgpu,有几个 demo 跑得挺欢。不过别在生产环境用,等等它再成熟一点。
互动
你开始折腾 WebGPU 了吗?有没有遇到什么坑?评论区分享出来,让后来人少走弯路 😏
下篇预告:【Three.js 与 AI】用 TensorFlow.js 给模型"开天眼"