Приёмы оптимизации и инстансинг
Зная врагов FPS, применяем приёмы: переиспользование, инстансинг и уровни детализации.
Главная идея оптимизации — делать меньше работы: меньше draw calls, меньше уникальных данных, меньше полигонов там, где они не видны.
Переиспользование (почти бесплатно)
Самый дешёвый приём мы уже знаем: не создавайте дубликаты geometry и material. Одна геометрия и один материал на множество одинаковых мешей экономят память и помогают движку. Это привычка, которую стоит включить сразу.
const geo = new THREE.BoxGeometry(1, 1, 1);
const mat = new THREE.MeshStandardMaterial({ color: 0x88aa55 });
const meshes = positions.map((p) => {
const m = new THREE.Mesh(geo, mat); // общие geo/mat
m.position.copy(p);
return m;
});
Инстансинг (InstancedMesh)
Когда одинаковых объектов тысячи — трава, деревья, кубики, частицы — даже с общей геометрией каждый меш всё ещё даёт свой draw call. Решение — InstancedMesh: одна геометрия, один материал, но множество позиций, нарисованных одним вызовом.
const count = 5000;
const mesh = new THREE.InstancedMesh(geometry, material, count);
const dummy = new THREE.Object3D();
for (let i = 0; i < count; i++) {
dummy.position.set(
Math.random() * 100 - 50,
0,
Math.random() * 100 - 50
);
dummy.updateMatrix();
mesh.setMatrixAt(i, dummy.matrix); // задаём положение i-й копии
}
scene.add(mesh); // 5000 объектов — 1 draw call
Как мы считали в прошлом уроке, это снижает число вызовов с 5000 до 1 — разница в производительности колоссальная.
Уровни детализации (LOD)
LOD (Level of Detail) подменяет модель на более грубую, когда она далеко: вблизи — детальная сфера на 4000 треугольников, вдали — грубая на 200. Глаз разницы не заметит, а GPU выдохнет. В Three.js для этого есть класс THREE.LOD.
Чек-лист оптимизации
| Приём | Когда |
| общие geometry/material | всегда |
| InstancedMesh | много одинаковых объектов |
| LOD | детальные объекты, которые бывают далеко |
| сжатие/уменьшение текстур | тяжёлые текстуры |
| меньше теневых источников | тени дорогие — оставьте один-два |
Не оптимизируйте вслепую
Сначала измерьте узкое место (renderer.info, профайлер), потом бейте именно по нему. Инстансить то, чего на сцене десять штук, — пустая трата сил.
Итог
- Переиспользование geometry/material — дёшево и всегда полезно.
- InstancedMesh рисует тысячи копий одним draw call.
- LOD упрощает далёкие объекты; оптимизируйте по результатам замеров.