three优化篇
1.模型简化
- 型简化是通过减少多边形数(即顶点和面)来降低模型的复杂度。LOD(Level of Detail,细节层次)
- Three.js支持LOD功能,能根据相机与模型的距离,自动切换不同细节的模型版本,从而减少渲染负荷。
import { LOD } from 'three';
const lod = new LOD();
// 设置低细节模型(适合远处显示)
const lowDetailMesh = createLowDetailMesh();
lod.addLevel(lowDetailMesh, 100); // 距离相机100单位时使用低细节模型
// 设置中细节模型
const mediumDetailMesh = createMediumDetailMesh();
lod.addLevel(mediumDetailMesh, 50); // 距离相机50单位时使用中细节模型
// 设置高细节模型(适合近距离显示)
const highDetailMesh = createHighDetailMesh();
lod.addLevel(highDetailMesh, 0); // 距离相机为0时使用高细节模型
scene.add(lod);
2.模型批处理
- 批处理将多个小模型合并为一个大模型,减少WebGL的绘制调用次数,从而提高性能。在Three.js中,常用的批处理技术包括合并网格(Mesh)、实例化渲染(Instanced Rendering)等。
- 可以将场景中多个静态对象合并成一个网格,从而减少渲染调用。
import { BufferGeometry, BoxGeometry, Mesh, MeshBasicMaterial, MeshStandardMaterial, Scene } from 'three';
// 创建材质和几何体
const material = new MeshStandardMaterial({ color: 0x00ff00 });
const geometry = new BoxGeometry();
// 创建多个网格
const meshes = [];
for (let i = 0; i < 10; i++) {
const mesh = new Mesh(geometry, material);
mesh.position.set(i * 2, 0, 0);
meshes.push(mesh);
}
// 合并网格
const mergedGeometry = BufferGeometryUtils.mergeBufferGeometries(meshes.map(m => m.geometry), true);
const mergedMesh = new Mesh(mergedGeometry, material);
scene.add(mergedMesh);
实例化渲染:使用InstancedMesh可以实现一次性渲染多个相同的网格,提高渲染效率。
import { InstancedMesh, BoxGeometry, MeshBasicMaterial, Matrix4 } from 'three';
const geometry = new BoxGeometry();
const material = new MeshBasicMaterial({ color: 0x00ff00 });
const count = 100;
const instancedMesh = new InstancedMesh(geometry, material, count);
for (let i = 0; i < count; i++) {
const matrix = new Matrix4();
matrix.setPosition(i % 10, Math.floor(i / 10), 0); // 设置位置
instancedMesh.setMatrixAt(i, matrix);
}
scene.add(instancedMesh);
硬件加速与性能优化技巧
硬件加速和性能优化是确保Three.js应用在多种设备上流畅运行的关键。优化渲染管道和减少GPU负荷能有效提高应用的响应速度。
- 使用帧率限制和动态分辨率。通过调整渲染器的更新时间,控制最大帧率。
let lastRenderTime = 0;
const maxFPS = 30;
function animate(time) {
const delta = time - lastRenderTime;
if (delta > 1000 / maxFPS) {
renderer.render(scene, camera);
lastRenderTime = time;
}
requestAnimationFrame(animate);
}
animate(0);
动态分辨率:动态调整渲染分辨率,在保持画质的同时降低渲染负担。Three.js中可以通过调整渲染器的setPixelRatio来实现。
renderer.setPixelRatio(window.devicePixelRatio > 1 ? 1.5 : 1);
场景剔除和遮挡剔除
- 场景剔除:Three.js中的场景剔除技术会自动隐藏相机视野外的对象。可以进一步使用分区剔除技术来优化大型场景。
- 遮挡剔除:在一些场景中,对被完全遮挡的物体进行剔除,可以减轻渲染负担。
清除不必要场景模型
/* 清除不再使用内存模型几何体与材质 防止泄露 */
mesh.remove()
1.
mesh.traverse((obj:any)=> {
if (obj.type === 'Mesh') {
obj.geometry.dispose();
obj.material.dispose();
}
})
2.
model.traverse((obj) => {
if (!obj.isMesh) return;
obj.geometry.dispose();
obj.material.dispose();
});
model = null;
节流渲染 requestAnimationFrame()
-面板超出一定时间停止渲染、鼠标事件触发重新渲染
1. 节流渲染
let timeOut;
let render = () => {
stats.update();
if (timeOut) {
controls.update();
composer.render();
}
/* 动画事件 */
requestAnimationFrame(render);
};render()