前端开发
在 React Three Fiber…
适用于 React Three Fiber 中创建形状、自定义 BufferGeometry、Instances、points 和 lines,并处理几何更新与绘制调用优化。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在 React Three Fiber 特定
解决思路
- 在复制构造函数参数或 helper props 前,先检查已安装的 Three.js、Fiber、Drei 版本;示例针对 Fiber 9 / React 19 和 Three.js r185。
- 普通形状使用原生 JSX geometry;`args` 与 Three.js 构造函数一致;修改 `args` 会重建 geometry,因此应动画 transform 而不是动画构造函数输入。
- 自定义拓扑使用 `BufferGeometry`;大规模粒子集使用基于 buffer 的 `points`;保持生成的数组稳定,结果需可复现时使用确定性生成。
- 需要方便声明式实例并支持事件时使用 Drei `Instances`;对于大规模或频繁更新的集合,阅读 `references/instancing.md` 中的原生 instancing,避免每个实例的 React 开销。
- instancing 共享 geometry/material 并减少 draw call;仅仅在多个独立 mesh 间共享一个 geometry 并不会批处理它们的 draw。
- Drei `Merged` 是从 meshes 创建 instancing 抽象,而不是从 BufferGeometry 对象创建;它不会拼接任意静态 geometry。真正合并时检查 `three/addons/utils/BufferGeometryUtils.js` 的 `mergeGeometries`,并确保 attributes/indexing 兼容。
- 声明式实例应挂载在 Canvas 下并配合灯光;每个 `Instance` 归属于最近的 `Instances` provider。
- 按示例组织声明式实例:`<Instances limit={3} range={3}><boxGeometry args={[0.7, 0.7, 0.7]} /><meshStandardMaterial /><Instance position={[-1.2, 0, 0]} color='coral' /><Instance position={[0, 0, 0]} color='skyblue' /><Instance position={[1.2, 0, 0]} color='gold' /></Instances>`。
- `position` 和 `normal` attributes 通常 item size 为 3;UVs 为 item size 2。
- 用 `args={[typedArray, itemSize]}` 和正确的 `attach` 构造 JSX buffer attributes,不要只传没有构造函数参数的 `array`/`count` props。
- indices 指向 vertices;winding 决定正面;在硬法线或 UV 接缝处复制 vertices;indexed vertices 共享所有 attributes,而不仅是 positions。
- 受光照的 geometry 需要 normals。合适时使用 `computeVertexNormals()`;如果 shader 或解析法线能更便宜地表达变形,不要每帧重新计算。
- CPU buffer 写入后,设置 `attribute.needsUpdate = true`;如果 buffers 会频繁变化,在首次 GPU 上传前选择 dynamic usage。
- 在影响 bounds 的 geometry 变更后,重新计算 bounding boxes/spheres;GPU 顶点位移不会自动更新 CPU bounds 或 raycasting。
- 现代 Three.js 中 UV 选择是显式的:`texture.channel` 选择 `uv`、`uv1`、`uv2` 或 `uv3`;不要为了 AO 无条件把 `uv` 复制到 `uv2`。
- 避免为指针移动重建 buffers;如果拓扑固定,改为修改 attribute contents 或 uniforms。
- Drei `Line` 支持有用的线宽;原生 WebGL line width 受平台限制;选择屏幕空间还是世界空间厚度时检查 `worldUnits`。
- 平面文字使用 Drei `Text`,挤出 geometry 使用 `Text3D`;当前 TextGeometry 使用 `depth`,不是历史上的 `height`;核对 helper 已安装的类型和字体格式。
- 使用 `Edges` 做锐边轮廓,不要把它当作屏幕空间选择效果的替代品。
- `Bounds` 和 `Center` 会改变取景/变换;决定它们是否应在资产加载、resize 或交互后更新。
- Segment count 应根据轮廓、变形和观看距离决定;固定的“高质量”段数并不普遍更好。
- 声明式创建的 geometry 可由 R3F 拥有;共享或缓存的 geometry 需要共享生命周期;不要在一个实例仍挂载时由另一个实例 dispose 它。
- 验证:更新后检查 bounds/culling、raycast 命中位置、资源清理和 draw calls;在目标对象数量下测试;三个实例不能证明一万个实例的性能。
适用边界 · 注意事项
- 不适用于调材质外观(material appearance)而非几何构建的场景。
- 未安装对应版本的 Three.js/Fiber/Drei 或未核对已安装类型时,不要照抄构造函数参数和 helper props。
- Drei `Merged` 不适合拼接任意静态 BufferGeometry;`Edges` 不适合替代屏幕空间选择效果。