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

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