Если коротко:

Occlusion culling в VR исключает из отрисовки renderers, скрытые стенами и другими непрозрачными объектами. Оно чаще помогает в комнатах, коридорах и сценах с крупными статичными перегородками, но может быть бесполезно на открытом уровне или стоить дороже сэкономленных draw calls. В Unity статическую видимость нужно запечь и проверить через Visualization; в Unreal Engine доступны precomputed visibility и runtime queries. Эффект подтверждают только A/B-профилированием на целевой гарнитуре.

Occlusion culling VR-сцены убирает renderers, которые находятся внутри поля зрения camera, но закрыты другой геометрией. Метод дополняет frustum culling: frustum отсекает всё вне view, а occlusion — объекты за стеной, перекрытием или крупным непрозрачным Actor. Экономия появляется лишь тогда, когда стоимость пропущенной отрисовки выше стоимости расчёта visibility и хранения data.

Это не Depth API occlusion в mixed reality, где реальная поверхность закрывает виртуальный объект. Здесь речь о virtual objects, отправляемых в rendering pipeline.

Когда occlusion culling полезен

Хорошие кандидаты — здания с отдельными комнатами, коридоры, многоэтажные интерьеры, промышленные цеха с массивными стенами и закрытые уровни. Camera обычно видит небольшой фрагмент всего мира, а opaque occluders стабильно скрывают целые группы meshes.

Польза сомнительна на открытой площадке, за стеклянными перегородками или при обзоре всей геометрии. Если за стеной один дешёвый объект, visibility query может не окупиться. Слишком крупные combined meshes тоже мешают: renderer считается видимым, когда его bounds частично нужны.

Occlusion culling не заменяет LOD, batching, instancing и distance culling. Эти методы решают разные задачи и обычно работают последовательно: по расстоянию, по frustum, по предвычисленной видимости, затем через динамические queries. Не следует включать механизм с ожиданием автоматического прироста FPS — узким местом могут быть shaders, fill rate, physics, scripts или уже видимая геометрия.

Bake и runtime: в чём разница

Предвычисленный вариант делит доступное пространство camera на cells и заранее сохраняет, какие static objects видны из каждой области. Bake тратит время в Editor и создаёт asset видимости; runtime читает его из памяти. Это уменьшает часть вычислений кадра, но добавляет размер data и требует повторного bake после изменений геометрии.

Runtime occlusion использует текущий depth buffer, software rasterization либо hardware queries. Он способен учитывать движущиеся occludees и актуальную scene, но создаёт CPU/GPU overhead и иногда получает результат с задержкой. Unreal Engine, например, читает результат hardware query на следующем кадре, из-за чего при быстром повороте camera возможен краткий pop-in.

В VR риск заметнее: изображение строится для двух глаз, голова быстро меняет view, а объект, скрытый для одного глаза у края преграды, может быть виден второму. Engine должен использовать stereo-aware culling. В Unity флаг CullingOptions.Stereo означает совместный culling обоих глаз; в Unreal Round Robin Occlusion чередует запросы для глаз по кадрам, экономя queries ценой дополнительной задержки visibility.

Настройка occlusion culling в Unity 6

Unity 6000.0 использует baked occlusion data для static geometry. Последовательность настройки:

  1. Пометьте крупные непрозрачные стены и перекрытия как Occluder Static. Они должны иметь Terrain или Mesh Renderer и не двигаться во время игры.
  2. Пометьте неподвижные объекты за ними как Occludee Static. Small props и transparent renderers могут быть occludees, но прозрачный объект не должен выступать occluder.
  3. На XR Camera включите Occlusion Culling.
  4. Откройте Window → Rendering → Occlusion Culling. При необходимости ограничьте возможные позиции camera через Occlusion Areas.
  5. На вкладке Bake задайте параметры, выполните bake и сохраните scene вместе со ссылкой на OcclusionCullingData.asset.
  6. На вкладке Visualization пройдите доступные точки и проверьте, какие renderers считаются visible и occluded.

Smallest Occluder задаёт минимальный размер геометрии, которая может закрывать другие objects. Слишком маленькое значение увеличивает детализацию data, bake time и размер asset. Smallest Hole описывает минимальный просвет, через который должна смотреть camera: завышенное значение способно скрыть объект, реально видимый через дверь или окно. Backface Threshold помогает сократить data, но агрессивное значение повышает риск ошибок.

Начинайте с крупных стен и консервативных параметров. Если visible object ошибочно исчезает, Unity рекомендует уменьшить Smallest Hole, вернуть Backface Threshold к 100 или снять Occluder Static с проблемной геометрии.

Dynamic GameObjects в Unity

Dynamic GameObject нельзя запечь как occluder. Он может быть occludee во время runtime, если у Renderer включена Dynamic Occlusion: тогда его скрывает статичный occluder. Опция включена по умолчанию. Её отключают для объектов, которые должны рисоваться за стеной, например контур цели, либо когда конкретный renderer заведомо не должен участвовать в расчёте.

Движущаяся дверь показывает типичное ограничение bake. Если её запечь закрытой как occluder, после открытия visibility data не узнает о новом проходе. Такую дверь лучше не использовать как static occluder; видимость соседнего помещения должна оставаться консервативной. Occlusion Portal применим к проёмам с известными состояниями, но его переключение нужно привязать к фактическому состоянию двери и протестировать со всех сторон.

Occlusion и visibility в Unreal Engine 5.8

Unreal по умолчанию сочетает view frustum и hardware occlusion queries. Actor проверяется по bounds; opaque и masked geometry может участвовать в dynamic occlusion. Стоимость растёт с количеством queries, поэтому сотни мелких Actors иногда выгоднее объединить логически, использовать HLOD или сначала убрать по distance.

Для мобильной и преимущественно статичной scene Epic предлагает Precomputed Visibility Volumes. Volume размещают только там, где может находиться игрок; cells генерируются над shadow-casting geometry во время lighting build и хранят видимость non-movable Actors. Метод подходит небольшим и средним уровням с ограниченным перемещением, обменивая rendering-thread time на runtime memory и build time.

Порядок проверки в Unreal:

  1. В Rendering → Culling убедитесь, что Occlusion Culling включён.
  2. Для static уровня добавьте Precomputed Visibility Volume и покройте им пространство движения HMD, включая высоту головы сидящего и стоящего пользователя.
  3. В World Settings включите Precomputed Visibility и соберите lighting/visibility data.
  4. В viewport используйте game view, затем проверяйте packaged или Standalone build.
  5. Командой stat initviews сравните Occluded Primitives, Occlusion Queries, View Visibility и Occlusion Cull; stat memory покажет память precomputed visibility.

Visibility Aggressiveness увеличивает число скрываемых Actors, но может вызвать popping. Малые cells точнее, однако требуют больше памяти и времени на распаковку. Override Volume подходит для известных ошибок: важный Actor можно принудительно оставить visible, не повышая агрессивность всей системы.

Round Robin Occlusion (vr.RoundRobinOcclusion=1) предназначен для stereo rendering и чередует eyes. Epic прямо указывает компромисс: целый набор queries экономится, но visibility получает ещё кадр задержки и может ошибаться на периферии. Включать его следует после A/B-теста конкретной сцены, а не как универсальный VR preset.

Как проверить реальную пользу

Соберите две одинаковые версии: control с текущими настройками и candidate с новым culling. Пройдите один и тот же маршрут с одинаковой скоростью, направлением взгляда, качеством и частотой дисплея. Измеряйте на целевой гарнитуре, потому что Editor, Link и desktop GPU меняют стоимость queries, driver overhead и thermal behavior.

Одного FPS недостаточно. Нужны CPU frame time, GPU frame time, rendering-thread time, draw calls, triangles, число processed/visible/occluded primitives и память visibility data. В Unity сопоставьте Profiler, Frame Debugger и Occlusion Visualization; порядок измерения описан в руководстве по профилированию VR в Unity. В Unreal используйте InitViews, GPU stats и захват Unreal Insights по методике профилирования VR.

Результат полезен, если время кадра стабильно уменьшается в репрезентативных точках; рост счётчика occluded objects сам по себе ничего не доказывает. Если draw calls снизились, но GPU frame остался прежним, ограничение находится в другом месте. Если rendering thread стал тяжелее, queries или обработка подробных bounds съели экономию.

Типичные ошибки

  • Пропадание у края стены. Проверьте bounds, Smallest Hole/cell size и оба глаза при движении головы.
  • Объект не cullится. Он может быть частью крупного renderer, иметь раздутые bounds или не попадать в baked area.
  • После изменения уровня ничего не поменялось. Static geometry требует нового bake и сохранения data asset.
  • Dynamic actor скрывает комнату. В Unity движущийся object не может быть baked occluder; проектируйте видимость консервативно.
  • Transparent surface считается стеной. Прозрачные материалы обычно оставляют occludees, а роль occluder дают непрозрачной геометрии.
  • Рост памяти на мобильной гарнитуре. Укрупните cells/Smallest Occluder, ограничьте volume доступной областью и повторите профиль.

Occlusion culling стоит оставлять, когда оно подтверждённо сокращает время кадра без stereo-артефактов и заметного роста памяти. Для одной сцены это может быть baked visibility, для другой — runtime queries, а для открытого уровня лучший результат дадут distance culling и LOD без дополнительного occlusion pass.

Проверка по шагам

Настройка occlusion culling в Unity 6

Выполнено 0 из 6

0 из 6
Поделиться:TelegramВКонтакте

Источники

  1. Unity 6 — Occlusion Culling
  2. Unity 6 — Occlusion Culling window
  3. Epic — Visibility and Occlusion Culling
  4. Meta — Best practices for Quest and PCVR