关于 threejs-geometry
面向 Three.js 网格形状和顶点数据处理的技能,帮助开发者选择并构建几何体。内容涵盖几何表示、有效属性、基于测量的性能优化、资源所有权和形状验证。
主要功能
- 01选择基础或自定义几何体
- 02构建位置、法线、颜色、UV 和索引缓冲区
- 03更新动态属性与边界
- 04针对测得的绘制调用瓶颈使用实例化
- 05管理几何体所有权与释放
适用场景
- 01根据顶点数据创建自定义网格
- 02修复法线、UV 接缝、绕序或剔除问题
- 03更新运行时变化的几何体
- 04减少重复网格的绘制调用
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ akillness/ jeo-skills --skill threejs-geometry安装后在 Claude Code 中输入/threejs-geometry确认已加载。
附带文件SKILL.toonevals/evals.json
详细介绍
Three.js 几何体
此技能用于网格形状和顶点数据处理。表面外观请交由
threejs-materials,图像/UV 资源处理请交由 threejs-textures,整个场景的设置请交由
threejs-fundamentals。
何时使用此技能
- 选择内置基本体、
BufferGeometry、ShapeGeometry或文本几何体 - 为自定义网格生成位置、法线、颜色、UV 和索引
- 安全更新动态属性,或修复错误的法线、绕序和剔除问题
- 测量绘制调用开销后,将重复的相同网格替换为
InstancedMesh
说明
步骤 1:选择最简单的几何体表示方式
- 当内置几何体的拓扑与所需特征匹配时,优先使用内置几何体。
- 使用
BufferGeometry处理生成或导入的顶点数据;旧版Geometry并非当前 Three.js 的实现方式。 - 仅当顶点确实共享时,才选择索引几何体。对于需要不同法线、UV 或顶点颜色的接缝,不要使用索引。
- 除非该功能明确拥有某个网格的几何体,否则应将其视为不可变的共享数据;按实例修改前先克隆。
步骤 2:构建有效的属性缓冲区
const geometry = new THREE.BufferGeometry();
geometry.setAttribute(
"position",
new THREE.Float32BufferAttribute([
-1, -1, 0,
1, -1, 0,
0, 1, 0,
], 3),
);
geometry.setIndex([0, 1, 2]);
geometry.computeVertexNormals();
geometry.computeBoundingSphere();
const mesh = new THREE.Mesh(geometry, material);
属性项大小必须与其语义相符:位置/法线为 3,UV 为 2,颜色通常为 3。修改已上传到 GPU 的属性后,设置 attribute.needsUpdate = true。当动态位置可能超出原有边界时,重新计算边界。
步骤 3:仅针对已测量的瓶颈使用性能工具
| 情况 | 首选方案 |
|---|---|
| 同一几何体/材质的多个副本 | InstancedMesh |
| 每个实例的颜色或变换 | 实例属性/矩阵 |
| 大型静态地形或模型 | 索引 BufferGeometry、合理剔除 |
| 数千个微小粒子 | 使用一个几何体/材质的 Points |
| 调试边缘或技术线框 | EdgesGeometry / WireframeGeometry |
| 拓扑或材质不同 | 使用独立网格;不要强行实例化 |
const instances = new THREE.InstancedMesh(geometry, material, count);
const matrix = new THREE.Matrix4();
for (let i = 0; i < count; i += 1) {
matrix.makeTranslation(i * 2, 0, 0);
instances.setMatrixAt(i, matrix);
}
instances.instanceMatrix.needsUpdate = true;
步骤 4:管理所有权和清理
当某个功能拥有的几何体不再有使用者时,调用 geometry.dispose()。替换几何体后,应释放被替换的几何体;在资源加载器缓存的共享几何体最后一个使用者释放前,不要将其释放。
步骤 5:验证形状和预算
- 使用辅助对象/调试视图检查法线、UV 接缝、面绕序和边界体积。
- 使用具有代表性的低密度和高密度输入,检查是否存在孔洞、NaN 或背面丢失。
- 测量实例化前后的绘制调用次数以及 GPU/CPU 帧耗时。
- 通过该功能的正常生命周期和清理流程测试动态几何体更新。
示例
构建可释放的程序化网格
根据稳定的输入值生成属性,上传前验证数组长度,然后将几何体所有者与其清理函数一并保存。每帧都重新创建大型几何体几乎总是错误做法;只有测量结果证明有必要时,才修改动态属性。
将加载或生成的网格居中
使用 geometry.computeBoundingBox() 并根据其中心计算偏移,然后更新边界。不要根据单个顶点猜测中心,也不要在资源的本地原点具有语义意义时应用网格变换。
最佳实践
- 与场景保持一致的坐标系和单位约定。
- 使用类型化数组;不要在每帧通过对象数组构建高频顶点缓冲区。
- 仅在拓扑/位置发生变化时重新计算法线,不要在每次渲染时都计算。
- 动态位置变化后更新边界,确保视锥体剔除正确。
- 将实例化视为绘制调用优化,而非高开销着色器或细节过多几何体的解决方案。
参考资料
评论
支持 Markdown