threejs-geometry by cloudai-x/threejs-skills
npx skills add https://github.com/cloudai-x/threejs-skills --skill threejs-geometryimport * as THREE from "three";
// 内置几何体
const box = new THREE.BoxGeometry(1, 1, 1);
const sphere = new THREE.SphereGeometry(0.5, 32, 32);
const plane = new THREE.PlaneGeometry(10, 10);
// 创建网格
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const mesh = new THREE.Mesh(box, material);
scene.add(mesh);
// 立方体 - 宽度, 高度, 深度, 宽度分段数, 高度分段数, 深度分段数
new THREE.BoxGeometry(1, 1, 1, 1, 1, 1);
// 球体 - 半径, 宽度分段数, 高度分段数, phi起始角度, phi长度, theta起始角度, theta长度
new THREE.SphereGeometry(1, 32, 32);
new THREE.SphereGeometry(1, 32, 32, 0, Math.PI * 2, 0, Math.PI); // 完整球体
new THREE.SphereGeometry(1, 32, 32, 0, Math.PI); // 半球体
// 平面 - 宽度, 高度, 宽度分段数, 高度分段数
new THREE.PlaneGeometry(10, 10, 1, 1);
// 圆形 - 半径, 分段数, theta起始角度, theta长度
new THREE.CircleGeometry(1, 32);
new THREE.CircleGeometry(1, 32, 0, Math.PI); // 半圆
// 圆柱体 - 顶部半径, 底部半径, 高度, 径向分段数, 高度分段数, 是否开口
new THREE.CylinderGeometry(1, 1, 2, 32, 1, false);
new THREE.CylinderGeometry(0, 1, 2, 32); // 圆锥体
new THREE.CylinderGeometry(1, 1, 2, 6); // 六棱柱
// 圆锥体 - 半径, 高度, 径向分段数, 高度分段数, 是否开口
new THREE.ConeGeometry(1, 2, 32, 1, false);
// 圆环体 - 半径, 管径, 径向分段数, 管状分段数, 弧度
new THREE.TorusGeometry(1, 0.4, 16, 100);
// 圆环结 - 半径, 管径, 管状分段数, 径向分段数, p, q
new THREE.TorusKnotGeometry(1, 0.4, 100, 16, 2, 3);
// 圆环 - 内半径, 外半径, theta分段数, phi分段数
new THREE.RingGeometry(0.5, 1, 32, 1);
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
// 胶囊体 - 半径, 长度, 端帽分段数, 径向分段数
new THREE.CapsuleGeometry(0.5, 1, 4, 8);
// 十二面体 - 半径, 细节级别
new THREE.DodecahedronGeometry(1, 0);
// 二十面体 - 半径, 细节级别 (0 = 20个面, 值越高越平滑)
new THREE.IcosahedronGeometry(1, 0);
// 八面体 - 半径, 细节级别
new THREE.OctahedronGeometry(1, 0);
// 四面体 - 半径, 细节级别
new THREE.TetrahedronGeometry(1, 0);
// 多面体 - 顶点, 索引, 半径, 细节级别
const vertices = [1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1];
const indices = [2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1];
new THREE.PolyhedronGeometry(vertices, indices, 1, 0);
// 旋转体 - 点数组[], 分段数, phi起始角度, phi长度
const points = [
new THREE.Vector2(0, 0),
new THREE.Vector2(0.5, 0),
new THREE.Vector2(0.5, 1),
new THREE.Vector2(0, 1),
];
new THREE.LatheGeometry(points, 32);
// 挤出体 - 形状, 选项
const shape = new THREE.Shape();
shape.moveTo(0, 0);
shape.lineTo(1, 0);
shape.lineTo(1, 1);
shape.lineTo(0, 1);
shape.lineTo(0, 0);
const extrudeSettings = {
steps: 2,
depth: 1,
bevelEnabled: true,
bevelThickness: 0.1,
bevelSize: 0.1,
bevelSegments: 3,
};
new THREE.ExtrudeGeometry(shape, extrudeSettings);
// 管道 - 路径, 管状分段数, 半径, 径向分段数, 是否闭合
const curve = new THREE.CatmullRomCurve3([
new THREE.Vector3(-1, 0, 0),
new THREE.Vector3(0, 1, 0),
new THREE.Vector3(1, 0, 0),
]);
new THREE.TubeGeometry(curve, 64, 0.2, 8, false);
import { FontLoader } from "three/examples/jsm/loaders/FontLoader.js";
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry.js";
const loader = new FontLoader();
loader.load("fonts/helvetiker_regular.typeface.json", (font) => {
const geometry = new TextGeometry("Hello", {
font: font,
size: 1,
depth: 0.2, // 旧版本中为 'height'
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 0.03,
bevelSize: 0.02,
bevelSegments: 5,
});
// 居中文本
geometry.computeBoundingBox();
geometry.center();
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
});
所有几何体的基类。将数据存储为类型化数组以提高 GPU 效率。
const geometry = new THREE.BufferGeometry();
// 顶点 (每个顶点3个浮点数: x, y, z)
const vertices = new Float32Array([
-1,
-1,
0, // 顶点 0
1,
-1,
0, // 顶点 1
1,
1,
0, // 顶点 2
-1,
1,
0, // 顶点 3
]);
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
// 索引 (用于索引几何体 - 重用顶点)
const indices = new Uint16Array([
0,
1,
2, // 三角形 1
0,
2,
3, // 三角形 2
]);
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
// 法线 (光照必需)
const normals = new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]);
geometry.setAttribute("normal", new THREE.BufferAttribute(normals, 3));
// UV坐标 (用于纹理贴图)
const uvs = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]);
geometry.setAttribute("uv", new THREE.BufferAttribute(uvs, 2));
// 颜色 (逐顶点颜色)
const colors = new Float32Array([
1,
0,
0, // 红色
0,
1,
0, // 绿色
0,
0,
1, // 蓝色
1,
1,
0, // 黄色
]);
geometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));
// 配合使用: material.vertexColors = true
// 常见属性类型
new THREE.BufferAttribute(array, itemSize);
// 类型化数组选项
new Float32Array(count * itemSize); // 位置, 法线, UV坐标
new Uint16Array(count); // 索引 (最多65535个顶点)
new Uint32Array(count); // 索引 (大型网格)
new Uint8Array(count * itemSize); // 颜色 (0-255范围)
// 项目大小
// 位置: 3 (x, y, z)
// 法线: 3 (x, y, z)
// UV坐标: 2 (u, v)
// 颜色: 3 (r, g, b) 或 4 (r, g, b, a)
// 索引: 1
const positions = geometry.attributes.position;
// 修改顶点
positions.setXYZ(index, x, y, z);
// 访问顶点
const x = positions.getX(index);
const y = positions.getY(index);
const z = positions.getZ(index);
// GPU更新标志
positions.needsUpdate = true;
// 位置变化后重新计算法线
geometry.computeVertexNormals();
// 变化后重新计算边界框/球体
geometry.computeBoundingBox();
geometry.computeBoundingSphere();
// 大型网格的更高效内存布局
const interleavedBuffer = new THREE.InterleavedBuffer(
new Float32Array([
// pos.x, pos.y, pos.z, uv.u, uv.v (每个顶点重复)
-1, -1, 0, 0, 0, 1, -1, 0, 1, 0, 1, 1, 0, 1, 1, -1, 1, 0, 0, 1,
]),
5, // 步幅 (每个顶点的浮点数)
);
geometry.setAttribute(
"position",
new THREE.InterleavedBufferAttribute(interleavedBuffer, 3, 0),
); // 大小 3, 偏移 0
geometry.setAttribute(
"uv",
new THREE.InterleavedBufferAttribute(interleavedBuffer, 2, 3),
); // 大小 2, 偏移 3
// 边缘线 (仅硬边)
const edges = new THREE.EdgesGeometry(boxGeometry, 15); // 15 = 阈值角度
const edgeMesh = new THREE.LineSegments(
edges,
new THREE.LineBasicMaterial({ color: 0xffffff }),
);
// 线框 (所有三角形)
const wireframe = new THREE.WireframeGeometry(boxGeometry);
const wireMesh = new THREE.LineSegments(
wireframe,
new THREE.LineBasicMaterial({ color: 0xffffff }),
);
// 创建点云
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(1000 * 3);
for (let i = 0; i < 1000; i++) {
positions[i * 3] = (Math.random() - 0.5) * 10;
positions[i * 3 + 1] = (Math.random() - 0.5) * 10;
positions[i * 3 + 2] = (Math.random() - 0.5) * 10;
}
geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
size: 0.1,
sizeAttenuation: true, // 大小随距离减小
color: 0xffffff,
});
const points = new THREE.Points(geometry, material);
scene.add(points);
// 线条 (连接点)
const points = [
new THREE.Vector3(-1, 0, 0),
new THREE.Vector3(0, 1, 0),
new THREE.Vector3(1, 0, 0),
];
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const line = new THREE.Line(
geometry,
new THREE.LineBasicMaterial({ color: 0xff0000 }),
);
// 闭合环线
const loop = new THREE.LineLoop(geometry, material);
// 线段 (点对)
const segmentsGeometry = new THREE.BufferGeometry();
segmentsGeometry.setAttribute(
"position",
new THREE.BufferAttribute(
new Float32Array([
-1,
0,
0,
0,
1,
0, // 线段 1
0,
1,
0,
1,
0,
0, // 线段 2
]),
3,
),
);
const segments = new THREE.LineSegments(segmentsGeometry, material);
高效渲染同一几何体的多个副本。
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const count = 1000;
const instancedMesh = new THREE.InstancedMesh(geometry, material, count);
// 为每个实例设置变换
const dummy = new THREE.Object3D();
const matrix = new THREE.Matrix4();
for (let i = 0; i < count; i++) {
dummy.position.set(
(Math.random() - 0.5) * 20,
(Math.random() - 0.5) * 20,
(Math.random() - 0.5) * 20,
);
dummy.rotation.set(Math.random() * Math.PI, Math.random() * Math.PI, 0);
dummy.scale.setScalar(0.5 + Math.random());
dummy.updateMatrix();
instancedMesh.setMatrixAt(i, dummy.matrix);
}
// GPU更新标志
instancedMesh.instanceMatrix.needsUpdate = true;
// 可选: 每个实例的颜色
instancedMesh.instanceColor = new THREE.InstancedBufferAttribute(
new Float32Array(count * 3),
3,
);
for (let i = 0; i < count; i++) {
instancedMesh.setColorAt(
i,
new THREE.Color(Math.random(), Math.random(), Math.random()),
);
}
instancedMesh.instanceColor.needsUpdate = true;
scene.add(instancedMesh);
// 更新单个实例
const matrix = new THREE.Matrix4();
instancedMesh.getMatrixAt(index, matrix);
// 修改矩阵...
instancedMesh.setMatrixAt(index, matrix);
instancedMesh.instanceMatrix.needsUpdate = true;
// 与实例化网格进行光线投射
const intersects = raycaster.intersectObject(instancedMesh);
if (intersects.length > 0) {
const instanceId = intersects[0].instanceId;
}
用于自定义超出变换/颜色的每个实例属性。
const geometry = new THREE.InstancedBufferGeometry();
geometry.copy(new THREE.BoxGeometry(1, 1, 1));
// 添加每个实例属性
const offsets = new Float32Array(count * 3);
for (let i = 0; i < count; i++) {
offsets[i * 3] = Math.random() * 10;
offsets[i * 3 + 1] = Math.random() * 10;
offsets[i * 3 + 2] = Math.random() * 10;
}
geometry.setAttribute("offset", new THREE.InstancedBufferAttribute(offsets, 3));
// 在着色器中使用
// attribute vec3 offset;
// vec3 transformed = position + offset;
import * as BufferGeometryUtils from "three/examples/jsm/utils/BufferGeometryUtils.js";
// 合并几何体 (必须具有相同属性)
const merged = BufferGeometryUtils.mergeGeometries([geo1, geo2, geo3]);
// 合并并分组 (用于多材质)
const merged = BufferGeometryUtils.mergeGeometries([geo1, geo2], true);
// 计算切线 (法线贴图必需)
BufferGeometryUtils.computeTangents(geometry);
// 交错属性以提高性能
const interleaved = BufferGeometryUtils.interleaveAttributes([
geometry.attributes.position,
geometry.attributes.normal,
geometry.attributes.uv,
]);
geometry.computeBoundingBox();
geometry.center(); // 移动顶点使中心位于原点
geometry.computeBoundingBox();
const size = new THREE.Vector3();
geometry.boundingBox.getSize(size);
const maxDim = Math.max(size.x, size.y, size.z);
geometry.scale(1 / maxDim, 1 / maxDim, 1 / maxDim);
const clone = geometry.clone();
clone.rotateX(Math.PI / 2);
clone.translate(0, 1, 0);
clone.scale(2, 2, 2);
// 基础几何体
const geometry = new THREE.BoxGeometry(1, 1, 1, 4, 4, 4);
// 创建变形目标
const morphPositions = geometry.attributes.position.array.slice();
for (let i = 0; i < morphPositions.length; i += 3) {
morphPositions[i] *= 2; // 缩放 X
morphPositions[i + 1] *= 0.5; // 压缩 Y
}
geometry.morphAttributes.position = [
new THREE.BufferAttribute(new Float32Array(morphPositions), 3),
];
const mesh = new THREE.Mesh(geometry, material);
mesh.morphTargetInfluences[0] = 0.5; // 50% 混合
mergeGeometries 减少绘制调用geometry.dispose()// 常见用途的良好分段数
new THREE.SphereGeometry(1, 32, 32); // 良好质量
new THREE.SphereGeometry(1, 64, 64); // 高质量
new THREE.SphereGeometry(1, 16, 16); // 性能模式
// 完成后释放
geometry.dispose();
threejs-fundamentals - 场景设置和 Object3Dthreejs-materials - 网格的材质类型threejs-shaders - 自定义顶点操作每周安装量
1.6K
仓库
GitHub 星标
1.8K
首次出现
2026年1月20日
安全审计
安装于
opencode1.2K
gemini-cli1.2K
claude-code1.1K
codex1.1K
cursor1.0K
github-copilot956
import * as THREE from "three";
// Built-in geometry
const box = new THREE.BoxGeometry(1, 1, 1);
const sphere = new THREE.SphereGeometry(0.5, 32, 32);
const plane = new THREE.PlaneGeometry(10, 10);
// Create mesh
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const mesh = new THREE.Mesh(box, material);
scene.add(mesh);
// Box - width, height, depth, widthSegments, heightSegments, depthSegments
new THREE.BoxGeometry(1, 1, 1, 1, 1, 1);
// Sphere - radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength
new THREE.SphereGeometry(1, 32, 32);
new THREE.SphereGeometry(1, 32, 32, 0, Math.PI * 2, 0, Math.PI); // Full sphere
new THREE.SphereGeometry(1, 32, 32, 0, Math.PI); // Hemisphere
// Plane - width, height, widthSegments, heightSegments
new THREE.PlaneGeometry(10, 10, 1, 1);
// Circle - radius, segments, thetaStart, thetaLength
new THREE.CircleGeometry(1, 32);
new THREE.CircleGeometry(1, 32, 0, Math.PI); // Semicircle
// Cylinder - radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded
new THREE.CylinderGeometry(1, 1, 2, 32, 1, false);
new THREE.CylinderGeometry(0, 1, 2, 32); // Cone
new THREE.CylinderGeometry(1, 1, 2, 6); // Hexagonal prism
// Cone - radius, height, radialSegments, heightSegments, openEnded
new THREE.ConeGeometry(1, 2, 32, 1, false);
// Torus - radius, tube, radialSegments, tubularSegments, arc
new THREE.TorusGeometry(1, 0.4, 16, 100);
// TorusKnot - radius, tube, tubularSegments, radialSegments, p, q
new THREE.TorusKnotGeometry(1, 0.4, 100, 16, 2, 3);
// Ring - innerRadius, outerRadius, thetaSegments, phiSegments
new THREE.RingGeometry(0.5, 1, 32, 1);
// Capsule - radius, length, capSegments, radialSegments
new THREE.CapsuleGeometry(0.5, 1, 4, 8);
// Dodecahedron - radius, detail
new THREE.DodecahedronGeometry(1, 0);
// Icosahedron - radius, detail (0 = 20 faces, higher = smoother)
new THREE.IcosahedronGeometry(1, 0);
// Octahedron - radius, detail
new THREE.OctahedronGeometry(1, 0);
// Tetrahedron - radius, detail
new THREE.TetrahedronGeometry(1, 0);
// Polyhedron - vertices, indices, radius, detail
const vertices = [1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1];
const indices = [2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1];
new THREE.PolyhedronGeometry(vertices, indices, 1, 0);
// Lathe - points[], segments, phiStart, phiLength
const points = [
new THREE.Vector2(0, 0),
new THREE.Vector2(0.5, 0),
new THREE.Vector2(0.5, 1),
new THREE.Vector2(0, 1),
];
new THREE.LatheGeometry(points, 32);
// Extrude - shape, options
const shape = new THREE.Shape();
shape.moveTo(0, 0);
shape.lineTo(1, 0);
shape.lineTo(1, 1);
shape.lineTo(0, 1);
shape.lineTo(0, 0);
const extrudeSettings = {
steps: 2,
depth: 1,
bevelEnabled: true,
bevelThickness: 0.1,
bevelSize: 0.1,
bevelSegments: 3,
};
new THREE.ExtrudeGeometry(shape, extrudeSettings);
// Tube - path, tubularSegments, radius, radialSegments, closed
const curve = new THREE.CatmullRomCurve3([
new THREE.Vector3(-1, 0, 0),
new THREE.Vector3(0, 1, 0),
new THREE.Vector3(1, 0, 0),
]);
new THREE.TubeGeometry(curve, 64, 0.2, 8, false);
import { FontLoader } from "three/examples/jsm/loaders/FontLoader.js";
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry.js";
const loader = new FontLoader();
loader.load("fonts/helvetiker_regular.typeface.json", (font) => {
const geometry = new TextGeometry("Hello", {
font: font,
size: 1,
depth: 0.2, // Was 'height' in older versions
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 0.03,
bevelSize: 0.02,
bevelSegments: 5,
});
// Center text
geometry.computeBoundingBox();
geometry.center();
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
});
The base class for all geometries. Stores data as typed arrays for GPU efficiency.
const geometry = new THREE.BufferGeometry();
// Vertices (3 floats per vertex: x, y, z)
const vertices = new Float32Array([
-1,
-1,
0, // vertex 0
1,
-1,
0, // vertex 1
1,
1,
0, // vertex 2
-1,
1,
0, // vertex 3
]);
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
// Indices (for indexed geometry - reuse vertices)
const indices = new Uint16Array([
0,
1,
2, // triangle 1
0,
2,
3, // triangle 2
]);
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
// Normals (required for lighting)
const normals = new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]);
geometry.setAttribute("normal", new THREE.BufferAttribute(normals, 3));
// UVs (for texturing)
const uvs = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]);
geometry.setAttribute("uv", new THREE.BufferAttribute(uvs, 2));
// Colors (per-vertex colors)
const colors = new Float32Array([
1,
0,
0, // red
0,
1,
0, // green
0,
0,
1, // blue
1,
1,
0, // yellow
]);
geometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));
// Use with: material.vertexColors = true
// Common attribute types
new THREE.BufferAttribute(array, itemSize);
// Typed array options
new Float32Array(count * itemSize); // Positions, normals, UVs
new Uint16Array(count); // Indices (up to 65535 vertices)
new Uint32Array(count); // Indices (larger meshes)
new Uint8Array(count * itemSize); // Colors (0-255 range)
// Item sizes
// Position: 3 (x, y, z)
// Normal: 3 (x, y, z)
// UV: 2 (u, v)
// Color: 3 (r, g, b) or 4 (r, g, b, a)
// Index: 1
const positions = geometry.attributes.position;
// Modify vertex
positions.setXYZ(index, x, y, z);
// Access vertex
const x = positions.getX(index);
const y = positions.getY(index);
const z = positions.getZ(index);
// Flag for GPU update
positions.needsUpdate = true;
// Recompute normals after position changes
geometry.computeVertexNormals();
// Recompute bounding box/sphere after changes
geometry.computeBoundingBox();
geometry.computeBoundingSphere();
// More efficient memory layout for large meshes
const interleavedBuffer = new THREE.InterleavedBuffer(
new Float32Array([
// pos.x, pos.y, pos.z, uv.u, uv.v (repeated per vertex)
-1, -1, 0, 0, 0, 1, -1, 0, 1, 0, 1, 1, 0, 1, 1, -1, 1, 0, 0, 1,
]),
5, // stride (floats per vertex)
);
geometry.setAttribute(
"position",
new THREE.InterleavedBufferAttribute(interleavedBuffer, 3, 0),
); // size 3, offset 0
geometry.setAttribute(
"uv",
new THREE.InterleavedBufferAttribute(interleavedBuffer, 2, 3),
); // size 2, offset 3
// Edge lines (only hard edges)
const edges = new THREE.EdgesGeometry(boxGeometry, 15); // 15 = threshold angle
const edgeMesh = new THREE.LineSegments(
edges,
new THREE.LineBasicMaterial({ color: 0xffffff }),
);
// Wireframe (all triangles)
const wireframe = new THREE.WireframeGeometry(boxGeometry);
const wireMesh = new THREE.LineSegments(
wireframe,
new THREE.LineBasicMaterial({ color: 0xffffff }),
);
// Create point cloud
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(1000 * 3);
for (let i = 0; i < 1000; i++) {
positions[i * 3] = (Math.random() - 0.5) * 10;
positions[i * 3 + 1] = (Math.random() - 0.5) * 10;
positions[i * 3 + 2] = (Math.random() - 0.5) * 10;
}
geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
size: 0.1,
sizeAttenuation: true, // Size decreases with distance
color: 0xffffff,
});
const points = new THREE.Points(geometry, material);
scene.add(points);
// Line (connected points)
const points = [
new THREE.Vector3(-1, 0, 0),
new THREE.Vector3(0, 1, 0),
new THREE.Vector3(1, 0, 0),
];
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const line = new THREE.Line(
geometry,
new THREE.LineBasicMaterial({ color: 0xff0000 }),
);
// LineLoop (closed loop)
const loop = new THREE.LineLoop(geometry, material);
// LineSegments (pairs of points)
const segmentsGeometry = new THREE.BufferGeometry();
segmentsGeometry.setAttribute(
"position",
new THREE.BufferAttribute(
new Float32Array([
-1,
0,
0,
0,
1,
0, // segment 1
0,
1,
0,
1,
0,
0, // segment 2
]),
3,
),
);
const segments = new THREE.LineSegments(segmentsGeometry, material);
Efficiently render many copies of the same geometry.
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const count = 1000;
const instancedMesh = new THREE.InstancedMesh(geometry, material, count);
// Set transforms for each instance
const dummy = new THREE.Object3D();
const matrix = new THREE.Matrix4();
for (let i = 0; i < count; i++) {
dummy.position.set(
(Math.random() - 0.5) * 20,
(Math.random() - 0.5) * 20,
(Math.random() - 0.5) * 20,
);
dummy.rotation.set(Math.random() * Math.PI, Math.random() * Math.PI, 0);
dummy.scale.setScalar(0.5 + Math.random());
dummy.updateMatrix();
instancedMesh.setMatrixAt(i, dummy.matrix);
}
// Flag for GPU update
instancedMesh.instanceMatrix.needsUpdate = true;
// Optional: per-instance colors
instancedMesh.instanceColor = new THREE.InstancedBufferAttribute(
new Float32Array(count * 3),
3,
);
for (let i = 0; i < count; i++) {
instancedMesh.setColorAt(
i,
new THREE.Color(Math.random(), Math.random(), Math.random()),
);
}
instancedMesh.instanceColor.needsUpdate = true;
scene.add(instancedMesh);
// Update single instance
const matrix = new THREE.Matrix4();
instancedMesh.getMatrixAt(index, matrix);
// Modify matrix...
instancedMesh.setMatrixAt(index, matrix);
instancedMesh.instanceMatrix.needsUpdate = true;
// Raycasting with instanced mesh
const intersects = raycaster.intersectObject(instancedMesh);
if (intersects.length > 0) {
const instanceId = intersects[0].instanceId;
}
For custom per-instance attributes beyond transform/color.
const geometry = new THREE.InstancedBufferGeometry();
geometry.copy(new THREE.BoxGeometry(1, 1, 1));
// Add per-instance attribute
const offsets = new Float32Array(count * 3);
for (let i = 0; i < count; i++) {
offsets[i * 3] = Math.random() * 10;
offsets[i * 3 + 1] = Math.random() * 10;
offsets[i * 3 + 2] = Math.random() * 10;
}
geometry.setAttribute("offset", new THREE.InstancedBufferAttribute(offsets, 3));
// Use in shader
// attribute vec3 offset;
// vec3 transformed = position + offset;
import * as BufferGeometryUtils from "three/examples/jsm/utils/BufferGeometryUtils.js";
// Merge geometries (must have same attributes)
const merged = BufferGeometryUtils.mergeGeometries([geo1, geo2, geo3]);
// Merge with groups (for multi-material)
const merged = BufferGeometryUtils.mergeGeometries([geo1, geo2], true);
// Compute tangents (required for normal maps)
BufferGeometryUtils.computeTangents(geometry);
// Interleave attributes for better performance
const interleaved = BufferGeometryUtils.interleaveAttributes([
geometry.attributes.position,
geometry.attributes.normal,
geometry.attributes.uv,
]);
geometry.computeBoundingBox();
geometry.center(); // Move vertices so center is at origin
geometry.computeBoundingBox();
const size = new THREE.Vector3();
geometry.boundingBox.getSize(size);
const maxDim = Math.max(size.x, size.y, size.z);
geometry.scale(1 / maxDim, 1 / maxDim, 1 / maxDim);
const clone = geometry.clone();
clone.rotateX(Math.PI / 2);
clone.translate(0, 1, 0);
clone.scale(2, 2, 2);
// Base geometry
const geometry = new THREE.BoxGeometry(1, 1, 1, 4, 4, 4);
// Create morph target
const morphPositions = geometry.attributes.position.array.slice();
for (let i = 0; i < morphPositions.length; i += 3) {
morphPositions[i] *= 2; // Scale X
morphPositions[i + 1] *= 0.5; // Squash Y
}
geometry.morphAttributes.position = [
new THREE.BufferAttribute(new Float32Array(morphPositions), 3),
];
const mesh = new THREE.Mesh(geometry, material);
mesh.morphTargetInfluences[0] = 0.5; // 50% blend
mergeGeometriesgeometry.dispose()// Good segment counts for common uses
new THREE.SphereGeometry(1, 32, 32); // Good quality
new THREE.SphereGeometry(1, 64, 64); // High quality
new THREE.SphereGeometry(1, 16, 16); // Performance mode
// Dispose when done
geometry.dispose();
threejs-fundamentals - Scene setup and Object3Dthreejs-materials - Material types for meshesthreejs-shaders - Custom vertex manipulationWeekly Installs
1.6K
Repository
GitHub Stars
1.8K
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode1.2K
gemini-cli1.2K
claude-code1.1K
codex1.1K
cursor1.0K
github-copilot956
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装