更新日期:2023年3月6日
新的深度 API
由于新的高质量 ZDepth 通道,可以在每秒 60 帧的速度下渲染,因此您可以通过 ARKit 3.5 / 6.0 中的新的深度 API 来提高 People Occlusion
和 Object Occlusion
功能的质量。但是,要获取它,您需要一台带有 LiDAR 扫描仪的 iPhone 或 iPad。在 ARKit 3.0 中,除非使用 Metal 或 MetalKit(因此不容易),否则无法改善 People Occlusion
功能。
提示:请注意,RealityKit 和 AR QuickLook 框架也支持 People Occlusion
。
当您使用人物遮挡功能时,为什么会出现此问题?
这是由于深度数据的本质所致。我们都知道,3D场景的渲染最终图像可以包含5个数字合成主要通道 - 红色
、绿色
、蓝色
、Alpha
和ZDepth
。
![enter image description here](https://istack.dev59.com/kpaPO.webp)
当然,还有其他有用的渲染通道(也称为AOVs)可以用于合成:
法线
、
运动向量
、
点位置
、
UVs
、
视差
等等。但在本文中,我们只关注两个主要的渲染集合-
RGBA
和
ZDepth
。
在ARKit 3.0中,ZDepth通道有三个严重的缺点
问题1. Z深度的别名和反走样
在任何高端软件(如Nuke、Fusion、Maya或Houdini)中渲染Z深度通道,默认情况下会产生锯齿状边缘或所谓的别名边缘。游戏引擎也不例外-SceneKit、RealityKit、Unity、Unreal或Stingray也存在这个问题。
当然,您可以说在渲染之前我们必须打开一个叫做反走样
的功能。是的,它对几乎所有通道都有效,但对于Z深度来说却不是这样。Z深度的问题是-每个前景对象(特别是透明的对象)的边缘像素如果进行了反走样
,就会“过渡”到背景对象中。换句话说,FG和BG的像素在FG对象的边缘处混合。
坦白地说,目前在专业合成行业中,只有一种有效的解决深度问题的方法 - Nuke合成师使用
Deep channels而不是
ZDepth
。但是没有一个游戏引擎支持它,因为
Deep
通道太大了。因此,深度通道合成既不适用于游戏引擎,也不适用于ARKit / RealityKit。唉!
![enter image description here](https://istack.dev59.com/liW3f.webp)
问题2. ZDepth的分辨率
普通的ZDepth
通道必须以32位
渲染,即使RGB
和Alpha
通道都只有8位
。深度数据的32位文件对CPU和GPU来说是一个沉重的负担。ARKit经常在视口中合并几个图层。例如,将真实世界的前景角色与虚拟模型和真实世界的背景角色合成。即使这些图层在视口分辨率而不是真实屏幕分辨率下合成,您是否认为这对您的设备来说太过于繁重?然而,以16位
或8位
渲染ZDepth
通道会压缩您真实场景的深度,降低合成的质量。
为了减轻CPU和GPU的负担并节省电池寿命,苹果工程师决定在捕获阶段使用缩小的ZDepth图像,然后将渲染的ZDepth图像放大到视口分辨率,并使用Alpha通道(即分割)对其进行
模板,然后使用
Dilate合成操作修复ZDepth通道的边缘。因此,这导致我们看到您图片中的这些令人讨厌的伪影(一种“痕迹”)。
![enter image description here](https://istack.dev59.com/v1sbg.webp)
![enter image description here](https://istack.dev59.com/YYypl.webp)
请查看《将人们带入AR》的演示幻灯片pdf这里。
问题三. ZDepth的帧率
第三个问题源于FPS。ARKit和RealityKit以60 fps
的速度运行。缩小ZDepth图像分辨率并不能减少处理量。因此,ARKit 3.0工程师们的下一个逻辑步骤是-将ZDepth的帧率降低到15 fps
。然而,最新版本的ARKit和RealityKit以60 fps渲染ZDepth通道,这极大地提高了人物遮挡和物体遮挡的质量。但在ARKit 3.0中,这会导致一些暴露的伪影(一种ZDepth通道的“丢帧”效应,导致“拖尾”效果)。
当您使用此类型属性时,无法更改合成图像的质量:
static var personSegmentationWithDepth: ARConfiguration.FrameSemantics { get }
因为它是一个可获取的属性,并且在ARKit 3.0中没有ZDepth质量的设置。
当然,如果你想提高ARKit 3.0中ZDepth通道的帧率,你应该实现数字合成中发现的“帧插值技术”(其中插入的帧是计算机生成的)。
![enter image description here](https://istack.dev59.com/i0UJF.webp)
但是这个帧插值技术需要大量的CPU计算,因为我们需要每秒生成45个额外的32位ZDepth帧(45个插值+15个真实=每秒60帧)。
我相信有人可以使用Metal改进ARKit 3.0中的ZDepth合成功能,但这对开发者来说是一个真正的挑战。请查看People Occlusion in Custom Renderers
的示例代码。
ARKit 6.0和LiDAR扫描仪支持
在ARKit 3.5...6.0中,支持使用LiDAR(光探测与测距
扫描仪)。 LiDAR扫描仪提高了People Occlusion功能的质量,因为ZDepth通道的质量更高,即使您在跟踪周围环境时没有实际移动。 LiDAR系统还可以帮助您映射墙壁、天花板、地板和家具,以快速获取用于动态交互的真实世界表面的虚拟网格,或者仅仅是定位它们上面的3D对象(甚至是部分遮挡的虚拟对象)。拥有LiDAR的设备可以实现无与伦比的准确性,检索真实世界表面的位置。通过考虑网格,射线投射可以与非平面表面或没有任何特征的表面相交,例如白色墙壁或几乎没有光照的墙壁。
要激活sceneReconstruction
选项,请使用以下代码:
let arView = ARView(frame: .zero)
arView.automaticallyConfigureSession = false
let config = ARWorldTrackingConfiguration()
config.sceneReconstruction = .meshWithClassification
arView.debugOptions.insert([.showSceneUnderstanding, .showAnchorGeometry])
arView.environment.sceneUnderstanding.options.insert([.occlusion,
.collision,
.physics])
arView.session.run(config)
![enter image description here](https://istack.dev59.com/Ve0AY.webp)
但在您的代码中使用sceneReconstruction
实例属性之前,您需要检查设备是否具有LiDAR扫描仪。您可以在AppDelegate.swift
文件中执行此操作:
import ARKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
guard ARWorldTrackingConfiguration.supportsSceneReconstruction(.meshWithClassification)
else {
fatalError("Scene reconstruction requires a device with a LiDAR Scanner.")
}
return true
}
}
RealityKit 2.0
使用带有LiDAR的iPhone Pro或iPad Pro上的RealityKit 2.0应用程序时,您有几个遮挡选项-相同的选项在ARKit 6.0中可用-改进的People Occlusion
,Object Occlusion
(例如家具或墙壁)和Face Occlusion
。 要在RealityKit 2.0中打开遮挡,请使用以下代码:
arView.environment.sceneUnderstanding.options.insert(.occlusion)