tags: [vr-ar]
Реализация окклюзии виртуальных объектов реальными предметами в AR
Без окклюзии AR выглядит как наклейка поверх реальности. Виртуальный персонаж стоит за реальным стулом — но стул не перекрывает персонажа, и иллюзия рассыпается. Пользователь мгновенно считывает это как «наложение картинки», а не как присутствие объекта в пространстве.
AR Foundation 5.x предоставляет AROcclusionManager — компонент, который использует карту глубины с сенсора (LiDAR на iPhone Pro / iPad Pro, depth estimation на устройствах без LiDAR) для маскировки виртуальных объектов за реальными. Но «просто добавить компонент» не работает.
Где ломается окклюзия
На устройствах с LiDAR карта глубины (environmentDepthTexture) обновляется в реальном времени с частотой около 30 fps — это честный depth buffer реального мира. На Android и iPhone без LiDAR AR Foundation использует ML-оценку глубины через AROcclusionManager.requestedEnvironmentDepthMode = EnvironmentDepthMode.Best, что даёт значительно больше артефактов на краях объектов.
Главная проблема — разрыв между глубиной реального мира и Z-буфером Unity. Виртуальные объекты рендерятся в стандартном пайплайне с обычным depth testing, а «реальный мир» приходит как 2D-текстура. Нужно явно реализовывать окклюзию: рендерить в глубину реальные поверхности через DepthShader, записывать их в depth buffer до рендера виртуальных объектов.
Конкретно в URP это выглядит так: создаётся ScriptableRendererFeature с двумя RenderPass. Первый проход берёт environmentDepthTexture из AROcclusionManager, конвертирует её в depth buffer (учитывая разницу в near/far clip плейнах между AR-камерой и Unity-камерой) и записывает в _CameraDepthTexture. Второй проход — стандартный рендер сцены. Виртуальные объекты автоматически получают корректный depth test против реального мира.
Звучит просто, но есть нюанс: конвертация глубины. AR Foundation возвращает линейную глубину в метрах, Unity depth buffer — нелинейный (logarithmic или reversed-Z в зависимости от настроек). Неправильная конвертация даёт «мерцание» на границах окклюзии или полное отсутствие эффекта.
Мягкие края и алфа-смешение
Жёсткая окклюзия — объект либо виден, либо нет — выглядит грубо. На краях реальных объектов карта глубины всегда имеет неточности: размытие, артефакты ML-оценки. Виртуальный объект режет по этому нечёткому краю, и получается зубчатая граница.
Правильное решение — soft occlusion через размытие карты глубины перед depth testing. AROcclusionManager в AR Foundation 5.x поддерживает OcclusionPreferenceMode.PreferEnvironmentOcclusion и PreferSmoothOcclusion — второй режим применяет bilateral filter для сглаживания границ. Но в URP его нужно подключать вручную через кастомный рендер пасс; автоматически он работает только в Built-in RP.
На практике мы делаем так: в шейдере виртуального объекта добавляем стадию окклюзии с smoothstep по сравнению depth реального мира и depth объекта. Диапазон смешения — 2–5 см в мировых координатах. Это даёт плавный переход на краях без явных артефактов.
Кейс: персонаж за мебелью
Проект — AR-игра с мобильным AR-персонажем, который взаимодействует с реальной комнатой. Задача: персонаж должен «прятаться» за реальными предметами мебели.
Без LiDAR (основная аудитория — mid-range Android) пришлось использовать ML-depth estimation. Проблема: ML плохо работает на однородных поверхностях (белая стена, гладкий стол) — глубина там нестабильна, и персонаж «проваливался» в стол или выходил перед ним хаотично.
Решение — гибридный подход. Для крупных обнаруженных плоскостей (ARPlane) используется точная геометрия из ARPlaneManager (мы знаем их положение в пространстве), они рендерятся в depth buffer как 3D-меши. ML-depth используется только для объектов, которые не являются плоскостями — стулья, люди, предметы на столе. Это убрало 80% артефактов на типичных интерьерных сценах.
Сроки и процесс
Оценка начинается с аудита целевых устройств и текущего рендер-пайплайна. URP и HDRP требуют разных подходов. HDRP в мобильном AR практически не используется — слишком тяжёлый, но если проект для Magic Leap или HoloLens, там своя специфика.
| Сценарий | Сроки |
|---|---|
Базовая окклюзия через AROcclusionManager (URP) |
3–7 дней |
| Мягкая окклюзия с кастомным рендер пассом | 1–2 недели |
| Гибридный подход (плоскости + ML depth) | 2–4 недели |
| HoloLens / Magic Leap (отдельный пайплайн) | от 3 недель |
Стоимость — после анализа проекта и целевых платформ. Ключевые вопросы: какой RP, есть ли LiDAR в целевой аудитории, нужна ли поддержка Android ниже ARCore 1.24.





