作者:起风了
Sessions: https://developer.apple.com/videos/play/wwdc2020/10612/
前言
本文是基于 WWDC2020 10612 What's new in RealityKit Session 整理而成,阅读本文需要有 ARKit、RealtyKit、AVPlayer 相关知识储备。这次 RealityKit 新特性增强了虚拟实体和现实世界的互动,让构建的场景更逼真、趣味。
新增功能
Video materials,这次 RealityKit 新功能允许将视屏用作 RealityKit 中的 Materials
借助 LiDAR 新增 Scene understanding,能将现实界带入到虚拟环境,因此可以实现虚拟内容与现实世界互动
改进了渲染调试,新增调试模拟组件,可以检查Entity渲染相关的各种属性
ARKit 4 扩展了其面部跟踪支持,可以在更多设备上使用
ARKit 4 还新增了 Location anchors,使用它可以将虚拟的 AR 实体放置在现实世界中的特定位置
Video materials
现在让我们深入研究这些新功能,并了解如何使用他们。
上图中可以看到,视屏材料被用给了图中虚拟物体使其身体和眼睛闪闪发光,Video Materials 可以使虚拟实体拥有随时间变化的纹理。我们从视屏中获取纹理可以实现很多事情,例如:使用它模拟看到的发光效果、也可以提供视屏说明等。
视屏材料还能播放空间音频(指声源的作用就像从特定位置发出),当将视屏应用到Entity时,该 Entity 将成为空间音频源。
既然知道了 Video Materials 是什么,我们该如何使用它们?
首先,我们需要加载视屏资源。RealityKit利用AVFoundation的AVPlayer的功能加载视屏源,一旦有了 AVPlayer 对象,就可以用它来创建 Video Material。
// 使用 AVFoundation 加载视屏 let asset = AVURLAsset(url: Bundle.main.url(forResource: "glow", withExtension: "mp4")!) let payerItem = AVPlayerItem(asset: asset)
接下来,我们可以用AVPlayer创建ViewMaterial对象,ViewMaterail和RealityKit其他的Material一样可以分配到Entity实体上。
let player = AVPlayer() bugEntity.materials = [VideoMaterial(player: player)]
通过上述过程我们可以给 Entity 实体分配 View Material 材料,现在我们可以使用 AVPlayer 播放器控制视屏。
player.replaceCurrentItem(with: playerItem) player.play()
我们可以使用 AVPlayerLooper 循环播放
也可以使用 AVQueuePlayer 顺序播放视屏队列
最后甚至可以使用 HTTP Live 流提供远程的媒体流。
想了解更多内容可以参考 WWDC 2016 中关于 AVFoundation 的 Session。
Scene understanding
Scene understanding 的主要目的是实现虚拟内容与现实世界互动,为了达成这样的目的我们需要将现实世界与虚拟内容融合。要做到这一点,需要从 ARVIew 开始:
AEView 有个 Environment 结构体属性,它可以设置与现实环境相关的配置。例如:背景图片、环境灯光以及空间音频,我们认为这些都是现实环境的一部分。这次新增了 Scene understanding 选项集,视频材料允许您将视频用作 RealityKit 中的材料。
Scene understanding 有四个选项集:
Occlusion(遮挡),真实世界的物体会遮挡虚拟世界的物体
Receives ligthing(接受光照),虚拟物体会在真实世界表面投射阴影
Physics(物理学),虚拟对象的行为可以与现实世界进行物理交互
Collision(碰撞),可以生成碰撞事件,并且可以对现实世界 Ray-cast
最后,设置了Receives lighting 会自动打开 Occlusion,Physics 会自动打开 Collision。
Occlusion
上图可以看出,左边没有遮挡效果,虚拟实体始可见;有遮挡效果的右边,虚拟实体隐藏在了树的后面,遮挡效果提高了增强现实的效果。
要想使用遮挡只需将 .occlusion 加到 Scene understanding 中。
arView.environment.sceneUnderstanding.options.insert(.occlusion)
Receives lighting
左边是没有 Receives lighting 的虚拟实体,由于缺少阴影,该虚拟物体看起来像漂浮的。
右边是带有 Receives lighting 的虚拟实体,它接受了光照在地板上投下了阴影,看上去像接地了。
arView.environment.sceneUnderstanding.options.insert(.receivesLighting)
由于投射的阴影是在真实世界的曲面,因此不需要将这些对象 Anchor 固定到水平面。也就是说虚拟世界的实体都会在现实世界投射阴影。需要特别注意的是,模仿的阴影是直射向下的光线。这意味着,在竖直的墙面上不会看到阴影。
Physics
以前在ARKit中,我们仅能使用平面或各种图元素来表示现实世界,这是不现实的,因为现实世界纷繁杂乱。现在基于 Scene understanding 可以产生更多的形态,例如:上图虚拟物体摔在地上分解后产生各种小碎片。要使用 Physics,只需要将 .pyhsics 加到 Scene understanding。
arView.environment.sceneUnderstanding.options.insert(.physics)
有一些细节需要我们了解:
ARView 中的现实世界物体是无限质量的静态物体,无法像现实生活中那样移动。
上述的小碎片不断更新,不要期望物体静止不动!尤其是在非平面表面上。
上图真实世界反映的网格仅限于用户已扫描的区域,例如:你没有扫描到地板,则场景中没有地板,结果物体将会掉落
上述网格是真实世界的近似值,不要期望网格有超清晰的边缘
Physics 不支持 Collaborative Sessions
Collision
需要使用碰撞,类似前面的三个选项,只需要将 .collision 加入 scene understanding。
arView.environment.sceneUnderstanding.options.insert(.collision)
collision有两方面需要处理:Ray-casting 和 Collision events。
Ray-casting
Ray-casting 即射线投射,我们可以用它来寻路、初始化对象放置、实现测试以及保持物体在网格上等。使用 Ray-casting 可以从实体身体向树投射射线,找到实体和树的接触点从而始终将实体保持在树上。虚拟物体和现实世界的实体碰撞检测,需要识别现实世界的实体,由此 RealityKit 引入了 Scene understanding entity。
SceneUnderstandingEntity 由各种 Component 组成,包括 Transform、Collision、Physics当然还有Scene Understanding。SceneUnderstandingComponent是SceneUnderstandingEntity唯一拥有的,它还能判断Entity是否是现实世界的实体。
`// 获取虚拟实体运动起始点
let bugOrigin = bug.position(relativeTo: nil)
let bugForward = bug.convent(direction: [0, 0, 1], relativeTo: nil)
// 使用起始点生成 ray-casting 并得到结果
let collisionResults = arView.scene.raycast(origin: bugOrigin, direction: bugForward)
// 获取真实世界的entitys
let fillteredResults = collisionResults.filter {$0.entity as? HasSceneUnderstanding}
// 列表按照由近到远排列,所以第一个 entity 最近
guard let closestCollisionPoint = filteredResults.first?.position else {
return
}
if length(bugorigin - closestCollisionPoint) < safeDistance {
//超出安全区域可以做些动作……
}
`
Collision events
Collison events 即碰撞事件,首先我们可以订阅所有实体间的碰撞事件,然后通过 HasSceneUnderstanding 特征判断是否有现实世界实体参与。
// 订阅所有碰撞事件 arView.scene.subscribe(to: CollisionEvents.Began.self) { event in // 获取SceneUnderstandingEntity guard let sceneUnderstandingEntity = (event.entityA as? HasSceneUnderstanding) ?? (event.entityB as? HasSceneUnderstanding) else { // 没有现实世界参与 return } let bugEntity = (sceneUnderstandingEntity == event.entityA) ?? event.entityB : event.entityA // 分解bugEntity }
Real world collision filtering
如果我们不希望和真实世界发生碰撞,可以使用过滤器,在filter中过滤掉.sceneUnderstanding.
// 仅仅和真实世界实体发生碰撞 entity.collision?.filter.mask = [.sceneUnderstanding] // 永远不会和真实世界发生碰撞 entity.collision?.filter.mask = CollisionGroup.all.subtraction(.sceneUnderstanding)
可视化网格
RealityKit新增可视化网格,它是真实世界的近似值,像我们展示了原始的,真实世界的边际。
网格的颜色随着与相机的距离变化而改变,超过5米所有内容均为白色。要启用网格可视化只需要将 .showSceneUnderstanding 加入到 ARView 的 debugOptions
arView.debugOptions.insert(.showSceneUnderstanding)
Rendering debugging
Rendering 是一个巨大的管道,其中包含许多 Component,它们有模型加载、材料设置、场景照明等等。为了帮助调试渲染相关的问题,RealityKit 增加了检查与渲染相关的 DebugModelComponent。
Entity 新增 debugComponent,它是 DebugModelComponent 类型,这让我们可以从大量的属性中可以选择单一属性调试,目前有16中可以选择。下面展示基本颜色(baseColor)使用
modelEntity.debugComponent = DebugModelComponent(sharderDebugModel: .baseColor)
最后需要注意的是,debugComponent 可视化仅仅用于自身不包括子 Entity,子 Entity 需要逐个添加。
ARKit 4
ARKit 4今年有很多更新,其中有两个与 RealityKit 相关的更新:Face Tracking 和 Location anchors
Face Tracking
Face Tracking 技术可以在不具有 TrueDepth 相机的设备上使用了,但是需要 A12 或更高处理器,例如最新的 iPhone SE。
Face Anchors 依然可以使用,不需要有额外工作量
Location anchors
Location Anchor 可以将现实世界的 Anchor 转化为设备的相对位置,这样可以将虚拟实体定位到现实世界
可以调用 ARGeoAnchor 实例化 AnchorEntity
ARKit为Location achors 引入了新的 ARGeo 跟踪配置,需要手动配置。
如果您想了解更多信息,建议您查看 ARKit 4 简介。
总结
关注我们
我们是「老司机技术周报」,每周会发布一份关于 iOS 的周报,也会定期分享一些和 iOS 相关的技术。欢迎关注。
关注有礼,关注【老司机技术周报】,回复「2020」,领取学习大礼包。
支持作者
这篇文章的内容来自于 《WWDC20 内参》。在这里给大家推荐一下这个专栏,专栏目前已经创作了 108 篇文章,只需要 29.9 元。点击【阅读原文】,就可以购买继续阅读 ~
WWDC 内参 系列是由老司机周报、知识小集合以及 SwiftGG 几个技术组织发起的。已经做了几年了,口碑一直不错。 主要是针对每年的 WWDC 的内容,做一次精选,并号召一群一线互联网的 iOS 开发者,结合自己的实际开发经验、苹果文档和视频内容做二次创作。
本文分享自微信公众号 - 老司机技术周报(LSJCoding)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。