Bloom эффект

Bloom (свечение) представляет собой постобработочный визуальный эффект, имитирующий рассеивание света от ярких областей изображения за пределы их геометрических границ. В физически корректной модели рендеринга подобное поведение связано с особенностями восприятия человеческого зрения и оптическими ограничениями камер: интенсивные источники света создают ореол, мягко «перетекающий» в соседние пиксели.

В контексте WebGL и 3D-графики bloom реализуется как этап постобработки, применяемый к уже отрендеренной сцене. Основной принцип заключается в выделении ярких пикселей, их размывке (blur) и последующем наложении на исходное изображение с аддитивным смешиванием.


Постобработка в архитектуре CesiumJS

Внутренний рендеринг сцены в CesiumJS построен на многоступенчатом графическом конвейере:

  • рендер геометрии (terrain, 3D Tiles, primitives)
  • наложение материалов и освещения
  • генерация буфера кадра (color buffer)
  • постобработка (post-processing stages)

Bloom относится именно к последнему этапу. Он не изменяет геометрию объектов и не влияет на освещение напрямую, а работает исключительно с итоговым изображением.

Постобработка в Cesium организована через объект сцены:

const viewer = new Cesium.Viewer("cesiumContainer");
const scene = viewer.scene;

scene.postProcessStages;

Включение bloom-эффекта

В стандартной конфигурации bloom может быть активирован через коллекцию постпроцессов:

const viewer = new Cesium.Viewer("cesiumContainer", {
    postProcessStages: {
        bloom: {
            enabled: true
        }
    }
});

Альтернативный способ — явное управление через сцену:

const scene = viewer.scene;

scene.postProcessStages.bloom.enabled = true;

При включении эффекта pipeline дополняется следующими шагами:

  1. выделение ярких фрагментов изображения (threshold pass)
  2. размытие выделенной маски (Gaussian blur)
  3. смешивание результата с исходным кадром (compositing)

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

Bloom в CesiumJS настраивается через набор параметров, влияющих на характер свечения.

Intensity (интенсивность)

Определяет силу добавляемого свечения:

scene.postProcessStages.bloom.uniforms.intensity = 1.2;

Высокие значения приводят к «пересвеченным» ореолам, низкие — к едва заметному эффекту.


Threshold (порог яркости)

Контролирует минимальную яркость пикселей, участвующих в эффекте:

scene.postProcessStages.bloom.uniforms.threshold = 0.8;

Пиксели ниже порога исключаются из bloom-процесса, что позволяет ограничить эффект только наиболее яркими объектами.


Blur scale (радиус размытия)

Отвечает за размер и мягкость ореола:

scene.postProcessStages.bloom.uniforms.blurScale = 3.0;

Увеличение значения расширяет световое пятно и снижает его резкость.


Glow only (режим свечения)

Позволяет отображать только свечение без базового изображения:

scene.postProcessStages.bloom.uniforms.glowOnly = false;

При значении true выводится исключительно размытая маска яркости.


Взаимодействие с материалами и освещением

Эффект bloom тесно связан с emissive-компонентами материалов. В сценах Cesium яркость объектов часто задаётся через:

  • material.emission
  • Cesium.Color с высокой интенсивностью
  • текстуры ночного освещения (night maps)

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

const material = new Cesium.ColorMaterialProperty(
    Cesium.Color.YELLOW.withAlpha(1.0)
);

При использовании 3D Tiles эмиссивные свойства часто задаются через JSON tileset:

"pbrMetallicRoughness": {
  "emissiveFactor": [1.0, 0.8, 0.2]
}

Яркие emissive-объекты становятся основными кандидатами для bloom-процесса.


Bloom и 3D Tiles

В сценах с 3D Tiles эффект особенно заметен на:

  • ночных городских моделях
  • инфраструктурных данных (дороги, линии освещения)
  • энергетических объектах (подсветка станций, трубопроводов)

Пример загрузки tileset с активным bloom:

const tileset = new Cesium.Cesium3DTileset({
    url: "tileset.json"
});

viewer.scene.primitives.add(tileset);

viewer.scene.postProcessStages.bloom.enabled = true;
viewer.scene.postProcessStages.bloom.uniforms.intensity = 1.5;
viewer.scene.postProcessStages.bloom.uniforms.threshold = 0.7;

Производительность и ограничения

Bloom относится к дорогостоящим постпроцессам, так как требует нескольких полноэкранных проходов:

  • выделение яркости (full-screen pass)
  • горизонтальный blur
  • вертикальный blur
  • композитинг

Основные факторы нагрузки:

  • разрешение canvas
  • количество активных постпроцессов
  • сложность сцены (особенно 3D Tiles)
  • частота кадров (target frame rate)

Снижение затрат достигается через:

scene.postProcessStages.bloom.uniforms.blurScale = 1.0;
scene.postProcessStages.bloom.uniforms.intensity = 0.8;

или отключением при низком FPS:

scene.postProcessStages.bloom.enabled = false;

Связь с HDR и тональной компрессией

Bloom в Cesium корректно работает в связке с HDR-рендерингом. В сценах с расширенным динамическим диапазоном:

  • яркие источники света выходят за пределы стандартного [0..1]
  • tone mapping сжимает диапазон в экранное пространство
  • bloom добавляет визуальное «перетекание» яркости

Это особенно важно для ночных режимов глобуса, где источники света должны восприниматься как реальные городские огни.


Комбинация с другими постпроцессами

Постпроцессинг в CesiumJS допускает одновременное использование нескольких эффектов:

scene.postProcessStages.fxaa.enabled = true;
scene.postProcessStages.bloom.enabled = true;

FXAA снижает aliasing, а bloom добавляет световые ореолы. Совместное использование требует баланса, поскольку оба эффекта работают с финальным изображением и могут усиливать шум и засветку.


Типовые конфигурации

Ночная городская сцена

scene.postProcessStages.bloom.enabled = true;
scene.postProcessStages.bloom.uniforms.intensity = 2.0;
scene.postProcessStages.bloom.uniforms.threshold = 0.75;
scene.postProcessStages.bloom.uniforms.blurScale = 2.5;

Сдержанный визуальный режим

scene.postProcessStages.bloom.enabled = true;
scene.postProcessStages.bloom.uniforms.intensity = 0.6;
scene.postProcessStages.bloom.uniforms.threshold = 0.9;
scene.postProcessStages.bloom.uniforms.blurScale = 1.0;

Минимальный эффект для производительных систем

scene.postProcessStages.bloom.enabled = true;
scene.postProcessStages.bloom.uniforms.intensity = 0.3;
scene.postProcessStages.bloom.uniforms.threshold = 0.95;
scene.postProcessStages.bloom.uniforms.blurScale = 0.8;

Поведение при разных источниках света

Эффективность bloom зависит от типа визуальных источников:

  • emissive материалы — наиболее предсказуемый результат
  • изображения ночных текстур — умеренный эффект
  • процедурное освещение — зависит от динамического диапазона
  • отражающие поверхности — усиливают ореолы косвенно

В глобальных сценах Cesium важную роль играют тайловые наборы, где световые зоны часто закодированы в текстурах, а не в динамическом освещении.


Особенности реализации blur-прохода

Размытие в bloom реализуется через separable Gaussian blur:

  • горизонтальный проход
  • вертикальный проход

Такой подход снижает вычислительную сложность с O(n²) до O(n), где n — радиус фильтра. В WebGL это критично для поддержания интерактивной частоты кадров при высоких разрешениях.


Управление качеством изображения

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

  • resolution scale сцены
  • blurScale bloom
  • интенсивность threshold
  • отключение при низкой нагрузке GPU

В больших сценах с глобусом оптимизация bloom часто становится частью общего профиля рендеринга, особенно при работе с 3D Tiles высокой плотности.