В сложных 3D-сценах производительность напрямую зависит от количества объектов, используемых материалов, источников света, теней, постобработки и разрешения текстур. При росте сложности сцены частота кадров может снижаться до неприемлемых значений.
В библиотеке Babylon.js для решения этой проблемы реализован механизм автоматической адаптации производительности — SceneOptimizer. Его задача заключается в динамическом изменении параметров сцены до тех пор, пока не будет достигнут заданный уровень производительности.
SceneOptimizer отслеживает текущий FPS и постепенно применяет оптимизации. Каждая оптимизация уменьшает нагрузку на графическую подсистему. Если после применения одного шага частота кадров всё ещё ниже требуемой, система применяет следующий шаг.
Подход основан на принципе постепенного ухудшения качества сцены ради сохранения плавности работы.
SceneOptimizer функционирует как последовательность уровней оптимизации. Каждый уровень содержит один или несколько оптимизационных действий.
Алгоритм работы:
Таким образом, механизм работает как адаптивная система деградации качества.
Использование оптимизатора требует подключения сцены Babylon.js. Базовый пример:
const optimizerOptions = new BABYLON.SceneOptimizerOptions(60);
BABYLON.SceneOptimizer.OptimizeAsync(scene, optimizerOptions);
Параметры:
OptimizeAsync запускает процесс оптимизации асинхронно и продолжает работу до достижения нужной производительности.
Класс SceneOptimizerOptions управляет поведением оптимизатора.
Основные параметры:
| Параметр | Описание |
|---|---|
| targetFrameRate | целевая частота кадров |
| trackerDuration | время ожидания между проверками FPS |
| optimizations | список оптимизаций |
Пример создания конфигурации:
const options = new BABYLON.SceneOptimizerOptions(60, 2000);
Здесь:
Чем больше интервал, тем стабильнее оценка производительности.
SceneOptimizer использует приоритеты для определения порядка применения оптимизаций.
Каждая оптимизация имеет числовой приоритет.
Меньшее значение приоритета означает более раннее применение.
Пример:
options.optimizations.push(
new BABYLON.ShadowsOptimization(0)
);
options.optimizations.push(
new BABYLON.LensFlaresOptimization(1)
);
Сначала отключатся тени, затем эффекты линз.
Такая структура позволяет постепенно снижать нагрузку.
Babylon.js предоставляет набор готовых оптимизационных действий.
Отключает генерацию теней.
Тени являются одной из самых затратных операций рендеринга, поскольку требуют дополнительных проходов рендеринга.
new BABYLON.ShadowsOptimization(priority)
Отключает эффекты бликов источников света.
new BABYLON.LensFlaresOptimization(priority)
Lens flare может существенно нагружать систему при использовании нескольких источников света.
Отключает постобработку.
Постпроцессы выполняются после основного рендеринга сцены и могут включать:
new BABYLON.PostProcessesOptimization(priority)
Отключает системы частиц.
new BABYLON.ParticlesOptimization(priority)
Частицы требуют большого количества вычислений и особенно сильно влияют на мобильные устройства.
Уменьшает разрешение текстур.
new BABYLON.TextureOptimization(priority, maximumSize)
Пример:
new BABYLON.TextureOptimization(2, 512)
Текстуры будут уменьшены до размера 512x512.
Это снижает:
Отключает дополнительные рендер-таргеты.
new BABYLON.RenderTargetsOptimization(priority)
Render targets используются для:
Их отключение может значительно повысить FPS.
Уменьшает внутреннее разрешение рендера.
new BABYLON.HardwareScalingOptimization(priority, maximumScale)
Пример:
new BABYLON.HardwareScalingOptimization(3, 2)
Фактически сцена рендерится в более низком разрешении и затем масштабируется.
Этот метод даёт один из самых сильных приростов производительности.
Babylon.js содержит три стандартных набора настроек.
Минимальная деградация качества.
BABYLON.SceneOptimizerOptions.LowDegradationAllowed();
Используется, когда требуется сохранить визуальное качество.
Баланс между качеством и производительностью.
BABYLON.SceneOptimizerOptions.ModerateDegradationAllowed();
Наиболее распространённый вариант.
Максимальная агрессивность оптимизации.
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);
В этом примере:
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 должен вернуть:
Эффективная стратегия зависит от характера сцены.
Типичные подходы:
Игровые сцены
Архитектурная визуализация
Мобильные приложения
Оптимизации могут снижать нагрузку на разные компоненты системы.
GPU-нагрузка уменьшается при:
CPU-нагрузка уменьшается при:
SceneOptimizer позволяет комбинировать оба подхода.
SceneOptimizer часто используется для реализации адаптивной графики, при которой приложение автоматически подстраивается под возможности устройства.
Типичный сценарий:
Такой подход особенно важен для:
SceneOptimizer не заменяет ручную оптимизацию сцены. Он работает как дополнительный уровень защиты от падения производительности.
Наиболее эффективная стратегия:
Это позволяет обеспечить стабильную частоту кадров даже при сложных сценах и различных типах устройств.