关于 threejs-impl-webgpu
threejs-impl-webgpu 是面向 Three.js 开发者的 WebGPU 实现参考技能,介绍 WebGPURenderer、TSL、节点材质、计算着色器与后期处理。内容注明相关 API 仍处于实验阶段。
主要功能
- 01初始化 WebGPURenderer 并检测支持情况
- 02使用 TSL 构建节点材质
- 03通过计算着色器执行 GPU 计算
- 04配置 WebGPU 后期处理
- 05说明从 WebGL 迁移的步骤
- 06提供 WebGL 回退建议
适用场景
- 01为 Three.js 场景配置 WebGPU 渲染
- 02使用 TSL 编写材质和着色逻辑
- 03将 WebGL 渲染流程迁移到 WebGPU
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ impertio-studio/ three.js-claude-skill-package --skill threejs-impl-webgpu安装后在 Claude Code 中输入/threejs-impl-webgpu确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.gitkeepreferences/anti-patterns.mdexamples.mdmethods.md详细介绍
threejs-impl-webgpu
实验性 — WebGPU 渲染器和 TSL 正在积极开发中。 API 接口可能会随 Three.js 版本更新而变化。请固定 Three.js 版本。
快速参考
WebGPURenderer 设置
import * as THREE from 'three/webgpu';
const renderer = new THREE.WebGPURenderer({ antialias: true });
await renderer.init(); // MUST await before first render
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setAnimationLoop(animate);
document.body.appendChild(renderer.domElement);
务必在首次调用 renderer.render() 前调用 await renderer.init()。
务必使用 renderer.setAnimationLoop(callback),而不是 requestAnimationFrame。
切勿在 init() 完成前调用 renderer.render() — 这会导致运行时错误。
浏览器支持
| 浏览器 | 版本 | 状态 |
|---|---|---|
| Chrome | 113+ | 完全支持 |
| Edge | 113+ | 完全支持 |
| Safari | 18+ | 支持 |
| Firefox | 实验性 | 需启用标志(dom.webgpu.enabled) |
功能检测与回退
import { WebGPU } from 'three/webgpu';
if (WebGPU.isAvailable()) {
const renderer = new THREE.WebGPURenderer({ antialias: true });
await renderer.init();
} else {
const renderer = new THREE.WebGLRenderer({ antialias: true });
}
务必在创建 WebGPURenderer 前检查 WebGPU.isAvailable()。
务必为不受支持的浏览器提供 WebGLRenderer 回退方案。
重要警告
切勿编写原始 GLSL 或 WGSL 字符串 — 务必使用 TSL 函数。WebGPU 会自动将 TSL 编译为 WGSL。WebGPU 后端不支持 GLSL。
切勿将 ShaderMaterial 与 WebGPURenderer 搭配使用 — 应改用结合 TSL 的 NodeMaterial。
切勿将 requestAnimationFrame 与 WebGPURenderer 搭配使用 — 务必使用 renderer.setAnimationLoop()。
切勿将 EffectComposer(three/examples)与 WebGPURenderer 搭配使用 — 应改用结合 TSL 节点的 PostProcessing 类。
节点材质
每种传统 Three.js 材质都有对应的基于节点的材质。传统材质与 WebGPURenderer 搭配使用时会自动转换,但节点材质可提供完整的 TSL 自定义能力。
材质映射
| 传统材质 | 节点材质 |
|---|---|
MeshBasicMaterial | MeshBasicNodeMaterial |
MeshStandardMaterial | MeshStandardNodeMaterial |
MeshPhysicalMaterial | MeshPhysicalNodeMaterial |
MeshPhongMaterial | MeshPhongNodeMaterial |
MeshLambertMaterial | MeshLambertNodeMaterial |
LineBasicMaterial | LineBasicNodeMaterial |
LineDashedMaterial | LineDashedNodeMaterial |
PointsMaterial | PointsNodeMaterial |
SpriteMaterial | SpriteNodeMaterial |
务必从 'three/webgpu' 导入节点材质,而不是从 'three' 导入。
NodeMaterial 输入属性
所有属性都接受 TSL 节点值。所有属性均为可选项,并会覆盖默认值。
常见输入(所有节点材质):
| 属性 | TSL 类型 | 用途 |
|---|---|---|
.colorNode | vec4 | 基础颜色 |
.opacityNode | float | 不透明度 |
.normalNode | vec3 | 替换法线贴图 |
.emissiveNode | color | 自发光输出 |
.positionNode | vec3 | 顶点位移 |
.fragmentNode | vec4 | 完全替换片元着色器 |
.vertexNode | vec4 | 完全替换顶点着色器 |
.outputNode | vec4 | 覆盖最终输出 |
.aoNode | float | 环境光遮蔽 |
.alphaTestNode | float | Alpha 测试阈值 |
.depthNode | float | 自定义深度 |
.castShadowNode | vec4 | 覆盖阴影投射 |
Standard/Physical 输入:
| 属性 | TSL 类型 | 用途 |
|---|---|---|
.metalnessNode | float | 金属度 |
.roughnessNode | float | 粗糙度 |
.envNode | color | 环境贴图 |
.lightsNode | — | 覆盖光照模型 |
仅限 Physical 的输入: .clearcoatNode、.clearcoatRoughnessNode、.clearcoatNormalNode、.sheenNode、.iridescenceNode、.iridescenceIORNode、.iridescenceThicknessNode、.specularIntensityNode、.specularColorNode、.iorNode、.transmissionNode、.thicknessNode、.attenuationDistanceNode、.attenuationColorNode、.dispersionNode、.anisotropyNode。
TSL(Three 着色语言)
TSL 是一种基于 JavaScript 的节点图系统,可编译为 GLSL(WebGL2)和 WGSL(WebGPU)。它完全取代原始着色器字符串。
类型系统
| 类别 | 函数 |
|---|---|
| 标量 | float()、int()、uint()、bool() |
| 向量 | vec2()、vec3()、vec4()、ivec2()、ivec3()、ivec4()、uvec2()、uvec3()、uvec4() |
| 矩阵 | mat2()、mat3()、mat4() |
| 颜色 | color() |
| 转换 | .toFloat()、.toVec3()、.toColor() |
变量和 Uniform
| 函数 | 用途 |
|---|---|
uniform(value) | GPU 端动态值 |
toVar(node) | 可复用的着色器变量 |
toConst(node) | 内联常量 |
varying(node) | 顶点到片元的插值 |
vertexStage(node) | 强制在顶点着色器中计算 |
attribute(name, type) | 访问缓冲区属性 |
Uniform 支持回调:.onRenderUpdate(fn)、.onFrameUpdate(fn)、.onObjectUpdate(fn)。
运算符
所有运算符都可以在 TSL 节点上链式调用:
- 算术:
.add()、.sub()、.mul()、.div()、.mod() - 比较:
.equal()、.notEqual()、.lessThan()、.greaterThan()、.lessThanEqual()、.greaterThanEqual() - 逻辑:
.and()、.or()、.not()、.xor() - 赋值:
.assign()、.addAssign()、.subAssign()、.mulAssign()、.divAssign() - 按位:
.bitAnd()、.bitOr()、.bitXor()、.shiftLeft()、.shiftRight()
几何节点
| 类别 | 节点 |
|---|---|
| 位置 | positionGeometry、positionLocal、positionWorld、positionView、positionWorldDirection、positionViewDirection |
| 法线 | normalGeometry、normalLocal、normalView、normalWorld |
| 切线 | tangentGeometry、tangentLocal、tangentView、tangentWorld |
| UV | uv(index) |
| 屏幕 | screenUV、screenCoordinate、screenSize |
| 视口 | viewportUV、viewportCoordinate、viewportSize |
相机和模型节点
- 相机:
cameraNear、cameraFar、cameraPosition、cameraProjectionMatrix、cameraViewMatrix、cameraWorldMatrix、cameraNormalMatrix - 模型:
modelViewMatrix、modelNormalMatrix、modelWorldMatrix、modelPosition、modelScale、modelDirection
动画节点
| 节点 | 用途 |
|---|---|
time | 自启动以来经过的秒数 |
deltaTime | 帧间隔秒数 |
oscSine(timer) | 正弦振荡器(0-1) |
oscSquare(timer) | 方波振荡器 |
oscTriangle(timer) | 三角波振荡器 |
oscSawtooth(timer) | 锯齿波振荡器 |
纹理操作
| 函数 | 用途 |
|---|---|
texture(tex, uv, level) | 通过插值进行采样 |
textureLoad(tex, uv, level) | 不进行插值地采样 |
textureStore(tex, uv, value) | 写入存储纹理 |
textureSize(tex, level) | 获取纹理尺寸 |
cubeTexture(tex, uvw, level) | 采样立方体贴图 |
triplanarTexture(texX, texY, texZ, scale, position, normal) | 三平面映射 |
控制流
始终使用大写的 If——小写的 if 属于 JavaScript,而不是 TSL。
If(condition, () => {
// true branch
}).ElseIf(otherCondition, () => {
// else-if branch
}).Else(() => {
// false branch
});
select(condition, trueVal, falseVal)— 三元运算符Loop(count, ({ i }) => { })— GPU 循环,支持Break()、Continue()Switch(value).Case(val, fn).Default(fn)— 不会贯穿执行Discard()— 丢弃片元Return()— 提前返回
函数定义
const myFn = Fn(([param1, param2]) => {
return param1.add(param2);
});
// Call: myFn(nodeA, nodeB)
计算着色器
WebGPU 通过 TSL 支持通用 GPU 计算。WebGL 回退模式下不支持计算着色器。
设置
import { compute, storage } from 'three/webgpu';
const computeNode = compute(shaderFn, count, workgroupSize);
await renderer.computeAsync(computeNode);
始终使用 await renderer.computeAsync()——计算调度是异步的。
存储和原子操作
- 存储:
storage(attribute, type, count)、storageTexture(texture) - 原子操作:
atomicAdd()、atomicSub()、atomicMax()、atomicMin()、atomicAnd()、atomicOr()、atomicXor()、atomicStore()、atomicLoad() - 屏障:
workgroupBarrier()、storageBarrier()、textureBarrier() - 内置 ID:
workgroupId、localId、globalId、numWorkgroups、subgroupSize
WebGPU 后期处理
切勿将 WebGL 的 EffectComposer 与 WebGPURenderer 搭配使用。请改用 PostProcessing 类。
import { PostProcessing } from 'three/webgpu';
import { bloom, renderOutput } from 'three/tsl';
const postProcessing = new PostProcessing(renderer);
const scenePass = renderOutput(scene, camera);
postProcessing.outputNode = bloom(scenePass);
可用的后期处理节点
bloom()、dof()、fxaa()、smaa()、gaussianBlur()、ssr()、ssgi()、ao()、chromaticAberration()、film()、dotScreen()、sobel()、afterImage()、anamorphic()、denoise()、lut3D()、motionBlur()、outline()、rgbShift()、transition()、traa()、renderOutput()
颜色操作
luminance()、saturation()、vibrance()、hue()、posterize()、grayscale()、sepia()
混合模式
blendBurn()、blendDodge()、blendOverlay()、blendScreen()、blendColor()
从 WebGL 迁移到 WebGPU
| 步骤 | 操作 |
|---|---|
| 1 | 将 import * as THREE from 'three' 替换为 import * as THREE from 'three/webgpu' |
| 2 | 将 new WebGLRenderer() 替换为 new WebGPURenderer(),并添加 await renderer.init() |
| 3 | 将经典材质替换为对应的 NodeMaterial(也可以保留经典材质——它们会自动转换) |
| 4 | 将 EffectComposer 替换为 PostProcessing 类和 TSL 后期处理节点 |
| 5 | 将原始 GLSL ShaderMaterial 替换为基于 TSL 的 NodeMaterial |
| 6 | 将 requestAnimationFrame 替换为 renderer.setAnimationLoop() |
使用 WebGPURenderer 时,务必将入口点设为 async——renderer.init() 会返回一个 Promise。
参考链接
- references/methods.md — WebGPURenderer、NodeMaterial、TSL、compute 的 API 签名
- references/examples.md — WebGPU 场景的可运行代码示例
- references/anti-patterns.md — 常见错误及其避免方法