大多数浏览器和
Developer App 均支持流媒体播放。
-
让您的现实世界与增强现实完美融合
跟我们一起探讨如何使用物体捕捉和 RealityKit,将现实世界的物体融入到增强现实游戏当中。我们将介绍如何借助 Object Capture 框架捕捉细节丰富的物品,将它们添加到 Xcode 的 RealityKit 项目,应用风格化的着色器和动画,并将它们整合到 AR 体验。我们还将分享在使用 ARKit、RealityKit 和物体捕捉功能时的最佳实践。为能更好地理解此讲座,我们建议您先观看 WWDC21 的“深入了解 RealityKit 2”和“利用物体捕捉创建 3D 模型”。
资源
- Building an Immersive Experience with RealityKit
- Capturing photographs for RealityKit Object Capture
- Creating a Game with Reality Composer
- Creating a Photogrammetry Command-Line App
- RealityKit
- Taking Pictures for 3D Object Capture
- Using object capture assets in RealityKit
相关视频
WWDC22
WWDC21
-
下载
♪ 柔和乐器演奏的嘻哈音乐 ♪ ♪ Hao Tang:您好 我是 Hao 一名 Object Capture 团队的工程师 今天 我和我的同事 Risa 将向您演示如何 借助 Object Capture API 和 RealityKit 来创建现实世界物体的 3D 模型 并把模型放进 AR 里 事不宜迟 我们开始吧 我会先带您回顾 Object Capture Object Capture 是 去年在 macOS 上 作为 RealityKit API 推出的 然后我向您介绍一下 ARKit 里的相机功能的优化 优化后 您能够拍摄到 物体的高分辨率照片 还能够更好地 将 Object Capture 整合到您的 AR App 中 接着 我会过一遍 Object Capture 的操作指南 以便您能够 充分利用好这项技术 后面的环节会由 Risa 向您 展示用 RealityKit 里的 Object Capture 进行端到端的工作流程 并演示如何将现实世界的物体 带入 AR 下面我们先来快速回顾 一下 Object Capture Object Capture 是 一项计算机视觉技术 您能轻松将实体的图像 转换成细节满满的 3D 模型 首先您要给物体拍照 各个角度都要拍摄 用 iPhone、iPad 或数码单反相机拍都可以 然后 您把这些照片复制到 Mac 上 Mac 支持使用 Object Capture 搭配使用 Photogrammetry API RealityKit 能将您的照片 转换成 3D 模型 而且只要几分钟的时间 输出的模型会呈现几何形体 和各种材质贴图 质感、纹理也包括在内 上述内容都是自动输出到您的模型 关于 Object Capture API 的更多详情 我强烈建议您观看 去年提及 Object Capture 的 WWDC 讲座 许多开发者借助 Object Capture 开发了 优秀的 3D 捕捉 App Unity、Cinema4D、Qlone PolyCam、PhotoCatch 等 这只是冰山一角 除此之外 我们还有很好看的模型 也是用此 API 创建的 这些是由 Ethan Saadia 创建的部分模型 用的就是 PhotoCatch App 里的 Object Capture 还有来自 Shopify 的朋友 Mikko Haapoja 也用这个 API 生成了许多好看的 3D 模型 您用 Object Capture 输出的 3D 模型细节质量 对于电子商务是十分有益的 打个比方 这个 GOAT App 可以让您试穿各种鞋子 这些鞋的模型都由 Object Capture API 创建 这个 API 就是为了 捕捉最精细的细节而设计的 这个功能对您有很大帮助 能帮您抉择是否购买某产品 甚至可以精准地规划某物体 是否适合放在您的空间中 比如 Plant Story App 可让您预览 将各种逼真的 3D 植物模型 放在您的真实空间的情况 这些植物模型都是用 Object Capture 创建的 这能帮助您了解放置一个盆栽 需要空出多少空间 或者只是单纯地预览逼真又 精致的模型在您空间里的样子 说到真实度 您能找到这个视频里真正的植物吗? 没错 白色花盆那株是真的 放在桌子的左上角 我们很高兴能看到 自 2021 年推出以来 Object Capture API 惊人的广泛运用 接下来 我们来谈谈 ARKit 里的相机功能优化 优化将大大地提高 Object Capture 的还原质量 一次好的 Object Capture 体验 从全方面拍好物体的照片开始 为此 您可以随意选 一款高分辨率相机 比如 iPhone、iPad 数码单反相机或微单 如果您用的是 iPhone 或 iPad 上的相机 App 您可以拍摄具有景深和重力 信息的高质量照片 让 Object Capture API 自动还原物体现实世界 中的大小和方向 还有 如果您用的是 iPhone 或 iPad 您可以利用 ARKit 的跟踪功能 在模型之上覆盖 3D 指导 UI 获得涵盖各个角度的物体 还有一个值得注意的重要事项 是您拍摄的图像分辨率越高 Object Capture 产出的 3D 模型质量越高 为此 在今年的 ARKit 版本中 我们即将推出 全新的高分辨率背景照片 API 这个 API 可让您以原始 相机分辨率拍摄照片 即使在运行 ARSession 的情况下 它允许您在物体之上添加 3D UI 叠层的同时 充分利用设备上的摄像头传感器 在 iPhone 13 上 这意味着广角摄像头 上 1200 万像素的原始分辨率 此 API 是非侵入式的 它不会中断当前 ARSession 进行着的视频流 所以您的 App 能持续 为用户提供流畅的 AR 体验 此外 ARKit 让 EXIF 元数据可用在 照片中 这允许您的 App 读取有关白平衡、曝光 以及其它对后期处理 有用的设置等信息 ARKit 能让您的 App 随意运用这个新 API 您能很方便地查询支持 高分辨率帧捕捉的视频格式 只要用 ARWorldTrackingConfiguration 如果成功了 设置新的视频格式 并运行 ARSession 如果要拍摄高分辨率照片 只需调用 ARSession 新的 captureHighResolutionFrame API 功能 就会通过异步完成处理程序 返回您一张高分辨率照片 就是这么简单 我们也意识到可能有 您更喜欢手动控制相机设置的情况 例如自行设置对焦、曝光或白平衡 所以我们为您提供了一种便捷的方式 能直接访问底层的 AVCaptureDevice 和更改属性以进行细致的相机控制 如本代码示例所示 只需调用 configurableCaptureDeviceForPrimaryCamera 这在 ARWorldTrackingConfiguration 上 就能访问底层的 AVCaptureDevice 有关功能优化的更多详情 我强烈推荐您查看 今年 WWDC 的 “探索 ARKit 6”讲座 下面 我们来看看 出色的 Object Capture 实践指南 首先 我们需要选择一个物体 它要具有适合 Object Capture 使用的相应特征 合适的物体表面有足够的纹理 如果物体个别地方是无纹理或透明的 这些地方的细节可能无法很好地还原 合适的物体也应该没有眩光和反光点 如果物体没有哑光表面 您可以试着使用漫射照明 减少它的镜面反射 如果您想翻转物体 拍摄物体底部 请确保物体能保持刚性 也就是说 翻转物体不会导致变形 最后 合适的物体在某种程度上 有着精细的结构 但您需要使用 高分辨率相机拍摄特写照片 涵盖到物体的精细细节 下个重要的事情 就是设置理想的拍摄环境 您需要确保您的拍摄环境 具有良好、均匀和分散的照明条件 维持背景也很重要 还有请在物体周围留够空间 如果您的房间很暗 您可以使用有着充足光线的转桌 接下来 我们看一看 拍出物体优质照片的指南 优质的照片能让您从 Object Capture 上 获得优质的 3D 模型 作为例子 我将向您展示 我的同事 Maunesh 如何 用他的 iPhone 拍摄 一艘炫酷海盗船的图像 海盗船是我们亲爱的 ARKit 工程师 Christian Lipski 的作品 Maunesh 先把海盗船 放在一张空桌子的中心位置 这般重点突出 这艘船 在照片中清晰可见 他用双手稳稳地拿着他的 iPhone 随着他慢慢地绕着船转 他从不同的高度拍摄照片 他确保船在相机视角中心 占幅充足 这样他就能捕捉到尽可能多的细节 他还确保他始终保持 任意两张相邻照片的 很大一部分画面重复 他拍了很多照片之后 这次示范里拍了 80 张左右 他把船放倒 以便后续他能还原船的底部 他继续拍船处于放倒状态的照片 拍了 20 张左右 有一个注意事项 他是横向 拿着 iPhone 的 这是因为他在拍摄一个长物体 这种情况下 横向模式可以帮助他 捕捉物体尽可能多的细节 但是 如果他要捕捉一个高物体 他就会竖着拿 iPhone
照片准备环节就结束啦 准备过程的最后一步是复制这些照片 到 Mac 上并用 Object Capture API 处理它们 您可以从四种不同的细节级别中选择 四种级别适用于不同的用例 “Reduced”和“Medium” 细节级别适和 在网页和手机上使用 比如在 AR QuickLook 中查看 3D 内容 这两个细节级别的还原模型 有较少的三角面和材质通道 从而占的内存更少 “Full”和“Raw”细节级别 适用于高端交互式用例 比如用在电脑游戏或 后期制作工作流程中 这两个级别的模型 含有最多的几何细节 能让您灵活地选择硬化 和非硬化材料 但这俩个等级要更多的内存来还原 根据您的用例选择 正确的输出级别很重要 我们给海盗船选择 了“Medium”细节级别 在 M1 Mac 上处理 只需要几分钟 输出的 3D 模型看起来非常棒 因此我们用海盗船模型做了个动画 这是海盗船在波澜壮阔 的大海上航行的样子 这就是 Object Capture 的能力! 啊呵! 下面有请 Risa 引领您 了解使用 RealityKit 中的 Object Capture 端到端的工作流程 Risa Yoneyama:谢谢 Hao 现在我们已经了解了 Object Capture API 我很高兴能带您了解 运用 RealityKit 把现实物体带入 AR 的端到端的开发者工作流程 我们将通过示例工作流程 详细介绍每一步 所以我们直接看演示吧 我的同事 Zach 偶尔做做木工 他最近做了六个超大的木质棋子 每一种一个棋子 看着这些棋子 我受到启发来创建一个 交互式 AR 国际象棋游戏 原先 您需要一个 3D 建模器 和材料专家来给现实世界的物体 创建高质量的 3D 模型 如今 有了 Object Capture API 我们可以直接捕捉这些棋子 并把它们带入增强现实 我们从捕捉“车”棋子开始 我的同事 Bryan 将 使用这个专业的设置 因为我们记住了在上个环节中 介绍的最佳操作方法 这个示例中 Bryan 将车放在转桌上 借助专业照明以免最终输出时 有明显的阴影 您也可以用 iPhone 摄像头搭配转桌 iPhone 为您提供输出 USDZ 中的自动规模估计和重力矢量信息 详情请查看 2021 年的 Object Capture 讲座 当然 如果您没有像 Bryan 这样的专业装备 您也可以 只用您的 iOS 设备 围着您的物体走动来捕捉图像 现在我们有了车的许多照片 我要把照片转到 Mac 上 我会用 2021 年推出的 PhotogrammetrySession API 来处理这些照片 根据最佳操作指南 我将使用“Reduced” 细节级别来还原 因为我们想要 AR App 运行良好 API 的最终输出会是 USDZ 文件类型的模型 这是我刚还原的车棋子 的最终输出 为了节省各位的时间 我已经 提前拍摄了其他五个棋子 您可能在想 棋子只有一种配色方案 要怎样制作国际象棋游戏 我们来复制这六个棋子 并把它们拉到 Reality Converter 中 我转换了原来纹理的颜色 并把这个新的纹理换在复制的一套上 这样 我们就有浅色 和深色版本的棋子了 每个玩家一个 然后在导出菜单里 打开压缩纹理选项 导出模型 这能减少纹理 占用的内存
既然我们有了全套棋子 现在就能把模型 引入 Xcode 项目 我用 RealityKit 创建了一个棋盘 用减小原始立方体 y 轴的方式 并交替设置黑色和白色 这是我还原的所有 棋子摆在棋盘上的样子 这已经很激动人心了 看着实际物体在 App 里 不过我们还是要添加一些功能 让其成为真正的互动游戏 在演示的这一环节中 我想展示几种不同的现有技术 这样我们可以向您提供不同示例 让您选择您想结合的技术 来完成您预想的输出 因为我们将讨论 RealityKit 中的高阶话题里的实际用例 我建议您观看 2021 年的 RealityKit 讲座 如果您还不熟悉相关 API 在我们初次启动 App 之前 我想先添加一个启动动画 我想制作的一个动画 是棋盘格 从略高于其 最终位置的地方慢慢落下 同时 棋子也跟着做一样的移动 为了在代码中呈现这种效果 只需要两个步骤 第一步 沿 y 轴向上 移动我们的两个实体 同时匀称地缩小棋子 第二步也是最后一步 为两个实体制作 回到原来变形的动画 这两个步骤的代码非常简单 我会先对棋盘格进行迭代 至于每个实体 我将保存棋盘格的当前变换 因为这将是它降落的最终位置 然后 我在 y 轴上把每个 方块向上移动 10 厘米 然后我们可以利用移动功能 将其动画化回我们的原始变形 我也碰巧知道这个边框 USDZ 它勾勒出了棋盘格 而且有内置动画 我们可以用 playAnimation API 同时开始动画 我为棋子添加了完全相同的动画 但也会在移动时调整比例 然后就有了 简单的启动动画 只需几行代码 然而 我们没有移动棋子的功能 实际上并不能下国际象棋 我们来制作这个功能 在移动棋子之前 我们首先要能选择棋子 我已经添加了 UITapGestureRecognizer 到我的 ARView 里 当用户轻点指定位置时 我们将定义一条从 相机原点开始的射线 并通过那个二维点 然后我们可以将该射线 投射到 3D 场景中 看看我们是否击中了任何实体 我已将我的棋子碰撞组指定为掩码 因为我知道我只是想在我的场景中 变得可以选择棋子 请注意光线投射功能 将忽略所有没有 CollisionComponent 的实体 如果我们找到了一个棋子 最终可以选择它了 现在我们知道了选择哪一个棋子 我想添加一个效果 使得棋子看起来像是在发光 我们可用自定义材料来实现这一目标 具体来说 就是表面着色器 表面着色器允许您通过 Metal 计算或指定材料参数 然后由 RealityKit 的 片段着色器调用 一次一个像素 我们可以编写一个表面着色器 它看起来像 Metal 中的这种火焰效果 然后用这个表面着色器 应用自定义材料到我们的长方体上 让着色器改变实体的外观 让我们编写一些代码来 达到我们想要的效果 我已经在项目中添加了噪点纹理 用在这个表面着色器中 我们将对纹理进行两次采样 一次为整体造型效果 还有一次为细节 然后我们获取 RGB 值 并重新映射它以得到 我们想要的的外观 然后 有了我们刚刚 提取并处理后的值 我们将计算样本点的不透明度 通过比较其 y 位置与图像值 为了给效果些许动感 我们将用时间函数 移动纹理的 y 轴 此外 我们还将使用每个样本点 的面向角度 这与相机的查看方向一致 来淡化两侧的效果 这将柔化边缘并隐藏 底层模型的常规性质 最后 我们将用表面参数函数 设置我们刚刚计算得出 的颜色和不透明度 这就是 应用了选定着色器的棋子外观 它们看起来确实像是内部在发光 现在 如果我们把 三个分开的移动动画结合起来 最后看起来就是这样的效果 实现了移动棋子的功能 我们也就能捕获对手的棋子 跟表面着色器差不多 几何修改器 也能使自定义材料来实现 几何修改器是非常强大的工具 因为您可以更改顶点数据 例如位置、法线、纹理坐标等 通过 RealityKit 的顶点 着色器 每个顶点都会对应 调用这些 Metal 每一个函数 这些修改纯粹是暂时的 并且不影响实际实体 的顶点信息 我想我们可以 添加一个有趣的几何修改器 用在棋子被捕获时把它们压扁 我的棋子上有 captureProgress 这个属性来表示 从 0 到 1 的捕获动画进度 由于捕获是用户发起的操作 我们需要以某种方式告知几何修改器 什么时候开始这个动画 好消息是您能做到这点 只要在 customMaterial 上设置自定义属性 这允许在中央处理器和 图形处理器之间共享数据 我们将在这里特意使用自定义值属性 并把动画进度传递给几何修改器 要从 Metal 端提取动画进度 我们可以用 uniforms 里的 custom_parameter 由于我想垂直缩放棋子 看起来像是它被另一个棋子压扁一样 我们将刻度轴设置为 y 方向 为了给动画增加一点复杂性 我们还将更改 x 轴上的几何图形 制造波浪效果 顶点的偏移量可以使用 set_model_position_ offset 函数 这是我们几何修改器的最终产出 您能看到它在倒塌之前放大了一点 同时沿 x 轴被垂直拉伸 我作为一个国际象棋新手 认为添加提示您选的棋子能放的方格 这一功能可能会有所帮助 能帮助我熟悉游戏 由于棋盘格都是有自己 Model Component 的独立实体 我可以用表面着色器 对潜在的可移动方块 应用脉冲效果 以将这些 方块跟其他的区分开来 接下来 我将添加一个名为 bloom 的后期处理效果 再次突出效果 同样 我们在这里使用自定义参数 我们在表面着色器中使用了发光效果 在这个演示中 我们从中央 处理器端传入一个布尔变量 到 Metal 表面着色器 如果这个方格是个可行的选择 我想通过更改颜色来添加脉冲效果 我们将在此处特地将 脉冲添加到发射颜色 最后 我会给整个视图添加绽放效果 “绽放”是一种 后期处理效果 可产生 来自明亮区域边界的光羽 我们可以利用 ARView 上的渲染回调属性达到这个效果 我们用内置在 Metal 的执行着色器函数 来编写绽放效果 接下来 我们只要设置 renderCallbacks.postProcess 闭包作为我们刚刚定义的发光函数 当我们对格子脉冲时 我们是脉冲到白色 而且还会用绽放效果 进一步强调 配合表面着色器和绽放效果 能清楚地看到我们 能把棋子移动到哪里 最后 让我们把所有的功能整合起来 来看现实生活中的棋子 在 AR App 里活灵活现 我们可以看看所有添加的功能 在我们的环境里的效果 为了给您提供便利 我们已把 Capture Chess 示例项目 链接添加到讲座资源中 请下载并 在您的环境里试玩 就是这么简单 从拍摄到还原大型棋子 然后放进我们的增强现实 App 我们今天在本次讲座 中介绍了很多内容 所以我们来总结一下关键点 我们先是回顾了 Object Capture API 这是在 2021 年发布的 然后我们谈到了在 ARKit 中一个新的 API 这个 API 可以在运行 ARSession 期间 按需以初始机相机分辨率拍摄照片 为了助您充分利用 Object Capture 技术 我们列出了在拍摄您的物体时 适合还原的物体类型、 获得高质量 图像的理想环境、 以及建议遵循的流程 在这个讲座的后半部分 我们过了一遍端到端 开发者工作流程示例 我们拍摄了大型棋子的照片 并把图像用作 PhotogrammetrySession API 的输入 然后创建它们的 3D 模型 接着 我们将模型导入 Reality Converter 替换一些纹理 最后 我们慢慢建立起国际象棋游戏 并在 AR 里看到棋子的移动 这就是我们今天讲座的全部内容 非常感谢您的收看 啊呵! ♪
-
-
6:20 - HighRes capturing
if let hiResCaptureVideoFormat = ARWorldTrackingConfiguration.recommendedVideoFormatForHighResolutionFrameCapturing { // Assign the video format that supports hi-res capturing. config.videoFormat = hiResCaptureVideoFormat } // Run the session. session.run(config) session.captureHighResolutionFrame { (frame, error) in if let frame = frame { // save frame.capturedImage // … } }
-
17:00 - Chessboard animation
// Board Animation class Chessboard: Entity { func playAnimation() { checkers .forEach { entity in let currentTransform = entity.transform // Move checker square 10cm up entity.transform.translation += SIMD3<Float>(0, 0.1, 0) entity.move(to: currentTransform, relativeTo: entity.parent, duration: BoardGame.startupAnimationDuration) } // Play built-in animation for board border border.availableAnimations.forEach { border.playAnimation($0) } } }
-
18:00 - select chess piece
// Select chess piece class ChessViewport: ARView { @objc func handleTap(sender: UITapGestureRecognizer) { guard let ray = ray(through: sender.location(in: self)) else { return } // No piece is selected yet, we want to select one guard let raycastResult = scene.raycast(origin: ray.origin, direction: ray.direction, length: 5, query: .nearest, mask: .piece).first, let piece = raycastResult.entity.parentChessPiece else { return } boardGame.select(piece) gameManager.selectedPiece = piece } }
-
21:16 - capture geometry modifier
// Capture Geometry Modifier class ChessPiece: Entity, HasChessPiece { var capturedProgress: Float get { (pieceEntity?.model?.materials.first as? CustomMaterial)?.custom.value[0] ?? 0 } set { pieceEntity?.modifyMaterials { material in guard var customMaterial = material as? CustomMaterial else { return material } customMaterial.custom.value = SIMD4<Float>(newValue, 0, 0, 0) return customMaterial } } } }
-
23:00 - highlight potential moves using bloom
// Checker animation to show potential moves void checkerSurface(realitykit::surface_parameters params, float amplitude, bool isBlack = false) { // ... bool isPossibleMove = params.uniforms().custom_parameter()[0]; if (isPossibleMove) { const float a = amplitude * sin(params.uniforms().time() * M_PI_F) + amplitude; params.surface().set_emissive_color(half3(a)); if (isBlack) { params.surface().set_base_color(half3(a)); } } }
-
23:20 - Import MetalPerformanceShaders
import MetalPerformanceShaders class ChessViewport: ARView { init(gameManager: GameManager) { /// ... renderCallbacks.postProcess = postEffectBloom } func postEffectBloom(context: ARView.PostProcessContext) { let brightness = MPSImageThresholdToZero(device: context.device, thresholdValue: 0.85, linearGrayColorTransform: nil) brightness.encode(commandBuffer: context.commandBuffer, sourceTexture: context.sourceColorTexture, destinationTexture: bloomTexture!) /// ... } }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。