Реалізація AR-масок та фільтрів для обличчя
Маски та фільтри — найпоширеніший сценарій face AR. Snapchat, Instagram Reels, TikTok привчили користувачів до певної якості. Якщо маска "пливе" при повороті голови або не реагує на вираз обличчя — користувач видаляє додаток. Технічно задача добре вирішується ARKit/RealityKit, але є нюанси з окклюзією, анімацією та записом відео.
Типи масок та їхня технічна реалізація
Геометрична маска — 3D-меш, натягнутий поверх обличчя та слідуючий за його деформаціями. Найреалістичніший варіант. У RealityKit: ModelEntity з skinned mesh, суглоби якого прив'язані до ARKit blendShapes:
// Face Anchor як корінь
let faceAnchor = AnchorEntity(.face)
// Завантажуємо USDZ з morph targets, що відповідають ARKit blendShapes
let maskEntity = try! ModelEntity.load(named: "zombie_face.usdz")
faceAnchor.addChild(maskEntity)
arView.scene.addAnchor(faceAnchor)
// У update loop — застосовуємо blendShapes до mask morph targets
func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
guard let faceAnchor = anchors.first as? ARFaceAnchor else { return }
// BlendShape mapping: ARKit jawOpen → mask jaw morph target
}
Плоский стикер/оверлей — 2D-зображення або відео, прив'язане до face anchor. Простіше у реалізації, менше деформацій. Підходить для рамок, "капелюхів", накладних вус.
Particle effects — частинки, прив'язані до точок обличчя (іскри з очей, дим з рота при jawOpen > 0.3). У RealityKit — Entity з кастомною particle system через Reality Composer Pro.
Face Occluder: маска перекриває реальні об'єкти
Головна технічна тонкість — віртуальні елементи маски (роги, корона, окуляри) мають бути перекриті реальним обличчям де це фізично правильно. Корона йде за голову — затилок перекриває її. Окуляри "сідають" на ніс — ніс поверх дужок.
У ARKit/RealityKit — occluder mesh: копія face geometry з .occlusion матеріалом. Цей меш невидимий для користувача, але записує глибину у depth buffer. Елементи "за" обличчям корректно перекриваються:
// Occluder entity — невидима копія обличчя
var occluderMaterial = OcclusionMaterial()
let occluderEntity = ModelEntity(
mesh: .init(arFaceGeometry: faceAnchor.geometry),
materials: [occluderMaterial]
)
faceAnchor.addChild(occluderEntity)
Без occluder роги торчать крізь голову з будь-якого кута — виглядає дешево.
Анімація за виразом обличчя
52 blendShapes ARKit → mapping до morph targets 3D-маски. Стандартний сценарій: зомбі-маска відкриває рот при jawOpen, щурить очі при eyeBlinkLeft/Right. Меш маски повинен мати відповідні morph targets з тими ж іменами або через маппінг-таблицю.
Reality Composer Pro дозволяє настроїти BlendShapeWeightsMapping прямо у USDZ без коду. Для скомплексованих анімацій — кастомний update у ARSessionDelegate:
// Передаємо blendShapes у shader parameter маски
maskEntity.model?.materials[0].setParameter(
name: "jawOpen",
value: .float(faceAnchor.blendShapes[.jawOpen]?.floatValue ?? 0)
)
Запис відео з AR-маскою
RPScreenRecorder (ReplayKit) — запис усього екрана включаючи AR-вью. Просто, але низька якість (записує те, що на екрані, включаючи UI-елементи). Для чистого запису AR-камери — ARView.session + кастомний CVPixelBuffer рендер через Metal:
// Composite: camera frame + AR overlay → CVPixelBuffer
// → AVAssetWriter → .mp4
Складніше, але дає чистий запис без UI-оверлею та з можливістю вибору розрізнення.
Lens Studio / Spark AR як альтернатива
Якщо ціль — вірусний фільтр для Snap/Instagram/TikTok, а не власний додаток: Lens Studio (Snap) та Meta Spark (Instagram) надають середовища розробки ефектів без написання нативного коду. Ефекти публікуються на платформі та доступні користувачам у нативних додатках.
Для кастомного мобільного додатку з власною камерою — лише нативна реалізація або Banuba Face AR SDK.
Сроки
Базова маска (статичний 3D-меш, без анімації blendShapes) — 4–6 днів. Анімована маска з face occluder та 3–5 blendShape реакціями — 2–3 тижні. Запис відео + галерея масок з cloud-загрузкою — ще 2–3 тижні. Вартість розраховується індивідуально.







