Приёмы оптимизации и инстансинг

Зная врагов 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 упрощает далёкие объекты; оптимизируйте по результатам замеров.
Проверьте себя
1. Что даёт InstancedMesh?
AРисует множество копий одной геометрии за один draw call — для тысяч одинаковых объектов
BЗагружает модели
CДобавляет туман
DВключает тени
2. Какой приём почти бесплатный и его стоит применять всегда?
AДобавлять как можно больше теней
BПереиспользование общих geometry и material вместо дублирования
CСтавить максимальную сегментацию всем объектам
DГрузить текстуры 8192x8192
3. Для чего нужен LOD (уровень детализации)?
AЧтобы менять цвет
BЧтобы включить звук
CПоказывать упрощённую модель, когда объект далеко и детали всё равно не видны
DЧтобы загрузить glTF