在 Three.js 中,BufferGeometry
允许我们创建自定义的几何体。相比 Geometry
(已废弃),BufferGeometry
更加高效,特别适用于 WebGL 渲染。
1. 创建 BufferGeometry
在 Three.js 中,BufferGeometry
是创建自定义几何体的基础。
const geometry = new THREE.BufferGeometry();
2. 设置顶点数据
**顶点(Vertices)**决定了几何体的形状。通常,使用 Float32Array
存储顶点数据,并通过 setAttribute
绑定到 BufferGeometry
。
(1)创建基本点
const positions = new Float32Array([
0, 0, 0, // 顶点1 (x, y, z)
1, 0, 0, // 顶点2
0, 1, 0 // 顶点3
]);
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
new THREE.BufferAttribute(positions, 3)
表示每个顶点有 3 个数据(x, y, z)。
3. 颜色、法线、UV 坐标
(1)顶点颜色
每个顶点可以有自己的颜色:
const colors = new Float32Array([
1, 0, 0, // 红色
0, 1, 0, // 绿色
0, 0, 1 // 蓝色
]);
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
需要在 Material
里启用 vertexColors
:
const material = new THREE.PointsMaterial({ vertexColors: true });
(2)法线(用于光照计算)
const normals = new Float32Array([
0, 0, 1, // 法线向量
0, 0, 1,
0, 0, 1
]);
geometry.setAttribute('normal', new THREE.BufferAttribute(normals, 3));
法线用于计算光照效果,使物体渲染更真实。
(3)UV 贴图坐标
UV 贴图用于材质映射:
const uvs = new Float32Array([
0, 0, // 顶点1 UV
1, 0, // 顶点2 UV
0, 1 // 顶点3 UV
]);
geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2));
(0,0)
表示贴图的左下角,(1,1)
表示右上角。
4. 使用索引(Index)优化渲染
有时候多个三角形共享顶点,可以使用 setIndex
来减少重复数据:
const indices = new Uint16Array([
0, 1, 2, // 三角形1
2, 1, 3 // 三角形2
]);
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
setIndex()
让 WebGL 复用相同顶点,减少内存占用,提高渲染效率。
5. 生成动态几何体
(1)修改顶点坐标
const positions = geometry.attributes.position.array;
positions[0] += 0.01; // 修改某个顶点的 X 轴位置
geometry.attributes.position.needsUpdate = true; // 通知 Three.js 更新
(2)让点移动
const animate = () => {
requestAnimationFrame(animate);
for (let i = 0; i < positions.length; i++) {
positions[i] += Math.sin(i + performance.now() * 0.001) * 0.01;
}
geometry.attributes.position.needsUpdate = true;
renderer.render(scene, camera);
};
animate();
这样,顶点位置会随时间变化,使几何体动态变形。
6. 创建粒子系统
自定义几何体常用于粒子系统:
const count = 5000;
const positions = new Float32Array(count * 3);
for (let i = 0; i < count * 3; i++) {
positions[i] = (Math.random() - 0.5) * 10;
}
const particleGeometry = new THREE.BufferGeometry();
particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({ size: 0.05, color: 0xff0000 });
const particles = new THREE.Points(particleGeometry, material);
scene.add(particles);
THREE.PointsMaterial
适用于粒子系统,sizeAttenuation: true
使远近粒子大小不同。
7. 线框模式
要查看几何体的线框:
const material = new THREE.MeshBasicMaterial({
color: 0x00ff00,
wireframe: true
});
这样只会渲染网格,不会填充面。
8. 计算法线
如果自定义几何体缺少法线,可以用:
geometry.computeVertexNormals();
这个方法会根据三角形的方向自动计算光照法线。
9. 合并多个 BufferGeometry
有时,我们想合并多个几何体:
const geometries = [
new THREE.BoxGeometry(),
new THREE.SphereGeometry()
];
const mergedGeometry = THREE.BufferGeometryUtils.mergeBufferGeometries(geometries);
const mesh = new THREE.Mesh(mergedGeometry, new THREE.MeshStandardMaterial());
scene.add(mesh);
mergeBufferGeometries
可以合并多个 BufferGeometry
,减少 draw calls,提高性能。
10. 用 ShaderMaterial 自定义渲染
自定义 BufferGeometry
可以结合 Shader 实现更复杂的效果:
const material = new THREE.ShaderMaterial({
vertexShader: `
varying vec3 vPosition;
void main() {
vPosition = position;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
varying vec3 vPosition;
void main() {
gl_FragColor = vec4(vPosition * 0.5 + 0.5, 1.0);
}
`
});
这段 Shader 代码会让物体表面颜色变化,取决于顶点位置。
总结
知识点 | 说明 |
---|---|
BufferGeometry | 现代 WebGL 高效几何体数据格式 |
setAttribute | 用于设置顶点位置、颜色、法线、UV |
setIndex | 让 WebGL 复用顶点,提高渲染效率 |
needsUpdate | 修改 BufferGeometry 后需设置 needsUpdate = true |
computeVertexNormals() | 计算光照法线,保证正确的光影效果 |
mergeBufferGeometries() | 合并多个 BufferGeometry ,提高性能 |
ShaderMaterial | 结合 GLSL 着色器,实现复杂渲染效果 |
BufferGeometry
是 Three.js 的重要组成部分,通过它可以创建各种复杂的 3D 形状、粒子效果、动态几何体等,提高 WebGL 性能! 🚀