关于 threejs
面向使用 Three.js 构建 3D 网页体验的开发者,涵盖 WebGPU、着色器与 React Three Fiber。内容还包括资源处理、动画和渲染性能优化。
主要功能
- 01WebGPU 渲染器配置
- 02TSL 着色器编写
- 03React Three Fiber 模式
- 043D 资源压缩与加载
- 05场景性能优化
- 06动画与灯光指导
适用场景
- 01配置 WebGPU 渲染
- 02用 React Three Fiber 组合场景
- 03加载并优化 GLTF 资源
- 04实现 3D 动画与灯光
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ oakoss/ agent-skills --skill threejs安装后在 Claude Code 中输入/threejs确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/animation.mdperformance.mdr3f-patterns.mdscene-and-lighting.mdwebgpu-tsl.md详细介绍
Three.js
概述
介绍如何使用 Three.js 构建高性能 3D Web 体验,涵盖 WebGPU 优先渲染、TSL(Three Shader Language)和 React Three Fiber。内容包括场景架构、资源压缩、绘制调用预算,以及 React 19 / Next.js 集成模式。
**适用场景:**创建 3D 场景、设置 WebGPU 渲染、编写 TSL 着色器、优化资源(Draco/KTX2)、组合 React Three Fiber、为 3D 内容使用 Next.js 流式传输、加载 GLTF 模型、设置灯光和阴影、播放和混合动画。
**不适用场景:**2D 画布动画(使用 Canvas API)、简单 SVG 图形、无需客户端水合的服务器端渲染,以及仅面向 2022 年以前硬件的项目。
快速参考
| 模式 | API / 方法 | 要点 |
|---|---|---|
| WebGPU 渲染器 | import * as THREE from 'three/webgpu' | 首次渲染前必须先执行 await renderer.init() |
| R3F 画布 | 带有 Suspense 的 <Canvas gl={...}> | 使用 <Suspense> 包裹以支持流式传输 |
| 帧更新 | useFrame((state, delta) => ...) | 直接修改 refs;切勿使用 setState |
| TSL 着色器 | import { ... } from 'three/tsl' | 基于节点;编译为 WGSL 或 GLSL |
| 实例化 | 使用矩阵更新的 <instancedMesh> | 重复几何体只需一次绘制调用 |
| 批处理网格 | BatchedMesh(r156+) | 不同几何体共享一个材质 |
| Draco 压缩 | gltf-pipeline -i in.gltf -o out.glb -d | 几何体大小最多可减少 90% |
| KTX2 纹理 | 通过 toktx 使用 Basis Universal | 在 VRAM 中保持压缩状态 |
| LOD | 带距离阈值的 THREE.LOD | 根据相机距离切换细节级别 |
| 按需渲染 | <Canvas frameloop="demand"> | 仅在场景状态变化时渲染 |
| 清理 | 卸载时调用 .dispose() | 几何体、材质和纹理 |
| 计算着色器 | Fn(() => {...})().compute(count) | GPU 端物理模拟、粒子和群集 |
| 灯光 | DirectionalLight、SpotLight、HemisphereLight | 在渲染器上启用 shadowMap,并在灯光上启用 castShadow |
| GLTF 加载 | GLTFLoader + DRACOLoader | 使用 Draco 压缩几何体;遍历模型以添加阴影 |
| 动画 | AnimationMixer + clipAction() | 每帧使用 clock.getDelta() 更新 |
| 淡入淡出 | action.fadeOut() / action.fadeIn() | 在行走 / 奔跑 / 闲置动画间按权重混合 |
| 环境贴图 | RGBELoader + PMREMGenerator | 设置 scene.environment 以实现 PBR 反射 |
| 射线投射 | Raycaster.setFromCamera(pointer, cam) | 鼠标 / 触摸拾取;对 GLTF 使用 recursive: true |
| 变形目标 | mesh.morphTargetInfluences[index] | 面部动画、来自 GLTF 的混合形状 |
常见错误
| 错误 | 正确做法 |
|---|---|
在 useFrame 中分配 new THREE.Vector3() 或 new THREE.Color() | 在循环外预先分配,以避免每帧产生 GC 压力 |
在 React 项目中手动使用 requestAnimationFrame | 使用 R3F 的 useFrame 钩子逐帧更新 |
使用 WebGPU 时未等待 renderer.init() | 首次渲染前始终执行 await renderer.init(),以避免竞争条件 |
加载资源时未使用 <Suspense> 边界 | 将 <Canvas> 包裹在 <Suspense> 中,以防止阻塞主线程 |
| 为背景或远处元素使用高多边形模型 | 使用 LOD(细节层次)或 Impostors 来减少绘制调用 |
在渲染循环中使用 setState 处理动画 | 通过 useFrame 直接修改 refs,逐帧更新 |
速度与帧率绑定(rotation += 0.01) | 乘以 delta,实现与帧率无关的运动 |
未对 mixer.update() 使用 clock.getDelta() | 始终将 delta 时间传给 mixer.update(delta),以确保动画速度正确 |
| 忘记释放已加载的 GLTF 模型 | 移除时遍历并释放几何体、材质和纹理 |
| 已在渲染器上启用阴影贴图,却未在光源上启用 | 同时设置 renderer.shadowMap.enabled 和 light.castShadow = true |
相机的 far/near 比值过大 | 保持较小的比值以避免 z-fighting;尽可能增大 near |
委派
- 资源和场景图探索:使用
Exploreagent - 多文件场景重构和优化:使用
Taskagent - 3D 架构和渲染管线规划:使用
Planagent
参考资料
评论
支持 Markdown