Реалізація 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 пристрій): нейромережа передбачає depth map з 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()
// глибина у мм, 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 тижні. Вартість розраховується індивідуально.







