RealityKit 和 ARKit——当应用程序启动时,AR 项目在寻找什么?

RealityKit and ARKit – What is AR project looking for when the app starts?

如果您打开 Xcode,创建一个新的增强现实项目并 运行 该项目,您会更好地理解这个问题。

项目在设备上 运行ning 后,您将看到来自后置摄像头的图像,正在拍摄您的房间。

3 或 4 秒后,出现一个立方体。

我的问题是:

  1. 立方体出现之前应用程序在做什么?我的意思是,我想该应用程序正在寻找场景中的跟踪点,因此它可以锚定立方体,对吗?

  2. 如果这是真的,应用程序正在寻找哪些元素?

  3. 假设我对立方体出现的点不满意。是否有任何功能可以通过点击屏幕触发,以便跟踪可以在我点击屏幕的位置附近再次搜索新点?

我知道我的问题很笼统,所以请给我正确的方向。

ARKit 和 RealityKit 阶段

启动 AR 应用时,ARKit 和 RealityKit 分为三个阶段:

  • 跟踪
  • 场景理解
  • 渲染

每个阶段都可能会大大增加放置模型所需的时间(+1...+4 秒,具体取决于设备)。让我们谈谈每个阶段。

跟踪

这是您的增强现实应用的初始状态。这里 iPhone 以 60 fps 的速度混合来自 RGB 后置摄像头的视觉数据和以 1000 fps 的速度转换来自 IMU 传感器(加速度计、陀螺仪和指南针)的数据。自动生成的 特征点 帮助 ARKit 和 RealityKit 跟踪周围环境并构建跟踪地图(无论是世界跟踪还是面部跟踪)。在光线充足的环境中,特征点会在现实世界对象和纹理的高收缩边缘上自发生成。如果您已经有一个以前保存的世界地图,它会减少将模型放置到场景中的时间。此外,您还可以使用 ARCoachingOverlayView 获取有用的视觉说明,在会话初始化和恢复期间为您提供指导。

场景理解

第二阶段可以包括水平和垂直平面检测、光线投射(或命中测试)和光估计。如果您激活了平面检测功能,则需要一些时间来检测具有相应 (或 AnchorEntity(.plane))的平面,该平面必须连接虚拟模型 - 在您的情况下为立方体。还有一个 高级场景理解 允许您使用 场景重建 功能。您可以在带有 LiDAR 扫描仪的设备中使用场景重建,它为您提供了改进的深度通道,用于在场景和人物遮挡中合成元素。您始终可以启用 Image/Object 检测功能,但您必须考虑到它是基于机器学习算法构建的,可以增加模型在场景中的放置时间。

渲染

最后一个阶段用于渲染场景中的虚拟几何体。场景可以包含带有着色器和纹理的模型、变换或资产动画、动态和声音。金属着色器的周围 HDR 反射由神经模块计算。 ARKit 无法渲染 AR 场景。对于 3d 渲染,您必须使用 RealityKit、SceneKit 或 Metal 等框架。这些框架有自己的渲染引擎。

默认情况下,在 RealityKit 中有需要额外计算能力的高质量渲染效果,例如运动模糊或光线追踪阴影。考虑一下.

提示

要显着减少在 AR 场景中放置对象的时间,请使用以纳秒级速度工作的 LiDAR 扫描仪。如果你的小工具没有激光雷达,那么只跟踪周围光照条件好的环境,所有真实世界的物体都清晰可辨,上面的纹理丰富,没有重复的图案。此外,尽量不要在项目中使用 超过 10K+ 多边形和高分辨率纹理(jpegpng 尺寸为 1024x1024 被认为是正常的)。

此外,RealityKit 默认启用了几个 heavy 选项 – Depth channel CompositingMotion BlurRay-traced Contact Shadows(在 A11 上和更早的地方有投影阴影)。如果您不需要所有这些功能,只需禁用它们即可。之后你的应用程序会快得多。


实用解法一

(禁用阴影、运动模糊、深度补偿等)

使用以下属性禁用处理器密集型效果:

override func viewDidLoad() {
    super.viewDidLoad()
    
    arView.renderOptions = [.disableDepthOfField,
                            .disableHDR,
                            .disableMotionBlur,
                            .disableFaceOcclusions,
                            .disablePersonOcclusion,
                            .disableGroundingShadows]
    
    let boxAnchor = try! Experience.loadBox()
    arView.scene.anchors.append(boxAnchor)
}


实用解法二

(阴影、深度补偿等默认启用)

当您在 RealityKit 中使用以下代码时:

override func viewDidLoad() {
    super.viewDidLoad()

    let boxAnchor = try! Experience.loadBox()
    arView.scene.anchors.append(boxAnchor)
}

您将获得包含水平面检测 属性 和 AnchorEntity 的 Reality Composer 预配置场景,设置如下:

AnchorEntity(.plane(.horizontal,
                classification: .any,
                 minimumBounds: [0.25, 0.25])

将跟踪和场景理解与模型加载和渲染分开

您遇到的问题是您的应用程序启动时发生的时间滞后。同时开始世界跟踪(第一阶段),然后应用程序尝试同时检测水平面(第二阶段),然后渲染立方体的金属着色器(第三阶段)。要消除这种时间延迟,请使用这种非常简单的方法(当应用程序启动时,您需要跟踪一个房间,然后点击屏幕以加载模型):

override func viewDidLoad() {
    super.viewDidLoad()
    
    let tap = UITapGestureRecognizer(target: self,
                                     action: #selector(self.tapped))
    arView.addGestureRecognizer(tap) 
}

@objc func tapped(_ sender: UITapGestureRecognizer) {

    let boxAnchor = try! Experience.loadBox()
    arView.scene.anchors.append(boxAnchor)
}

这样可以减少 CPU 和 GPU 的同时负载。所以您的多维数据集加载速度更快。

P.S.

此外,作为替代方案,您可以使用 loadModelAsync(named:in:) 类型方法,该方法允许您从包中的文件异步加载模型实体:

static func loadModelAsync(named name: String, 
                            in bundle: Bundle?) -> LoadRequest<ModelEntity>

在默认情况下 Experience.rcproject 多维数据集有一个 AnchoringComponent with a horizontal plane。所以基本上立方体不会显示,直到 ARSession 在您的场景中找到任何水平面(例如地板或 table)。一旦发现立方体就会出现

如果您想在捕获点击事件时创建和锚定并将其设置为目标,则可以执行 raycast。使用光线投射的结果,您可以获取 worldTransform 并将立方体的 AnchoringComponent 设置为该变换:

像这样:
boxAnchor.anchoring = AnchoringComponent(.world(transform: raycastResult.worldTransform))