mcpField
I
improve-threejs

improve-threejs

github.com/millionco开发15.1k320 次安装2 周前更新
代码仓库

关于 improve-threejs

improve-threejs 是用于审查和改进 Three.js 与 React Three Fiber 代码库的技能。它结合 React Doctor 扫描、渲染循环优先级判断和基于证据的视觉检查,定位性能、资源生命周期及场景问题。

主要功能

  1. 01梳理渲染循环和交互热点
  2. 02运行 React Doctor 扫描
  3. 03按帧循环影响排列问题优先级
  4. 04依据视觉检查表检查场景
  5. 05修复性能及 GPU 资源问题
  6. 06验证代码改动和视觉表现

适用场景

  1. 01审查 Three.js 或 R3F 应用
  2. 02查找帧回调中的分配或状态更新
  3. 03依据场景证据诊断视觉缺陷
  4. 04检查修复是否引入回归并验证渲染行为

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/millionco/react-doctor --skill improve-threejs

安装后在 Claude Code 中输入/improve-threejs确认已加载。

详细介绍

改进 Three.js

审查 Three.js 或 React Three Fiber(R3F)代码库,并修复影响最大的问题:每帧都会运行的操作、从未释放的 GPU 资源、每次渲染都会重建的场景图对象,以及用户可见的视觉缺陷。React Doctor 提供机器验证的代码扫描;本技能则补充通用 React 扫描器所缺乏的帧循环判断和视觉检查。

核心原则:严重程度取决于渲染循环。useFrame 或 requestAnimationFrame 回调中的代码每秒运行 60 次,因此其中的轻微低效问题也比设置面板中的严重问题更值得优先处理。根据每项问题的运行位置重新排序,而不是照搬规则的默认严重程度。

工作流

第 1 步:侦察

扫描前先确定技术栈:纯 Three.js 还是 R3F、使用了哪些辅助库(drei、postprocessing、rapier),以及渲染循环位于何处(useFrame 钩子、requestAnimationFrame、<Canvas frameloop> 设置)。

绘制热路径图:列出每个 useFrame 函数体、每个 RAF 回调和每个指针移动处理器。第 3 步将对这些文件进行最严格的审查。

第 2 步:扫描

以只读模式运行 React Doctor,收集结构化证据:

npx react-doctor@latest --verbose

进行更改后,可使用 --scope changed 运行回归检查,并确认评分没有下降。

第 3 步:根据帧循环影响重新评估

利用热路径图重新排列扫描器发现的问题,然后查找扫描器无法识别的 Three.js 特有问题。报告前,逐一在对应的 file:line 位置确认每项问题。

高严重程度,每帧运行或导致 GPU 内存泄漏:

  • 在 useFrame 中分配对象:每帧都创建 new Vector3()、new Color(),或传给 Three.js API 的新数组。修复方法:将临时对象提升到模块作用域或放入 useMemo,然后直接修改对象
  • 在 useFrame 中调用 setState:每帧都会重新渲染 React 树。修复方法:直接修改 refs;仅在选择或可见性等离散变化时使用状态
  • 未释放资源:以命令式方式创建的几何体、材质、纹理或渲染目标从未释放。修复方法:在清理函数中调用 dispose(),或者将对象移入 R3F 声明式树,由其管理生命周期
  • 渲染时重建对象:创建几何体或材质实例时未使用 useMemo,或使用了每次渲染都会改变引用的内联 args 数组,导致 R3F 重建底层对象

中等严重程度,每次渲染或交互都会造成浪费:

  • 场景图属性不稳定:将内联 new THREE.Vector3() 或新建的材质对象作为属性传入(position={[x, y, z]} 这样的普通数组没有问题;R3F 会处理它们)
  • 缺少实例化渲染:数百个相同的网格分别渲染,而不是通过 <Instances> 或 InstancedMesh 渲染
  • 浪费帧:仅在交互时变化的场景使用了 frameloop="always"。修复方法:改用 frameloop="demand",并配合 invalidate()
  • 未缓存资源加载:纹理和模型在 useLoader、useTexture 或 useGLTF 之外加载,无法利用缓存和 Suspense 集成

低严重程度,代码卫生问题: React Doctor 对非画布 UI 代码的发现、缺少 <Preload>、纹理尺寸过大。

第 4 步:视觉审查

检查场景实际渲染的内容。每项视觉问题都必须有证据:截图、帧捕获或复现后的观察结果;绝不能仅凭阅读源代码猜测。如果有开发服务器和浏览器可用,就打开应用,捕获第一帧稳定画面,然后在移动摄像机并进行交互后再次捕获。如果没有浏览器,则检查下方列出的代码层面原因,并将每项问题标注为根据源代码推断。

应用此简易评估标准。只有证据表明存在失败情况时,对应条目才算未通过:

区域检查失败条件
渲染健全性加载后场景达到稳定帧画布全黑、WebGL 上下文错误,或内容始终未显示
几何体沿接缝、边缘和边界移动摄像机存在间隙、缺失的面、可见的背面,或两个表面在相同深度闪烁(深度冲突)
透明度和深度穿越重叠或可透光表面的深度排序边界排序错误、光晕、应透光的表面不透明,或掠射角处闪烁
纹理从近处、远处和掠射角观察贴图表面纹理缺失、拉伸、接缝、摩尔纹、闪烁,或因颜色空间错误导致颜色褪淡
材质和光照改变受光表面的光照方向和观察方向表面不受光照方向影响,或反射金属没有可供反射的环境
阴影在其范围内移动投射物、接收面和光源阴影痤疮、分离或悬浮的阴影、静止时闪烁,或投射物移开后阴影仍存在
摄像机在移动和过渡过程中跟随主要主体主体离开画面、摄像机穿入几何体,或前景遮挡游戏区域
比例和接触对照周围环境比较物体比例和静置接触情况物体悬浮在支撑表面上方、陷入其中或与之相交,或比例不合理
图像稳定性在受支持的分辨率下缓慢平移摄像机轮廓、细薄几何体或高光出现爬动、闪烁或残影
调整大小和 DPR更改视口大小、缩放和设备像素比画面变形、模糊、拉伸,或内容超出视口

每行检查项都有一小组常见的代码层面原因。某行检查失败时,请先检查以下原因:

  • 颜色褪淡或过暗:未设置 renderer.outputColorSpace 为 SRGBColorSpace,颜色纹理缺少 texture.colorSpace = SRGBColorSpace,或数据纹理(法线、粗糙度)被错误标记为 sRGB
  • 深度冲突:共面几何体需要设置 polygonOffset 或微调位置,或者近裁剪面相对于场景比例设置得过小
  • 阴影痤疮或悬浮阴影:未调优 shadow.bias 和 shadow.normalBias,或者阴影摄像机视锥体远大于场景
  • 画布模糊或拉伸:渲染器尺寸未与画布 CSS 尺寸同步、从未调用 setPixelRatio,或调整大小的处理程序忘记调用 camera.updateProjectionMatrix()
  • 金属发黑:设置了 metalness: 1,但未设置 scene.environment
  • 透明度排序问题:大型透明网格需要设置 depthWrite: false、手动指定 renderOrder,或拆分为更小的网格
  • 闪烁和爬动:缺少纹理各向异性、禁用了抗锯齿,或细薄几何体需要加厚
步骤 5:修复

按严重程度顺序修复:先处理 HIGH 性能问题和未通过的视觉检查项。如果某项问题对应 React Doctor 规则,请获取其标准修复方案,而不是自行摸索:

https://www.react.doctor/prompts/rules/<plugin>/<rule>.md

对于 Three.js 特有的问题,请应用分诊列表或上述原因列表中列出的修复方法。

步骤 6:验证

运行 npx react-doctor@latest --verbose --scope changed,确认评分没有下降。使用与原始证据相同的视角和交互方式,重新检查每一项未通过的视觉评估指标,并确认现在已通过。然后验证行为:场景能够渲染,动画能够播放,交互能够响应。如果可以使用浏览器开发者工具,请在空闲场景中环绕查看时监控内存配置;空闲时堆内存持续增长,说明仍存在资源释放泄漏。

扫描器总会漏掉的检查项

每次审查时,都要手动检查以下内容:

  • 是否对每个以命令式方式创建的 GPU 资源调用了 dispose()
  • useFrame 和 RAF 回调中的内存分配与 setState
  • Canvas 或 window 上未清理的事件监听器和 ResizeObserver
  • 是否在每次指针移动时都对整个场景进行光线投射,而不是使用经过筛选的目标列表
  • 当场景的某一部分需要阴影或后期处理时,是否全局启用了这些效果
  • 渲染器和每个颜色纹理的色彩空间配置

评论

支持 Markdown