首页 / Three.js 入门教程 / WebGPU 简介

Three.js 入门教程

WebGPU 简介

本教程共 40 篇 · 第 38 篇 · 更新于 2026-08-14 · 约 8 分钟阅读

Three.jsWebGPUWebGPURendererTSLWebGL

本节目标:认识 WebGPU 这个新一代浏览器图形 API,学会用 three.js 的 WebGPURenderer 跑起一个场景,并理解 TSL 与 WebGPU 的关系。学完你能判断自己的项目该不该上 WebGPU。

WebGL 的局限

WebGL 出身于 2011 年,底层是 OpenGL ES 2.0。十几年过去,它有几个天生短板:

  • 状态机设计:切换材质、纹理、缓冲都要改全局状态,CPU 开销大,draw call 一多就卡
  • CPU 与 GPU 同步等待:很多操作会阻塞主线程等 GPU 返回结果
  • 没有计算着色器:GPU 最强的通用计算能力(物理、粒子、AI)用不上,只能靠顶点/片元着色器绕

图形行业老早转向了 Vulkan、Metal、DirectX 12 这种现代 API。浏览器里也该有对应的东西了,这就是 WebGPU。

WebGPU 是什么

WebGPU 是 W3C「GPU for the Web」工作组制定的新一代 Web 图形 API,参与者包括 Apple、Google、Mozilla、Microsoft。它借鉴 Vulkan、Metal、DirectX 12 的设计:

  • 显式管线:渲染状态(管线、绑定组)提前配置好,运行时切换开销小
  • 计算着色器:通用 GPU 计算原生支持,粒子、物理、流体模拟都能上
  • 高效 CPU/GPU 交互:命令先编码再批量提交,减少同步等待
  • WGSL 着色语言:新的着色语言,语法更像现代语言

代价是原生 WebGPU 非常底层,直接写比 WebGL 还繁琐。好消息是 three.js 把它封装好了,我们几乎不用碰 WGSL。

WebGPU 与 WebGL 对比

对比项WebGL 2WebGPU
出身2011 年,基于 OpenGL ES 2.02023 年起陆续落地,对标 Vulkan/Metal/DX12
设计状态机,切换开销大显式管线,切换开销小
着色语言GLSL(three.js 内可用 TSL 替代)WGSL(three.js 内用 TSL)
计算着色器原生支持
CPU/GPU 交互同步等待多命令批量提交,交互高效
浏览器支持全面Chrome/Edge/Safari 默认,Firefox 桌面端默认(部分平台需开启)

浏览器支持现状

截至 2026 年年中:

  • Chrome / Edge:Chrome 113(2023 年 4 月)起默认开启
  • Safari:Safari 26(2025 年)起默认开启
  • Firefox:桌面版 Firefox 141(2025 年 7 月)起在 Windows 默认开启,其他平台需在 about:config 打开 dom.webgpu.enabled;Linux 版计划 2026 年上线,Android 与 Mac 时间表未定
  • 移动端:整体滞后于桌面,iOS 26 起可用,Android Chrome 部分设备可用

用一行代码检测当前浏览器:

if (navigator.gpu) {
  console.log('支持 WebGPU');
} else {
  console.log('不支持 WebGPU,请更新浏览器');
}

three.js 里的 WebGPU:WebGPURenderer

r185 中,WebGLRenderer 仍是默认、成熟的渲染器,兼容性最好,绝大多数示例和教程都用它。WebGPURenderer 是官方定位的”新渲染器”:

  • 默认优先用 WebGPU 后端,浏览器不支持时自动回退到 WebGL2 后端
  • { forceWebGL: true } 可强制走 WebGL2
  • API 与 WebGLRenderer 高度相似,迁移成本低
  • 仍在快速迭代,版本间可能有破坏性变更,生产环境要谨慎评估

官方示例仓库里 webgpu_* 开头的示例已经有两百多个,粒子、物理、水体、后期处理都有覆盖,说明能力已经相当完整。

基本用法:渲染器从 three/webgpu 入口导入(对应 build/three.webgpu.js 构建文件):

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <title>WebGPURenderer 示例</title>
  <style>body { margin: 0; overflow: hidden; }</style>
</head>
<body>
<script type="importmap">
  {
    "imports": {
      "three": "https://cdn.jsdelivr.net/npm/three@0.185.0/build/three.webgpu.js",
      "three/webgpu": "https://cdn.jsdelivr.net/npm/three@0.185.0/build/three.webgpu.js",
      "three/tsl": "https://cdn.jsdelivr.net/npm/three@0.185.0/build/three.tsl.js",
      "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.185.0/examples/jsm/"
    }
  }
</script>
<script type="module">
import * as THREE from 'three/webgpu';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, innerWidth / innerHeight, 0.1, 100);
camera.position.set(2, 2, 2);

// WebGPU 下抗锯齿默认关闭,需要显式开启(走 MSAA)
const renderer = new THREE.WebGPURenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

// WebGPU 初始化是异步的,必须等待
await renderer.init();

new OrbitControls(camera, renderer.domElement);

const mesh = new THREE.Mesh(
  new THREE.BoxGeometry(1, 1, 1),
  new THREE.MeshStandardMaterial({ color: 0x00aaff })
);
scene.add(mesh);
scene.add(new THREE.AmbientLight(0xffffff, 0.6));
scene.add(new THREE.DirectionalLight(0xffffff, 2));

renderer.setAnimationLoop(() => {
  mesh.rotation.y += 0.01;
  renderer.render(scene, camera);
});
</script>
</body>
</html>

与 WebGLRenderer 的差异,记住三点:

  1. 入口不同import * as THREE from 'three/webgpu',不是 'three'
  2. 必须 await renderer.init():WebGPU 初始化是异步的,不等待就渲染会报错。模块脚本支持顶层 await,直接写即可
  3. 抗锯齿要显式开启{ antialias: true } 走 MSAA(默认 4 采样)。WebGLRenderer 同样默认关闭,之前章节我们也是手动开的

场景、相机、几何体、材质、OrbitControls 的用法和 WebGL 完全一样,这正是 three.js 封装的价值。

TSL 与 WebGPU 的关系

第 35 章讲过 TSL(Three.js Shading Language)。它的编译目标有两个:WebGPU 的 WGSL 和 WebGL2 的 GLSL。three.js 内部用 NodeBuilder 生成着色器代码,它有两个子类:WGSLNodeBuilder(面向 WebGPU)和 GLSLNodeBuilder(面向 WebGL2)。

所以:

  • TSL 不是 WebGPU 专属,WebGL 渲染器同样能用(官方 webgl_tsl_* 示例就是证据)
  • 但 WebGPURenderer 的定制着色主要靠 TSL,而不是老一套的 GLSL 字符串拼接
  • 用 TSL 写的材质,在两种渲染器之间迁移几乎不用改

WebGPU 下自定义材质的标准姿势是节点材质(Node Material):

import * as THREE from 'three/webgpu';
import { texture, uv, color } from 'three/tsl';

const material = new THREE.MeshStandardNodeMaterial();
// 颜色 = 贴图颜色 × 红色,用节点拼接
material.colorNode = texture(myTexture).mul(color(0xff0000));

节点材质有 MeshBasicNodeMaterialMeshStandardNodeMaterialMeshPhysicalNodeMaterial 等,和普通材质一一对应,只是属性换成了 colorNoderoughnessNode 这种节点版本。

迁移时容易踩的坑

  • 背景透明度不一样WebGPURendereralpha 默认是 true,画布默认透明;WebGLRenderer 默认是 false,背景是黑色。跨渲染器迁移时,透明背景的物体看起来会”变样”
  • 首帧编译卡顿:WebGPU 首次运行要编译渲染管线,第一帧可能明显卡顿。可以在加载阶段调用 await renderer.compileAsync(scene, camera) 预编译,把卡顿挪到进度条后面
  • 部分 addons 的兼容性:绝大多数扩展(OrbitControls、GLTFLoader)两个渲染器通用,少数 WebGL 专属实现需要替换,官方 webgpu_* 示例里都有对应版本
  • 版本迭代快:WebGPU 相关 API 在 three.js 里变化比其他部分快,升级主版本时留意 release notes 里的破坏性变更

什么时候该用 WebGPU

适合的场景:

  • 计算着色器:粒子系统、布料、流体、集群动画(官方 webgpu_compute_* 示例)
  • 大量 TSL 定制着色
  • 新项目,且目标用户浏览器较新
  • 想体验下一代图形技术

暂时不用的场景:

  • 需要兼容老浏览器、低端移动设备
  • 项目已经稳定运行在 WebGLRenderer 上,没有性能痛点
  • 不想承担 API 快速迭代的维护成本
Note

WebGPURenderer 在 r185 里已经很好用,但官方和社区都明确提醒:它仍处于快速迭代期,可能有不兼容变更。线上项目建议继续用 WebGLRenderer,用 WebGPU 前先做原型验证。这个判断基于 2025-2026 年的社区共识(three.js 官方文档、threlte 官方文档),r185 之后可能随时变化。

Tip

想快速看 WebGPU 能做什么,直接打开 threejs.org/examples 里的 webgpu_compute_birds.htmlwebgpu_ocean.htmlwebgpu_tsl_galaxy.html。你的浏览器只要支持 WebGPU,就能跑。