В трёхмерной графике значительная часть геометрии сцены может быть полностью скрыта другими объектами. Несмотря на это, стандартный рендеринг всё равно отправляет такие объекты в графический конвейер, выполняя вычисления вершин, фрагментов и освещения. Это приводит к лишней нагрузке на GPU.
Occlusion Culling — это техника оптимизации, позволяющая исключать из рендеринга объекты, полностью перекрытые другими объектами сцены. Если объект не виден из текущей точки камеры, его отрисовка пропускается.
В библиотеке Babylon.js механизм Occlusion Culling встроен в систему Mesh и может использоваться без сторонних расширений. Проверка видимости происходит на уровне графического API с применением occlusion queries, поддерживаемых WebGL.
Основная цель технологии — уменьшение количества объектов, проходящих через стадию рендеринга, особенно в сложных сценах с большим количеством геометрии.
Перед применением Occlusion Culling необходимо понимать отличие этой техники от более базового механизма — Frustum Culling.
Frustum Culling проверяет, находится ли объект внутри пирамиды видимости камеры (view frustum).
Если объект полностью вне этой пирамиды, он не рендерится.
Особенности:
Пример: объект может находиться перед камерой, но быть полностью скрыт стеной. Frustum Culling всё равно сочтёт его видимым.
Occlusion Culling проверяет реальную видимость объекта, учитывая перекрытие другими объектами.
Особенности:
Если объект полностью скрыт другими объектами, он исключается из рендеринга.
Babylon.js использует аппаратные возможности WebGL:
EXT_occlusion_query_booleanANY_SAMPLES_PASSEDМеханизм работает следующим образом:
Проверка выполняется асинхронно, чтобы не блокировать GPU.
Каждый объект Mesh имеет ряд свойств для управления системой окклюзии.
Определяет стратегию обработки результата occlusion query.
Возможные значения:
BABYLON.AbstractMesh.OCCLUSION_TYPE_NONEBABYLON.AbstractMesh.OCCLUSION_TYPE_OPTIMISTICBABYLON.AbstractMesh.OCCLUSION_TYPE_STRICTПример:
mesh.occlusionType = BABYLON.AbstractMesh.OCCLUSION_TYPE_OPTIMISTIC;
Если результат запроса ещё не получен, объект временно считается видимым.
Плюсы:
Минусы:
Если результат запроса ещё не готов, объект считается скрытым.
Плюсы:
Минусы:
Определяет количество попыток повторной проверки видимости объекта.
mesh.occlusionRetryCount = 5;
Если объект остаётся скрытым, система повторит проверку указанное количество раз.
Это полезно для объектов, которые могут появиться после перемещения камеры.
Определяет алгоритм проверки.
mesh.occlusionQueryAlgorithmType = BABYLON.AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE;
Поддерживаются два варианта:
Используется точная проверка количества пикселей.
BABYLON.AbstractMesh.OCCLUSION_ALGORITHM_TYPE_ACCURATE
Плюсы:
Минусы:
Проверяет, прошёл ли хотя бы один пиксель.
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 автоматически будет:
Occlusion query выполняется не для всей геометрии объекта, а для его ограничивающего объёма.
Babylon.js использует:
Axis Aligned Bounding Box (AABB)
Это упрощает вычисления и снижает нагрузку на GPU.
Преимущества:
Недостаток:
В результате:
объект может считаться видимым, даже если его геометрия скрыта.
Occlusion Culling работает эффективно только при правильном порядке рендеринга.
Сначала должны отрисовываться:
После этого выполняются occlusion queries для более мелких объектов.
Babylon.js автоматически сортирует некоторые объекты, однако сложные сцены иногда требуют ручной настройки.
Несмотря на высокую эффективность, технология имеет ряд ограничений.
Occlusion query выполняется асинхронно.
Это означает, что результат может быть получен на следующий кадр.
В некоторых ситуациях это приводит к:
Большое количество occlusion queries может вызвать дополнительную нагрузку на GPU.
Поэтому не рекомендуется включать Occlusion Culling для:
Некоторые браузеры или устройства могут не поддерживать occlusion queries.
Babylon.js автоматически отключает механизм при отсутствии поддержки расширения WebGL.
Для максимальной эффективности необходимо правильно организовать сцену.
Лучше всего работают:
Такие элементы перекрывают большое количество геометрии.
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 наиболее эффективен при совместном использовании с другими механизмами оптимизации.
LOD снижает сложность объектов на расстоянии.
Вместе с Occlusion Culling это даёт двойной эффект:
Инстансинг позволяет рендерить множество копий одного объекта.
Occlusion Culling может использоваться для групп экземпляров, снижая нагрузку при массовых сценах.
Пространственные структуры, такие как:
уменьшают количество объектов, проверяемых системой окклюзии.
Babylon.js имеет встроенную поддержку Octree, что значительно повышает эффективность Occlusion Culling.
При разработке сложных сцен полезно контролировать работу Occlusion Culling.
Babylon.js предоставляет инструменты:
Inspector можно включить следующим образом:
scene.debugLayer.show();
В панели отображается:
Это позволяет определить, насколько эффективно работает система окклюзии.
Occlusion Culling особенно полезен в следующих типах сцен:
Городские сцены
Множество зданий перекрывают друг друга.
Интерьеры
Стены и комнаты скрывают большое количество объектов.
Коридоры и лабиринты
Камера видит только небольшую часть уровня.
Игры от первого лица
Большая часть геометрии находится вне прямой видимости.
Практика разработки сцен в Babylon.js показывает несколько эффективных стратегий:
При грамотной настройке сцены технология позволяет существенно снизить нагрузку на GPU и увеличить производительность сложных 3D-приложений, особенно в сценах с плотной архитектурной геометрией и большим количеством объектов.