代码下载
使用场景的深度数据在现实世界中布点,以呈现物理环境的形状。
概述
Depth Cloud 是一款应用程序,它使用 metal 根据来自设备的 LiDAR 扫描仪的深度信息,通过在物理环境中放置一组点来显示摄像头馈送。 对于会话的周期性深度读数 (depthMap) 中的每个距离样本,应用程序会在物理环境中的该位置放置一个虚拟点,最终结果类似于点云。 Depth Cloud 根据 ARKit 的相机图像 (capturedImage) 为云着色。
对于深度图中的每个条目——因此,对于云中的每个点——示例应用程序检查相机图像中的相应像素并将像素的颜色分配给点。 当用户直接查看点云时,应用程序的显示看起来几乎与相机馈送相同。 为了演示云的 3D 形状,示例应用程序不断旋转云以改变其相对于用户的视角。
WWDC20 会议 10611:探索 ARKit 4 引用了此示例应用程序的先前版本,它在云中累积点。 对于会话中显示的应用程序的原始版本,从下载根文件夹中的 Git 存储库克隆初始提交。
有关 ARKit 深度数据的实际应用,请参阅使用场景深度创建雾效果。
设置相机源
为了显示相机源,示例项目定义了一个 SwiftUI 场景,其主体包含一个窗口。 为了从窗口代码中抽象出视图代码,示例项目将其所有显示包装在一个名为 metalDepthView 的视图中。
因为 Depth Cloud 使用 metal 绘制图形,所以示例项目通过定义自定义 GPU 代码来显示相机源。 示例项目在其 ARReceiver.swift 文件中访问 ARKit 的相机源,并将其包装在自定义 ARData 对象中,以便最终传输到 GPU。
确保设备支持并开始会话
设备需要激光雷达扫描仪才能访问场景的深度。 在深度可视化视图的主体定义中,应用程序通过检查设备是否支持场景深度来防止运行不受支持的配置。
为了将数据采集与显示分开,示例应用程序将 ARKit 调用包装在其 ARProvider 类中。
AR 提供程序运行世界跟踪配置,并通过配置场景深度帧语义来请求有关场景深度的信息(请参阅 ARframeSemanticSceneDepth 和 ARframeSemanticSmoothedSceneDepth)。
访问场景的深度
为了响应配置的场景深度帧语义,框架在会话的 currentframe 上定义了 sceneDepth 和 smoothedSceneDepth 的帧的 depthMap 属性。
由于示例项目使用 metal 绘制图形,因此应用程序的 CPU 代码捆绑了其 GPU 代码显示体验所需的数据。 要使用点云对物理环境进行建模,该应用程序需要相机捕获数据来为每个点着色,并使用深度数据来定位它们。
示例项目在 GPU 代码中定位每个点,因此 CPU 端将深度数据打包在 metal 纹理中以供 GPU 使用。
示例项目为 GPU 代码中的每个点着色,因此 CPU 端将相机数据打包以在 GPU 上使用。
转换相机数据
在 pointCloudVertexShader 函数(参见示例项目的 shaders.metal 文件)中,示例项目为深度纹理中的每个值创建一个点,并通过对该深度纹理值在相机图像中的位置进行采样来确定该点的颜色。 每个顶点通过将其在一维顶点数组中的位置转换为深度纹理中的二维位置来计算其在相机图像中的 x 和 y 位置。
系统的相机捕获管道以 YUV 格式表示数据,示例项目使用亮度图 (colorYtexture) 和蓝色与红色色度图 (colorCbCrtexture) 对其进行建模。 GPU颜色格式为RGBA,需要样例工程转换相机数据才能显示。 着色器在顶点的 x、y 位置对亮度和色度纹理进行采样,并应用静态转换因子。
为简洁起见,示例项目演示了 YUV 到 RGB 的内联转换。 要查看将静态转换因子提取到 4 x 4 矩阵的示例,请参阅使用 metal 显示 AR 体验。
设置点云视图
为了使用点云显示相机源,该项目定义了一个 UIViewRepresentable 对象 metalPointCloud,其中包含一个显示 metal 内容的 MTKView。
该项目通过将点云视图嵌入到 metalDepthView 布局中,将其插入到视图层次结构中。
作为 UIView 的代表,metal 纹理视图定义了一个协调器,CoordinatorPointCloud。
点云协调器扩展了 MTKCoordinator,该示例在显示金属内容的其他视图中共享它。
作为 MTKViewDelegate,MTKCoordinator 处理在整个 metal 视图生命周期中发生的相关事件。
在 UIView 可表示的 makeUIView 实现中,示例项目将协调器分配为视图的委托。
在运行时,显示链接然后调用 metal 协调器的 drawInMTKView: 实现来发出 CPU 端渲染命令。
使用 GPU 代码显示点云
点云(英语:point cloud)是空间中的数据集,可以表示三维形状或对象,通常由三维扫描仪获取。
示例项目在 GPU 上绘制点云。 点云视图将其相应的 GPU 代码作为输入所需的几个纹理打包在一起。
类似地,点云视图将其相应的 GPU 代码作为输入所需的几个计算属性打包。
为了调用绘制点云的 GPU 函数,该示例定义了一个管道状态,该状态将其 pointCloudVertexShader 和 pointCloudFragmentShader 金属函数排队(请参阅项目的 shaders.metal 文件)。
在 GPU 上,点云顶点着色器决定了每个点在屏幕上的颜色和位置。 在函数签名中,顶点着色器接收 CPU 代码发送的输入纹理和属性。
该代码将点的世界位置基于其在相机馈送中的位置和深度。
该点的屏幕位置是其世界位置和参数投影矩阵的乘积。
vertex 函数将点的屏幕位置以及点的颜色作为转换后的 RGB 结果输出。
片段着色器在其函数签名中接收顶点函数输出。
在过滤任何离设备相机太近的点后,片段着色器通过返回每个顶点的颜色将剩余的点排队以供显示。
改变云的方向以传达深度
为了调整点云相对于用户的方向,示例应用程序相反地为相机的姿势设置了平移和旋转偏移。
示例项目在返回调整后的结果之前将相机位姿偏移应用于原始投影矩阵。
扩大深度缓冲区
为了对齐相关视觉效果(相机图像和置信度纹理)的大小,AR 提供者使用 MPS 双线性比例过滤器。
在 processLastARData 例程中,AR 提供程序为扩大深度缓冲区的计算通道创建额外的 metal 命令缓冲区。
AR 提供程序将输入深度数据转换为 RGB 格式,根据引导过滤器的要求。
在对双线性比例和引导过滤器进行编码后,AR 提供者设置放大的深度缓冲区。
显示深度置信度
该项目通过将深度可视化视图嵌入到项目的 metalViewSample.swift 文件中的 metalDepthView 布局中,将其插入到视图层次结构中。
深度可视化视图的内容由包含来自 AR 会话当前帧的深度数据的纹理组成。
深度纹理视图的协调器 CoordinatorDepth 分配一个填充纹理的着色器。
planeFragmentShaderDepth 着色器(请参阅 shaders.metal)根据需要将深度值转换为 RGB 以显示它们。
同样,该项目通过将置信度可视化视图嵌入到项目的 metalViewSample.swift 文件中的 metalDepthView 布局中,将其插入到视图层次结构中。
置信度可视化视图的内容由包含来自 AR 会话当前帧的置信度数据的纹理组成。
置信度纹理视图的协调器 CoordinatorConfidence 分配一个填充纹理的着色器。
planeFragmentShaderConfidence 着色器(请参阅 shaders.metal)根据需要将深度值转换为 RGB 以显示它们。