RealityKit 和 ARKit——当应用程序启动时,AR 项目在寻找什么?
RealityKit and ARKit – What is AR project looking for when the app starts?
如果您打开 Xcode,创建一个新的增强现实项目并 运行 该项目,您会更好地理解这个问题。
项目在设备上 运行ning 后,您将看到来自后置摄像头的图像,正在拍摄您的房间。
3 或 4 秒后,出现一个立方体。
我的问题是:
立方体出现之前应用程序在做什么?我的意思是,我想该应用程序正在寻找场景中的跟踪点,因此它可以锚定立方体,对吗?
如果这是真的,应用程序正在寻找哪些元素?
假设我对立方体出现的点不满意。是否有任何功能可以通过点击屏幕触发,以便跟踪可以在我点击屏幕的位置附近再次搜索新点?
我知道我的问题很笼统,所以请给我正确的方向。
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+ 多边形和高分辨率纹理(jpeg
或 png
尺寸为 1024x1024 被认为是正常的)。
此外,RealityKit 默认启用了几个 heavy
选项 – Depth channel Compositing
、Motion Blur
和 Ray-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))
如果您打开 Xcode,创建一个新的增强现实项目并 运行 该项目,您会更好地理解这个问题。
项目在设备上 运行ning 后,您将看到来自后置摄像头的图像,正在拍摄您的房间。
3 或 4 秒后,出现一个立方体。
我的问题是:
立方体出现之前应用程序在做什么?我的意思是,我想该应用程序正在寻找场景中的跟踪点,因此它可以锚定立方体,对吗?
如果这是真的,应用程序正在寻找哪些元素?
假设我对立方体出现的点不满意。是否有任何功能可以通过点击屏幕触发,以便跟踪可以在我点击屏幕的位置附近再次搜索新点?
我知道我的问题很笼统,所以请给我正确的方向。
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+ 多边形和高分辨率纹理(jpeg
或 png
尺寸为 1024x1024 被认为是正常的)。
此外,RealityKit 默认启用了几个 heavy
选项 – Depth channel Compositing
、Motion Blur
和 Ray-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))