SceneOptimizer: автоматические оптимизации

В сложных 3D-сценах производительность напрямую зависит от количества объектов, используемых материалов, источников света, теней, постобработки и разрешения текстур. При росте сложности сцены частота кадров может снижаться до неприемлемых значений.

В библиотеке Babylon.js для решения этой проблемы реализован механизм автоматической адаптации производительности — SceneOptimizer. Его задача заключается в динамическом изменении параметров сцены до тех пор, пока не будет достигнут заданный уровень производительности.

SceneOptimizer отслеживает текущий FPS и постепенно применяет оптимизации. Каждая оптимизация уменьшает нагрузку на графическую подсистему. Если после применения одного шага частота кадров всё ещё ниже требуемой, система применяет следующий шаг.

Подход основан на принципе постепенного ухудшения качества сцены ради сохранения плавности работы.


Основная идея работы

SceneOptimizer функционирует как последовательность уровней оптимизации. Каждый уровень содержит один или несколько оптимизационных действий.

Алгоритм работы:

  1. Проверяется текущая частота кадров сцены.
  2. Если FPS ниже заданного значения, запускается оптимизация уровня 0.
  3. После применения оптимизаций система ожидает небольшой промежуток времени.
  4. FPS проверяется повторно.
  5. Если цель не достигнута — применяется следующий уровень оптимизаций.
  6. Процесс продолжается до достижения нужной производительности либо до выполнения всех уровней.

Таким образом, механизм работает как адаптивная система деградации качества.


Подключение SceneOptimizer

Использование оптимизатора требует подключения сцены Babylon.js. Базовый пример:

const optimizerOptions = new BABYLON.SceneOptimizerOptions(60);

BABYLON.SceneOptimizer.OptimizeAsync(scene, optimizerOptions);

Параметры:

  • scene — сцена Babylon.js, к которой применяется оптимизация
  • 60 — целевой FPS

OptimizeAsync запускает процесс оптимизации асинхронно и продолжает работу до достижения нужной производительности.


SceneOptimizerOptions

Класс SceneOptimizerOptions управляет поведением оптимизатора.

Основные параметры:

Параметр Описание
targetFrameRate целевая частота кадров
trackerDuration время ожидания между проверками FPS
optimizations список оптимизаций

Пример создания конфигурации:

const options = new BABYLON.SceneOptimizerOptions(60, 2000);

Здесь:

  • 60 FPS — требуемая частота
  • 2000 ms — интервал между проверками

Чем больше интервал, тем стабильнее оценка производительности.


Уровни оптимизаций

SceneOptimizer использует приоритеты для определения порядка применения оптимизаций.

Каждая оптимизация имеет числовой приоритет.

Меньшее значение приоритета означает более раннее применение.

Пример:

options.optimizations.push(
    new BABYLON.ShadowsOptimization(0)
);

options.optimizations.push(
    new BABYLON.LensFlaresOptimization(1)
);

Сначала отключатся тени, затем эффекты линз.

Такая структура позволяет постепенно снижать нагрузку.


Встроенные типы оптимизаций

Babylon.js предоставляет набор готовых оптимизационных действий.

ShadowsOptimization

Отключает генерацию теней.

Тени являются одной из самых затратных операций рендеринга, поскольку требуют дополнительных проходов рендеринга.

new BABYLON.ShadowsOptimization(priority)

LensFlaresOptimization

Отключает эффекты бликов источников света.

new BABYLON.LensFlaresOptimization(priority)

Lens flare может существенно нагружать систему при использовании нескольких источников света.


PostProcessesOptimization

Отключает постобработку.

Постпроцессы выполняются после основного рендеринга сцены и могут включать:

  • bloom
  • color grading
  • blur
  • depth of field
new BABYLON.PostProcessesOptimization(priority)

ParticlesOptimization

Отключает системы частиц.

new BABYLON.ParticlesOptimization(priority)

Частицы требуют большого количества вычислений и особенно сильно влияют на мобильные устройства.


TextureOptimization

Уменьшает разрешение текстур.

new BABYLON.TextureOptimization(priority, maximumSize)

Пример:

new BABYLON.TextureOptimization(2, 512)

Текстуры будут уменьшены до размера 512x512.

Это снижает:

  • потребление видеопамяти
  • время выборки текстур
  • нагрузку на GPU

RenderTargetsOptimization

Отключает дополнительные рендер-таргеты.

new BABYLON.RenderTargetsOptimization(priority)

Render targets используются для:

  • отражений
  • теней
  • постобработки

Их отключение может значительно повысить FPS.


HardwareScalingOptimization

Уменьшает внутреннее разрешение рендера.

new BABYLON.HardwareScalingOptimization(priority, maximumScale)

Пример:

new BABYLON.HardwareScalingOptimization(3, 2)

Фактически сцена рендерится в более низком разрешении и затем масштабируется.

Этот метод даёт один из самых сильных приростов производительности.


Готовые пресеты оптимизации

Babylon.js содержит три стандартных набора настроек.

LowDegradationAllowed

Минимальная деградация качества.

BABYLON.SceneOptimizerOptions.LowDegradationAllowed();

Используется, когда требуется сохранить визуальное качество.


ModerateDegradationAllowed

Баланс между качеством и производительностью.

BABYLON.SceneOptimizerOptions.ModerateDegradationAllowed();

Наиболее распространённый вариант.


HighDegradationAllowed

Максимальная агрессивность оптимизации.

BABYLON.SceneOptimizerOptions.HighDegradationAllowed();

Может отключать большое количество эффектов.


Пример полной настройки оптимизатора

const options = new BABYLON.SceneOptimizerOptions(60, 2000);

options.optimizations.push(new BABYLON.ShadowsOptimization(0));
options.optimizations.push(new BABYLON.LensFlaresOptimization(0));

options.optimizations.push(new BABYLON.PostProcessesOptimization(1));
options.optimizations.push(new BABYLON.ParticlesOptimization(1));

options.optimizations.push(new BABYLON.TextureOptimization(2, 512));

options.optimizations.push(new BABYLON.RenderTargetsOptimization(3));

options.optimizations.push(new BABYLON.HardwareScalingOptimization(4, 2));

BABYLON.SceneOptimizer.OptimizeAsync(scene, options);

В этом примере:

  1. Сначала отключаются тени и блики.
  2. Затем постобработка и частицы.
  3. После этого уменьшается размер текстур.
  4. Затем отключаются render targets.
  5. Последним шагом уменьшается разрешение рендеринга.

Колбэки завершения оптимизации

OptimizeAsync поддерживает колбэки, позволяющие отследить результат.

BABYLON.SceneOptimizer.OptimizeAsync(
    scene,
    options,
    function () {
        console.log("Целевая производительность достигнута");
    },
    function () {
        console.log("Все оптимизации применены, но FPS недостаточен");
    }
);

Первый колбэк вызывается при достижении целевого FPS. Второй — если оптимизации закончились, но производительность всё ещё недостаточна.


Остановка оптимизатора

Иногда требуется вручную остановить процесс.

optimizer.stop();

Оптимизация может быть остановлена, например, если пользователь переключает графические настройки.


Создание пользовательских оптимизаций

Babylon.js позволяет реализовывать собственные классы оптимизации.

Для этого используется базовый класс SceneOptimization.

Пример:

class DisableLightsOptimization extends BABYLON.SceneOptimization {

    apply(scene) {
        scene.lights.forEach(light => {
            light.setEnabled(false);
        });

        return true;
    }

}

Добавление в оптимизатор:

options.optimizations.push(
    new DisableLightsOptimization(1)
);

Метод apply должен вернуть:

  • true — если оптимизация была успешно применена
  • false — если попытка не удалась

Выбор стратегии оптимизации

Эффективная стратегия зависит от характера сцены.

Типичные подходы:

Игровые сцены

  • отключение теней
  • уменьшение частиц
  • понижение разрешения

Архитектурная визуализация

  • уменьшение разрешения текстур
  • отключение постобработки
  • снижение качества отражений

Мобильные приложения

  • сильное hardware scaling
  • отключение частиц
  • минимальное количество источников света

Влияние оптимизаций на GPU и CPU

Оптимизации могут снижать нагрузку на разные компоненты системы.

GPU-нагрузка уменьшается при:

  • отключении теней
  • уменьшении разрешения
  • уменьшении текстур
  • отключении постобработки

CPU-нагрузка уменьшается при:

  • отключении систем частиц
  • уменьшении количества объектов
  • снижении количества источников света

SceneOptimizer позволяет комбинировать оба подхода.


Применение в адаптивной графике

SceneOptimizer часто используется для реализации адаптивной графики, при которой приложение автоматически подстраивается под возможности устройства.

Типичный сценарий:

  1. Сцена запускается в максимальном качестве.
  2. Измеряется FPS.
  3. При падении производительности включается оптимизатор.
  4. Сцена адаптируется под конкретное устройство.

Такой подход особенно важен для:

  • веб-игр
  • мобильных браузеров
  • VR-сцен
  • больших 3D-визуализаций

Комбинирование с ручной оптимизацией

SceneOptimizer не заменяет ручную оптимизацию сцены. Он работает как дополнительный уровень защиты от падения производительности.

Наиболее эффективная стратегия:

  1. оптимизировать геометрию
  2. уменьшить количество draw calls
  3. использовать instancing
  4. оптимизировать материалы
  5. применять SceneOptimizer как динамический механизм адаптации

Это позволяет обеспечить стабильную частоту кадров даже при сложных сценах и различных типах устройств.