Occlusion Culling

В трёхмерной графике значительная часть геометрии сцены может быть полностью скрыта другими объектами. Несмотря на это, стандартный рендеринг всё равно отправляет такие объекты в графический конвейер, выполняя вычисления вершин, фрагментов и освещения. Это приводит к лишней нагрузке на GPU.

Occlusion Culling — это техника оптимизации, позволяющая исключать из рендеринга объекты, полностью перекрытые другими объектами сцены. Если объект не виден из текущей точки камеры, его отрисовка пропускается.

В библиотеке Babylon.js механизм Occlusion Culling встроен в систему Mesh и может использоваться без сторонних расширений. Проверка видимости происходит на уровне графического API с применением occlusion queries, поддерживаемых WebGL.

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


Различие между Frustum Culling и Occlusion Culling

Перед применением Occlusion Culling необходимо понимать отличие этой техники от более базового механизма — Frustum Culling.

Frustum Culling

Frustum Culling проверяет, находится ли объект внутри пирамиды видимости камеры (view frustum).

Если объект полностью вне этой пирамиды, он не рендерится.

Особенности:

  • выполняется на CPU;
  • работает очень быстро;
  • проверяет только геометрическое пересечение с фрустумом;
  • не учитывает перекрытие объектов.

Пример: объект может находиться перед камерой, но быть полностью скрыт стеной. Frustum Culling всё равно сочтёт его видимым.


Occlusion Culling

Occlusion Culling проверяет реальную видимость объекта, учитывая перекрытие другими объектами.

Особенности:

  • выполняется с помощью GPU;
  • использует аппаратные occlusion queries;
  • определяет, попадают ли пиксели объекта в буфер кадра.

Если объект полностью скрыт другими объектами, он исключается из рендеринга.


Поддержка Occlusion Queries в Babylon.js

Babylon.js использует аппаратные возможности WebGL:

  • EXT_occlusion_query_boolean
  • ANY_SAMPLES_PASSED

Механизм работает следующим образом:

  1. GPU получает запрос на проверку видимости объекта.
  2. Рендерится его упрощённая форма (bounding box).
  3. Проверяется, прошёл ли хотя бы один фрагмент тест глубины.
  4. Если ни один пиксель не прошёл — объект считается скрытым.

Проверка выполняется асинхронно, чтобы не блокировать GPU.


Основные свойства Occlusion Culling

Каждый объект Mesh имеет ряд свойств для управления системой окклюзии.

occlusionType

Определяет стратегию обработки результата occlusion query.

Возможные значения:

  • BABYLON.AbstractMesh.OCCLUSION_TYPE_NONE
  • BABYLON.AbstractMesh.OCCLUSION_TYPE_OPTIMISTIC
  • BABYLON.AbstractMesh.OCCLUSION_TYPE_STRICT

Пример:

mesh.occlusionType = BABYLON.AbstractMesh.OCCLUSION_TYPE_OPTIMISTIC;

OPTIMISTIC

Если результат запроса ещё не получен, объект временно считается видимым.

Плюсы:

  • отсутствие задержек;
  • стабильный рендеринг.

Минусы:

  • возможна кратковременная отрисовка скрытых объектов.

STRICT

Если результат запроса ещё не готов, объект считается скрытым.

Плюсы:

  • более строгая оптимизация.

Минусы:

  • возможны визуальные артефакты (объект может появиться с задержкой).

occlusionRetryCount

Определяет количество попыток повторной проверки видимости объекта.

mesh.occlusionRetryCount = 5;

Если объект остаётся скрытым, система повторит проверку указанное количество раз.

Это полезно для объектов, которые могут появиться после перемещения камеры.


occlusionQueryAlgorithmType

Определяет алгоритм проверки.

mesh.occlusionQueryAlgorithmType = BABYLON.AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE;

Поддерживаются два варианта:

ACCURATE

Используется точная проверка количества пикселей.

BABYLON.AbstractMesh.OCCLUSION_ALGORITHM_TYPE_ACCURATE

Плюсы:

  • высокая точность.

Минусы:

  • больше вычислений.

CONSERVATIVE

Проверяет, прошёл ли хотя бы один пиксель.

BABYLON.AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE

Плюсы:

  • значительно быстрее;
  • используется по умолчанию.

Минусы:

  • менее точная оценка.

Базовый пример использования

Включение Occlusion Culling для объекта выполняется несколькими строками кода.

const box = BABYLON.MeshBuilder.CreateBox("box", {}, scene);

box.occlusionType = BABYLON.AbstractMesh.OCCLUSION_TYPE_OPTIMISTIC;
box.occlusionRetryCount = 10;
box.occlusionQueryAlgorithmType =
    BABYLON.AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE;

После этого Babylon.js автоматически будет:

  1. отправлять occlusion query на GPU;
  2. получать результат проверки;
  3. исключать объект из рендеринга при необходимости.

Использование Bounding Box

Occlusion query выполняется не для всей геометрии объекта, а для его ограничивающего объёма.

Babylon.js использует:

Axis Aligned Bounding Box (AABB)

Это упрощает вычисления и снижает нагрузку на GPU.

Преимущества:

  • быстрые проверки;
  • минимальный объём геометрии.

Недостаток:

  • bounding box может быть больше реальной формы объекта.

В результате:

объект может считаться видимым, даже если его геометрия скрыта.


Влияние порядка рендеринга

Occlusion Culling работает эффективно только при правильном порядке рендеринга.

Сначала должны отрисовываться:

  • большие статические объекты;
  • стены;
  • здания;
  • крупные элементы окружения.

После этого выполняются occlusion queries для более мелких объектов.

Babylon.js автоматически сортирует некоторые объекты, однако сложные сцены иногда требуют ручной настройки.


Ограничения Occlusion Culling

Несмотря на высокую эффективность, технология имеет ряд ограничений.

Задержка результата

Occlusion query выполняется асинхронно.

Это означает, что результат может быть получен на следующий кадр.

В некоторых ситуациях это приводит к:

  • кратковременному появлению скрытых объектов;
  • задержке появления объекта после выхода из-за препятствия.

Нагрузка на GPU

Большое количество occlusion queries может вызвать дополнительную нагрузку на GPU.

Поэтому не рекомендуется включать Occlusion Culling для:

  • мелких объектов;
  • частиц;
  • элементов UI;
  • динамических мелких мешей.

Ограничения WebGL

Некоторые браузеры или устройства могут не поддерживать occlusion queries.

Babylon.js автоматически отключает механизм при отсутствии поддержки расширения WebGL.


Оптимизация сцены с Occlusion Culling

Для максимальной эффективности необходимо правильно организовать сцену.

Использование крупных окклюдеров

Лучше всего работают:

  • здания
  • стены
  • скалы
  • большие объекты окружения

Такие элементы перекрывают большое количество геометрии.


Ограничение количества проверок

Occlusion queries должны применяться только к важным объектам:

  • сложным моделям;
  • большим мешам;
  • объектам с большим количеством полигонов.

Статическая геометрия

Статические сцены (например, архитектура) дают наилучший результат оптимизации.

Динамические объекты постоянно меняют положение, что снижает эффективность кэширования результатов.


Практический пример сцены

Рассмотрим упрощённую сцену с архитектурной структурой.

const wall = BABYLON.MeshBuilder.CreateBox("wall", {
    width: 20,
    height: 10,
    depth: 1
}, scene);

const hiddenBox = BABYLON.MeshBuilder.CreateBox("hidden", {}, scene);

hiddenBox.position.z = -10;

hiddenBox.occlusionType = BABYLON.AbstractMesh.OCCLUSION_TYPE_OPTIMISTIC;
hiddenBox.occlusionRetryCount = 3;

Если камера находится перед стеной, объект hiddenBox будет полностью скрыт.

Babylon.js выполнит occlusion query и исключит этот объект из рендеринга.


Комбинирование с другими техниками оптимизации

Occlusion Culling наиболее эффективен при совместном использовании с другими механизмами оптимизации.

Level of Detail (LOD)

LOD снижает сложность объектов на расстоянии.

Вместе с Occlusion Culling это даёт двойной эффект:

  • дальние объекты упрощаются;
  • скрытые объекты полностью исключаются.

Instances

Инстансинг позволяет рендерить множество копий одного объекта.

Occlusion Culling может использоваться для групп экземпляров, снижая нагрузку при массовых сценах.


Spatial Partitioning

Пространственные структуры, такие как:

  • Octree
  • BSP
  • Grid

уменьшают количество объектов, проверяемых системой окклюзии.

Babylon.js имеет встроенную поддержку Octree, что значительно повышает эффективность Occlusion Culling.


Отладка и диагностика

При разработке сложных сцен полезно контролировать работу Occlusion Culling.

Babylon.js предоставляет инструменты:

  • Inspector
  • статистику рендеринга
  • отображение bounding box

Inspector можно включить следующим образом:

scene.debugLayer.show();

В панели отображается:

  • количество отрисованных мешей;
  • активные объекты;
  • производительность рендеринга.

Это позволяет определить, насколько эффективно работает система окклюзии.


Типичные сценарии применения

Occlusion Culling особенно полезен в следующих типах сцен:

Городские сцены

Множество зданий перекрывают друг друга.


Интерьеры

Стены и комнаты скрывают большое количество объектов.


Коридоры и лабиринты

Камера видит только небольшую часть уровня.


Игры от первого лица

Большая часть геометрии находится вне прямой видимости.


Рекомендации по использованию

Практика разработки сцен в Babylon.js показывает несколько эффективных стратегий:

  • применять Occlusion Culling только к сложным объектам;
  • использовать CONSERVATIVE algorithm;
  • избегать включения для маленьких мешей;
  • комбинировать с Octree и LOD;
  • контролировать количество occlusion queries.

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