Реализация AR-эффектов окружения (Environment Occlusion)
Environment occlusion — это когда реальные объекты правильно перекрывают виртуальные. Поставили AR-диван у стены, зашли за него — диван частично скрывается за вашим силуэтом. Без occlusion AR-объект всегда рисуется поверх всего — и иллюзия присутствия ломается немедленно. Технически это один из самых требовательных эффектов, потому что нужна информация о глубине реального мира в реальном времени.
Два принципиально разных пути к occlusion
LiDAR-путь (iPhone 12 Pro+, iPad Pro): ARWorldTrackingConfiguration.sceneReconstruction = .mesh строит dense mesh окружения. Этот mesh пишет значения в depth buffer. AR-объект за mesh'ем — перекрыт. Точность — до 1-2 см на дистанции до 5 метров. Реальное время без задержки.
ML-путь (любое ARKit/ARCore устройство): нейросеть предсказывает карту глубины из RGB-изображения (monocular depth estimation). ARKit ARDepthMap / ARCore Depth API (DepthPoint). Точность хуже (5-15 см), есть артефакты на краях объектов, лёгкая задержка 1-3 кадра.
Для production: если аудитория — iPhone Pro / iPad Pro, используем LiDAR. Для массового приложения — ML depth с LiDAR-ускорением там, где есть.
RealityKit: включение occlusion одной строкой
На устройствах с LiDAR и iOS 15+:
arView.environment.sceneUnderstanding.options = [
.occlusion, // реальные объекты перекрывают AR
.collision, // AR-объекты сталкиваются с реальной геометрией
.physics, // физика относительно реальных поверхностей
.receivesLighting // AR-объекты освещены как реальные
]
Это буквально всё, что нужно для базового occlusion в RealityKit. Под капотом — ARKit строит mesh окружения, RealityKit использует его как occluder.
Без LiDAR на том же API: ARView использует ARKit person segmentation (A12+) — только силуэт человека перекрывает AR-объекты. Стол, стул, стена — не перекрывают. Ограниченно, но лучше чем ничего.
Person Occlusion: отдельная задача
ARWorldTrackingConfiguration.frameSemantics = .personSegmentation — ARKit сегментирует человека на кадре и создаёт stencil mask. AR-объекты «за» человеком перекрываются его силуэтом. Работает на A12+ без LiDAR.
Качество маски — по краям тела небольшой ореол 2-5 пикселей. На тёмном фоне заметно, на естественном — приемлемо.
Для кастомного рендеринга: ARFrame.segmentationBuffer — CVPixelBuffer с классами пикселей (ARFrame.SegmentationClass.person). Используется в Metal шейдерах для кастомного compositing.
ARCore Depth API (Android)
На устройствах с ToF-сенсором (Samsung Galaxy S21 Ultra, LG V60) — hardware depth. На остальных — ML depth от ARCore Depth API (Raw Depth Image):
val frame = session.update()
if (session.isDepthModeSupported(Config.DepthMode.AUTOMATIC)) {
val depthImage = frame.acquireDepthImage16Bits()
// depth в мм, 16-bit unsigned short
// ARCore рекомендует использовать через OpenGL texture
}
ARCore предоставляет OcclusionShader через их sample — OpenGL фрагментный шейдер, который дискардирует фрагменты AR-объектов глубже реальной геометрии. Это основа для occlusion в Sceneform/кастомном рендерере.
Кастомный occlusion шейдер (Metal / OpenGL ES)
Для нестандартных требований (нужен blurred edge на границе occlusion, художественный стиль) — кастомный Metal шейдер:
fragment float4 occlusionFragment(
VertexOut in [[stage_in]],
texture2d<float> arDepthMap [[texture(0)]],
texture2d<float> vrObject [[texture(1)]]
) {
float2 uv = in.texCoord;
float realDepth = arDepthMap.sample(s, uv).r; // глубина реальной сцены
float vrDepth = in.depth; // глубина AR-объекта
if (vrDepth > realDepth + 0.01) {
discard_fragment(); // AR-объект за реальной геометрией
}
return vrObject.sample(s, uv);
}
Отступ 0.01 (1 см) предотвращает z-fighting на поверхностях, к которым вплотную «прислонён» AR-объект.
Soft Occlusion: размытые края
На LiDAR mesh краях перехода occlusion бывает «пиксельным» — depth resolution конечна. Soft occlusion через bilateral blur на маске глубины сглаживает переход. В Metal: custom kernel с depth-aware blur (размытие только в пределах depth threshold).
Это заметно только при внимательном взгляде, но для премиального AR-продукта — стоит реализовать.
Тени от виртуальных объектов на реальные поверхности
Бонус к occlusion: AR-диван отбрасывает тень на реальный пол. В RealityKit с sceneUnderstanding.receivesLighting — тени автоматически. В кастомном рендере: shadow map от AR-объекта, projected на real-world geometry из LiDAR mesh.
Без LiDAR: тень только на ARKit-detected planes (пол, стол). Пользователь видит «плоскую» тень, которая не следует рельефу реальной поверхности.
Сроки
LiDAR occlusion через RealityKit API — 2-3 дня интеграции. Person segmentation occlusion — 3-5 дней. ARCore Depth occlusion на Android — 1-2 недели (кастомный шейдер). Soft occlusion с кастомным Metal/GLSL shading — плюс 1-2 недели. Стоимость рассчитывается индивидуально.







