Three.js 自定义 Geometry(几何体)知识点整理

在 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 性能! 🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值