mcpField
T
threejs-syntax-geometries

threejs-syntax-geometries

github.com/impertio-studio开发23136 次安装30 周前更新
代码仓库

关于 threejs-syntax-geometries

threejs-syntax-geometries 是面向 Three.js 开发者的几何体参考,讲解网格数据的创建与管理,涵盖 BufferGeometry、属性、内置形状、实例化和资源处理。

主要功能

  1. 01BufferGeometry 与 BufferAttribute API
  2. 02内置几何体目录
  3. 03自定义路径与挤出
  4. 04InstancedMesh 用法
  5. 05几何体更新与释放

适用场景

  1. 01创建自定义网格
  2. 02选择内置基础形状
  3. 03高效渲染重复对象
  4. 04安全更新顶点数据

安装

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

$npx skills add https://github.com/impertio-studio/three.js-claude-skill-package --skill threejs-syntax-geometries

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

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

.gitkeep
references/
anti-patterns.md
examples.md
methods.md

详细介绍

threejs-syntax-geometries

快速参考

BufferGeometry:核心属性
属性类型默认值描述
attributesObject{}由具名 BufferAttribute 实例构成的哈希映射
indexBufferAttribute | nullnull用于索引渲染的索引缓冲区
morphAttributesObject{}变形目标属性数组
morphTargetsRelativeBooleanfalse如果为 true,变形数据表示相对偏移量
groupsArray[]用于多材质的 { start, count, materialIndex }
drawRangeObject{ start: 0, count: Infinity }要渲染的几何体部分
boundingBoxBox3 | nullnull缓存值 — 在调用 computeBoundingBox() 前为 null
boundingSphereSphere | nullnull缓存值 — 在调用 computeBoundingSphere() 前为 null
BufferGeometry:关键方法
方法返回值描述
setAttribute(name, attr)this添加或替换具名属性
getAttribute(name)BufferAttribute按名称获取属性
deleteAttribute(name)this移除具名属性
hasAttribute(name)boolean检查属性是否存在
setIndex(attr)—设置索引缓冲区
addGroup(start, count, materialIndex?)—为多材质定义渲染组
clearGroups()—移除所有组
setDrawRange(start, count)—限定渲染范围
computeVertexNormals()—根据面拓扑计算平滑法线
computeTangents()—计算切线向量(需要 position、normal、uv 和 index)
computeBoundingBox()—计算并缓存 AABB
computeBoundingSphere()—计算并缓存包围球
toNonIndexed()新几何体创建非索引副本,并复制顶点
translate(x, y, z)this原地平移顶点位置
rotateX/Y/Z(radians)this原地旋转顶点位置
scale(x, y, z)this原地缩放顶点位置
center()this将几何体中心移至原点
dispose()—释放 GPU 资源
BufferAttribute:构造函数和属性
import * as THREE from 'three';

new THREE.BufferAttribute(array: TypedArray, itemSize: number, normalized?: boolean)
属性类型默认值描述
arrayTypedArray—底层数据
itemSizenumber—每个顶点的值数量(1=标量,2=UV,3=位置,4=RGBA)
countnumber计算得出array.length / itemSize
needsUpdatebooleanfalse设置为 true,将更改上传到 GPU
usagenumberStaticDrawUsageGPU 使用提示
类型化便捷类
类底层类型用途
Float32BufferAttributeFloat32Array位置、法线、UV(最常用)
Float16BufferAttributeFloat16Array内存优化属性
Uint16BufferAttributeUint16Array索引缓冲区(顶点数 <65536)
Uint32BufferAttributeUint32Array索引缓冲区(顶点数 >65536)
Uint8BufferAttributeUint8Array字节颜色(使用 normalized=true)
Int8/Int16/Int32BufferAttribute对应数组有符号整数数据
使用提示
常量使用场景
THREE.StaticDrawUsage数据仅上传一次,读取多次(默认)
THREE.DynamicDrawUsage数据频繁更新(粒子、动画顶点)
THREE.StreamDrawUsage数据每帧更新并读取一次
关键警告

绝不要在通过 setX/setXY/setXYZ 或直接写入数组修改 BufferAttribute 数据后,忘记设置 attribute.needsUpdate = true。如果没有此标志,修改将无法传到 GPU。

绝不要假设 boundingBox 或 boundingSphere 会自动填充。在显式调用 computeBoundingBox() / computeBoundingSphere() 之前,它们都是 null。

如果需要光照,构建自定义几何体后务必调用 computeVertexNormals()。如果没有法线,MeshStandardMaterial 和其他受光照影响的材质会渲染为黑色。

从场景中永久移除几何体时,务必调用 geometry.dispose()。未释放会导致 GPU 内存泄漏。垃圾回收器不会释放 GPU 端的缓冲区。

绝不要在动画循环中调用 translate()、rotateX()、scale() 或其他原地变换方法。这些方法会永久修改实际顶点数据。运行时变换请使用 mesh.position、mesh.rotation 和 mesh.scale。

如果计划每帧更新属性数据,务必在首次渲染前将 usage 设置为 DynamicDrawUsage。初次上传后再更改 usage 对某些 GPU 驱动程序无效。

在 InstancedMesh 上调用 setMatrixAt() 后,绝不要忘记设置 instanceMatrix.needsUpdate = true。如果没有此标志,所有实例都会渲染在原点。


索引几何体与非索引几何体

方面索引几何体非索引几何体
内存较低(顶点共享)较高(顶点重复)
GPU 缓存更好(顶点复用)不复用
平面着色需要重复法线每个面自然拥有独立法线
线框边缘整洁可能显示对角线

对于顶点共享的平滑着色网格,务必使用索引几何体。只有在需要逐面属性(具有唯一法线的平面着色)时,才使用 geometry.toNonIndexed()。


全部 21 种内置几何体

基本体
几何体关键参数
BoxGeometry(width=1, height=1, depth=1, wSeg=1, hSeg=1, dSeg=1)
SphereGeometry(radius=1, wSeg=32, hSeg=16, phiStart, phiLen, thetaStart, thetaLen)
PlaneGeometry(width=1, height=1, wSeg=1, hSeg=1)
CylinderGeometry(radTop=1, radBot=1, height=1, radSeg=32, hSeg=1, open, thetaStart, thetaLen)
ConeGeometry(radius=1, height=1, radSeg=32, hSeg=1, open, thetaStart, thetaLen)
CapsuleGeometry(radius=1, length=1, capSeg=4, radSeg=8)
TorusGeometry(radius=1, tube=0.4, radSeg=12, tubSeg=48, arc=2PI)
TorusKnotGeometry(radius=1, tube=0.4, tubSeg=64, radSeg=8, p=2, q=3)
CircleGeometry(radius=1, seg=32, thetaStart=0, thetaLen=2PI)
RingGeometry(inner=0.5, outer=1, thetaSeg=32, phiSeg=1, thetaStart, thetaLen)
多面体

所有几何体均接受 (radius=1, detail=0)。detail 控制细分级别。

几何体基础面数
TetrahedronGeometry4
OctahedronGeometry8
DodecahedronGeometry12
IcosahedronGeometry20
PolyhedronGeometry自定义(vertices, indices, radius, detail)
基于路径的几何体
几何体描述
ExtrudeGeometry(shapes, options)将 2D Shape 拉伸为 3D
ShapeGeometry(shapes, curveSegments=12)从 Shape 创建平面 2D 几何体
LatheGeometry(points, segments=12, phiStart, phiLength)绕 Y 轴旋转 2D 轮廓
TubeGeometry(path, tubSeg=64, radius=1, radSeg=8, closed)沿 Curve3 创建管体
实用工具
几何体描述
EdgesGeometry(geometry, thresholdAngle=1)角度大于阈值的边(整洁的轮廓)
WireframeGeometry(geometry)所有三角形边(调试可视化)

ExtrudeGeometry 选项

选项类型默认值描述
depthnumber1挤出深度
stepsnumber1沿深度方向的细分步数
bevelEnabledbooleantrue启用边缘倒角
bevelThicknessnumber0.2向形状内部延伸的倒角深度
bevelSizenumberbevelThickness - 0.1倒角与轮廓之间的距离
bevelOffsetnumber0倒角相对于边缘的偏移量
bevelSegmentsnumber3倒角细分精度
curveSegmentsnumber12曲线上的点数
extrudePathCurveundefined沿其挤出的 3D 路径
UVGeneratorObjectWorldUVGenerator自定义 UV 生成

Shape 类:2D 路径绘制

import * as THREE from 'three';

const shape = new THREE.Shape();
shape.moveTo(x, y);                                    // Start new subpath
shape.lineTo(x, y);                                    // Straight line
shape.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);   // Cubic Bezier
shape.quadraticCurveTo(cpx, cpy, x, y);                // Quadratic Bezier
shape.splineThru(points);                               // Smooth spline through Vector2[]
shape.arc(aX, aY, radius, startAngle, endAngle, cw);   // Relative arc
shape.absarc(aX, aY, radius, startAngle, endAngle, cw); // Absolute arc

// Holes
const holePath = new THREE.Path();
holePath.absarc(0, 0, 0.5, 0, Math.PI * 2);
shape.holes.push(holePath);

变形目标

import * as THREE from 'three';

// Define morph target positions
const morphPositions = new Float32Array([/* ... */]);
geometry.morphAttributes.position = [
  new THREE.BufferAttribute(morphPositions, 3)
];

// Control on the mesh
mesh.morphTargetInfluences[0] = 0.5; // 50% blend toward morph target 0

// Named morph targets (from glTF)
mesh.morphTargetDictionary; // { "smile": 0, "frown": 1 }

当变形数据表示偏移量而非绝对位置时,请设置 geometry.morphTargetsRelative = true。


InstancedMesh

import * as THREE from 'three';

const mesh = new THREE.InstancedMesh(geometry, material, count);
属性类型描述
instanceMatrixInstancedBufferAttribute4x4 矩阵(每个实例 16 个浮点数)
instanceColorInstancedBufferAttribute | null每个实例的 RGB 颜色(首次调用 setColorAt 时创建)
countnumber实例数量(构造后只读)
方法描述
setMatrixAt(index, matrix4)设置实例的变换
getMatrixAt(index, matrix4)将变换读取到目标对象中
setColorAt(index, color)设置实例的颜色
getColorAt(index, color)读取实例的颜色
性能指南
实例数量建议
< 10使用独立的 Mesh 对象
10 - 100两种方式均可;根据具体情况进行性能分析
100 - 10,000始终使用 InstancedMesh
> 10,000使用带空间细分的 InstancedMesh 或 BatchedMesh(r160+)
自定义每实例属性
import * as THREE from 'three';

const phases = new Float32Array(count);
for (let i = 0; i < count; i++) phases[i] = Math.random();
mesh.geometry.setAttribute('aPhase', new THREE.InstancedBufferAttribute(phases, 1));
// Access in vertex shader: attribute float aPhase;

使用组实现多材质

import * as THREE from 'three';

geometry.addGroup(0, 6, 0);    // First 6 indices -> material[0]
geometry.addGroup(6, 6, 1);    // Next 6 indices  -> material[1]
const mesh = new THREE.Mesh(geometry, [materialA, materialB]);

InterleavedBuffer

对于大型网格(10,000+ 个顶点),为获得最佳 GPU 缓存性能:

import * as THREE from 'three';

const stride = 8; // 3 (position) + 3 (normal) + 2 (uv)
const buffer = new THREE.InterleavedBuffer(new Float32Array(vertexCount * stride), stride);

geometry.setAttribute('position', new THREE.InterleavedBufferAttribute(buffer, 3, 0));
geometry.setAttribute('normal',   new THREE.InterleavedBufferAttribute(buffer, 3, 3));
geometry.setAttribute('uv',       new THREE.InterleavedBufferAttribute(buffer, 2, 6));

当各属性单独更新时,始终使用独立缓冲区。仅当所有属性均为静态或一同更新时,才使用交错缓冲区。


释放规则

  • 从场景中永久移除几何体时,始终调用 geometry.dispose()
  • 共享几何体(由多个网格使用):仅在所有网格都移除后释放
  • 内置几何体:移除使用它的网格时释放
  • JavaScript 垃圾回收器不会释放 GPU 端的顶点缓冲区

参考链接

官方来源

评论

支持 Markdown