写点什么

AR 在百度小游戏中的探索与实践

  • 2019-11-28
  • 本文字数:7222 字

    阅读完需:约 24 分钟

AR在百度小游戏中的探索与实践

背景


这篇文章是我对这次 GMTC 的移动 AI 专场中分享的“AR 在百度小游戏中的探索实践”所做的记录整理,并对其中一小部分内容做了一点微调。


这次分享主要分为三块内容


1. 目前比较典型的 AR 应用的介绍,对现在应用的 AR 能力有一些了解


2.浏览器中的 AR 以及百度小游戏中 AR 的集成方案


3.通过一个 case 介绍怎么在百度小游戏上去开发一个 AR 的应用

AR应用的介绍


1. 六个 AR 案例

首先第一个非常传统的是基于 marker 追踪的 AR 效果。这种 AR 需要使用一张像 barcode 这样具有规定特征的图片作为 marker 生成特征数据,然后在运行的时候对输入的相机画面做匹配,寻找这个特征图片,进行实时的追踪并且生成三维变换矩阵应用到三维模型上达到现虚拟场景和显示场景融合的效果。像浏览器中的 AR.js 就是基于 Marker 追踪实现的 AR 能力。而它底层实际上是用的 ARtoolkit 的 JS 版本,这也是一个非常老牌的 AR 库了。



第二个是基于图片的追踪,跟刚才对 Marker 的追踪一样,也需要预先对图片生成特征数据,然后在运行时做匹配。不一样的是,基于图片的追踪可以使用任意的自然图片了(当然还是需要有一定的特征,不能使用纯色这样的图片),这样使得 AR 可以应用到更多的营销场景中,比如图中是追踪了马里奥游戏盒的封面图片,然后在上面展现了更多的游戏信息。



第三个愤怒小鸟的 AR 版。它使用了基于平面追踪的 AR,游戏中会检测相机输入的现实场景中有哪些是平面,然后把游戏场景放到这个平面上。这个技术的代表就是苹果的 ARKit 和 Google 的 ARCore 了。



第四个是前几年很火的 AR 游戏 Pokemon Go ,这个游戏是基于 LBS 的玩法,玩家需要跑到地图上投放了宠物的位置去寻找和捕获宠物



最后两个案例:


前一个是前段时间权力游戏第八季开播时在 Snapchat 上投放的 AR 营销,它会在用户打开相机后去识别画面中的地标建筑(地标建筑也需要预先生成特征数据),然后对画面做天空分割,在分割出来的区域播放一个天空盒的视频,画面中在飞的龙和乌云就是视频播放的。



后一个是典型的人脸 AR 应用,也是一个营销的场景。人脸的增强一般就是识别并追踪前置摄像头中的人脸画面,识别出人脸上五官的特征点,然后基于这些特征点实现像表情触发,人脸美妆和贴纸等效果。



###2. 浏览器中的 AR



刚刚介绍了六个 AR 的应用,这些应用都是会通过不同的手段去识别现实场景中自己需要的内容,然后根据识别到的内容实现相应的游戏或者应用逻辑。


所以对于一个 AR 应用来说,首先要做的事情是通过各种各样的技术手段去理解现实场景,比如通过陀螺仪等传感器去感知手机空间位置和朝向的改变。通过对输入的相机画面做一些传统的 CV 识别,或者现在更流行的卷积神经网络,去识别出画面中的人脸,平面等物体。通过 GPS 去知道自己在世界地图中的位置。然后在理解现实场景的基础上,再通过一些三维渲染的技术,去加入虚拟形象,虚拟场景,与相机画面做整合,实现增强现实的效果。AR 的效果好不好,主要就看对周围环境的理解是否到位,是否能够正确识别到平面,是否能够识别出遮挡等等。而这其中深度学习起到了非常重要的作用。


在浏览器中,现在已经有一些规范能够去提供刚才所说的 AR 需要的能力了,比如有 deviceorientationevent 和 devicemotionevent 两个事件去接受传感器的变化,有 WebRTC 规范去得到相机画面的输入。对于深度学习来说,TensorFlow 和百度的 Paddle 都已经有了可以在浏览器中运行的版本,可以通过这些深度学习库在浏览器上去对输入的相机图像做理解和推理。


但是以目前 JavaScript 的性能,尤其是在 AR 最依赖的手机端,去实现刚才演示的那些 AR 的效果还是很吃力。JavaScript 很难去做一些非常底层的硬件优化,也没法使用 SIMD,多线程这些常用的优化手段,尽管像 TensorFlow 和 Paddle 会使用 WebGL 去做一些卷积计算的 GPU 通用计算,但是整体的性能还是远远不够,很难达到实时。不过深度学习这一块也是有一些正在推进中更低 level 或者更专项的规范去更高效的做这些事,比如 WebGPU 和 WebNN。


除了这些,w3c 也有一个 immersive group 在制定针对 AR / VR 场景的规范 - WebXR。WebXR 之前其实是 WebVR,后来为了引入 AR 才重新把名字叫做了 WebXR,现在 WebXR 里也主要还是针对 VR 的场景,跟 AR 相关的比较少。


我们在百度小游戏中对于 AR 的集成就参考了 WebXR 的规范,也是希望后面在 WebXR 完善了 AR 的场景之后能够做到兼容。

百度小游戏中AR的集成


###1. 基于 ARCore 和 ARKit 的能力


百度小游戏作为一个容器,包含了一个 JS 引擎(安卓下是 V8,iOS 下是 JSCore)用于运行开发者写的 JS 游戏逻辑代码,同时提供了 WebGL 和 Canvas 2D 用于游戏渲染,以及文件系统,网络等能力用于加载游戏资源。接下来会大概介绍一下百度小游戏中对于 AR 的集成,包括基于 ARKit 和 ARCore 提供的平面 AR 的能力,以及基于百度的 DuMix AR 提供的人脸 AR 扩展。




这个演示的例子是前段时间用 THREE.js 写的一个百度小游戏的 AR case,这个例子演示了一个完整的 AR 应用的流程。在开始的普通界面就是一个常见的汽车展示的样子,可以旋转,缩放查看。在进入 AR 模式之后会调起摄像头,检测画面中的平面,检测到合适的平面后可以点击放置汽车模型,这个汽车模型会和真实场景融合在一起,用户可以走动查看车辆的各个细节。


通过这个 case 大概可以看到一些百度小游戏中基于 ARKit 和 ARCore 提供的能力,比如进入 AR 模式后 AR 会话的创建,相机在现实世界中位置的追踪,平面检测等等。接下来会具体介绍其中的六个主要能力。


1.1 World Tracking


世界追踪 World Tracking 是百度小游戏 AR 中一个非常基础的能力,它能够实时的追踪用户在现实世界中的位置,然后返回相机的 view matrix 。这个 view matrix 是三维渲染中的视图变换矩阵,能够直接被游戏引擎中的三维相机对象使用,从而实现把用户在现实世界中的位置映射到虚拟世界中的效果。


1.2 Point Cloud


ARKit 和 ARCore 每一帧都会对相机画面检测特征点,开发者能够拿到这些特征点点云的三维位置(x, y, z)数据然后绘制到相机画面上,能够给用户一个在实时检测的反馈。


1.3 Plane Tracking


ARKit 和 ARCore 会通过整个 AR 会话期间检测出来的特征点,去推测出空间中的平面,这个平面可以是水平的地面,桌面,也可以是垂直的墙面。这是非常核心的一个能力,开发者可以获取到检测到的平面中心点的变换矩阵以及平面的大小。


1.4 Hit Test


Hit Test 是三维渲染中的一个概念,一般是根据屏幕上的一个坐标得到一条射线,然后使用这个射线跟三维场景求交得到相交的交点坐标和表面法向量。对于 AR 来说,求交得到的就是平面上的交点或者说是特征点。开发者可以使用这个能力实现诸如点击放置三维模型的功能。


1.5 Anchor


在锚点(Anchor)上,ARKit 和 ARCore 的定义会有点区别,ARKit 所有追踪的东西都是锚点,比如人脸,平面等。ARCore 就要简单很多,锚点就是一个现实空间中的固定位置和朝向,但是它可以是绑定到像平面这样可追踪的物体上。Immersive web 也有讨论 WebXR 中该怎么定义这个锚点,现在并没有什么结论。我们是对 ARKit 和 ARCore 取了一个交集,锚点就是在现实空间中的一个固定位置和朝向,没有其它的用途。


游戏引擎中的场景节点的可以跟锚点绑定起来,每一帧锚点都会更新它最新的变换矩阵 poseMatrix,像三维模型这样的场景节点在应用了这个锚点之后,可以保证渲染的时候它看起来就是放在一个固定的位置上。就像下图演示的一样。



1.6 Light Estimate


最后一个是光照信息的获取,目前可以获取到环境光的强度和色调 RGB 值。开发者可以像下图一样根据获取到的环境光强度去调整渲染中的光照强度,保证在不同光照的场景下三维渲染都能跟真实场景更融合。



这是目前我们基于 ARKit 和 ARCore 提供的六个主要能力,后面也会逐渐暴露更多 ARKit 和 ARCore 的能力提供给开发者。通过这些能力可以去更好的融合三维的虚拟世界以及相机中的现实世界,能够让用户在使用 AR 游戏或者应用的时候有更沉浸式的体验。


2. 基于 DuMix AR 提供的人脸增强扩展

除了 ARkit 和 ARCore,我们也集成了我们自己的 AR SDK,去提供一些像人脸增强这样的扩展 AR 模式。同样的接下来会大概介绍一下这个人脸模式中提供的能力。


2.1 相机数据


对相机加后期滤镜是人脸应用中不可缺少的一个环节,因此我们通过 Video 对象提供给了开发者相机数据访问的能力。这个 Video 对象跟图片一样可以作为 WebGL 中纹理的数据源,然后在 Shader 中实现一些像下图中演示的故障艺术,DuoTone 以及磨皮美白这样的实时滤镜。



2.2 特征点识别


人脸五官特征点的识别是目前大部分人脸应用的基础,我们会把检测到的 95 个人脸特征点归一后的(x, y)坐标放到一个 Float32Array 中,开发者可以利用这些特征点去做像瘦脸,2D 贴纸这样的后期效果


2.3 人脸骨骼识别


在刚才特征点的基础上,算法还会计算出人脸的骨骼的变换矩阵,这个骨骼的变换会驱动相应的人脸三维模型,实现下图这样贴合人脸的模型动画




动图中绿色的点就是骨骼节点了,看起来可能跟特征点很像,但是它是三维空间而且跟白色的人脸模型网格绑定的。如果我们再给这个人脸模型加上纹理,就可以类似像上面右图这样的 3D 贴纸效果或者美妆效果。除此之外,也可以在骨骼节点上绑定一个像帽子,耳环这样的三维模型去实现虚拟头饰的佩戴。


2.4 表情系数


最后一个同样也是根据特征推算出来的,五官的表情系数。表情系数是一系列 0 到 1 的值,用来描述五官的特征。比如嘴巴完全闭合是 0,完全张开是 1。那识别出来半张嘴的可能是一个 0.5 的值,同样的像眼睛,眉毛都会有这样一个系数。这个表情系数可以用来做一些游戏逻辑的触发,也可以实现 Morph Animation。


大概介绍完了这两大块百度小游戏中提供的 AR 能力,我们再来简单看下现在小游戏的架构中是怎么集成和暴露这些 AR 能力的。



这个是现在小游戏集成 AR 的模块图,最底层是我们集成的各个 AR 算法,包括 ARKit,ARCore,还有基于 DuMix AR 的人脸算法模块。然后上面这层是小游戏的 Runtime,管理整个小游戏应用的 loop,每一帧去更新 AR 算法,拿到算法计算出来的数据,然后执行开发者写的 JS 逻辑,开发者会通过上层 v8 或者 JSCore Binding 到 JS 运行环境的接口去访问 AR 的数据,再把这些 AR 的数据提供给像 THREE.js 这样的游戏引擎,比如相机对象会使用 projectionMatrix 和 viewMatrix ,锚点的 poseMatrix 会更新到场景节点上。开发者的 JS 逻辑执行完后,再去渲染 Canvas 画布,和相机画面做混合然后绘制到屏幕上。

开发一个百度小游戏的AR应用


最后一部分会大概介绍一下怎么利用现在小游戏提供的 AR 能力去开发一个像刚才汽车展示那样的 AR demo。


首先是在编辑器中实现最基础的三维模型展示



刚才有提到小游戏 Runtime 提供了 JS 引擎,提供了 WebGL 的渲染能力,这些对于像 THREE.js 这样的游戏引擎来说已经足够用了,还有一些零碎的像注册事件这样的 DOM 操作可以通过一层 JavaScript 中封装的 DOM 适配层来解决。在这个基础上,我们就可以用 THREE.js 来愉快的开发小游戏的 3D 应用了。汽车的模型是 turbosquid 上下的,简单的处理了一下后转成了 glTF 格式,glTF 格式是 khronos 最近在推的一个 web 模型传输规范,特点是体积小,解析方便。Khronos 对这个格式的定位是图片中的 jpeg,视频中的 MP4 格式。THREE.js 有现成的模块可以直接加载展示 glTF 格式的模型。加载完之后就可以再加一些 JS 的逻辑去实现模型的旋转查看,车漆颜色的更换等效果。右图是在开发者工具中的预览效果。


接下来第二步是进入 AR 模式,在小游戏中启动 AR 模式是通过 swan.requestXRSession 这个接口。



整个接口的风格是跟小游戏其它接口风格保持一致的,调用 requestXRSession 后会异步的去创建 AR 的会话实例并且调起相机,创建成功后会进入 success 回调并且传入会话实例,如果失败(比如无相机权限)则会进入 fail 回调。调起成功后每帧可以通过 getFrame 方法获取帧对象,并且通过帧对象访问到相应的 AR 数据。


这个时候可以看到屏幕中的相机画面了,底下的 ARKit 和 ARCore 也会开始检测画面中的平面,我们可以通过 getTrackablePalnes 方法获取检测到的平面并且判断这个平面是否可放置。



图中代码大概演示了怎么去获取平面并且判断平面是否可以放置,在这过程中我们可以绘制相应的引导去提示用户该怎么做,比如还不能放置的时候让他们再多移动一下手机,或者找一个更明显的地面。如果可以放置了则提示点击放置。因为平面检测的过程往往需要几秒到十几秒,这个过程有一个友好的引导是非常有必要的。


在查找到平面后就是“放置”模型的步骤了,这个“放置”我加了引号是因为实际上我们做的事是根据上面 hitTest 得到的结果去创建一个锚点。然后每一帧使用锚点的提供的矩阵并且应用到模型的场景节点上,实现虚拟物体“固定”在现实世界中中某个位置的效果。在“放置”完后我们就能得到差不多这样的画面了



我们第一眼看到的时候可能还是会感觉,这个就只是把模型画面覆盖在相机画面上吧,无法看出来这个模型是被放置在桌面上的,整个车的光照效果也跟相机画面中的格格不入。接下来我们就会去通过一些渲染的优化措施去解决这两个问题。



首先是光照的优化,刚才我们只是用了一个简单的平行光源,整体光照效果非常单一。对此我们可以引入 HDR 的环境光贴图。环境光贴图它相当于是每个像素都是一个光源了,可以让整体的光照更加丰富,比如车漆表面也有这种反射的效果了,然后再配合基于物理的渲染,可以取实现金属和非金属材质的区分,材质粗糙度的模拟,以及这个例子中特殊的 Clear Coat 的车漆效果。


使用固定的环境光照贴图在很多时候可以欺骗过用户的眼睛了,但是固定的毕竟不能反映真实的光照场景,比如局部明暗信息,或者说从室外换到室内,用的还是同一张环境光贴图,就显得不太合适了,所以有时候还是会显得比较假。更优的方案就是实时的从相机视频流里计算出环境光贴图。ARKit 提供了 AREnvironmentProbeAnchor 去得到环境光贴图,ARCore 最新版本还没有类似的功能,但是刚刚 Google IO 上有介绍了他们新版本会加入(在分享完后整理这篇文章的时候 ARcore 刚好发布了 1.10 版本,支持了 HDR 的环境光贴图,平行光预测,以及球谐光照的系数)


HDR 的环境光贴图作为输入的光源,需要映射到 LDR 才不会在输出屏幕的时候导致过亮,这中间有一步叫做 Tone Mapping,做的事情就是从 HDR 线性或者非线性映射到 LDR 颜色空间。我们可以使用刚才提到过的 Light Estimate 的环境光系数来作为 Tone Mapping 的曝光系数,让整体渲染画面的曝光强度跟相机画面的曝光强度更接近。



然后是阴影的优化,阴影和遮挡是体现空间关系两个非常重要的因素,阴影可以用来体现光照,可以用来表现平面。PPT 下面图中加上阴影后可以看到汽车就像是被放在这个桌面上了。当然这个不只是渲染中才有的问题,在现实世界中如果阴影的位置跟人脑想像的不一样也会让人产生视觉错觉。


刚才的阴影是对理想光源的阴影,在现实世界中,更多的光照信息来自于各种其它物体或者大气中的漫反射,也就是间接光照。一些比较角落的区域就会因为接受到的简介光照比较少,就会比较暗。比如图中电脑和桌面接触的部分,同样的渲染的汽车的底盘下面也应该会暗很多。因此我们要在渲染中加入 接触阴影(Contact Shadow) 去模拟这种效果。


对于移动端来说,比较常见的方式是离线去烘焙出 AO 贴图,这种方式开销很低,而且对于静态场景来说效果不错,缺点就是没法针对使用到动态的场景中。


如果是动态的场景的话,可以使用实时的 SSAO 去模拟这种接触阴影,它是在屏幕空间中对像素周围的像素采样得到自己的遮挡信息,但是因为要实时所以不能有太多的采样,而且屏幕空间中也已经丢失了很多场景的几何信息,这些遮挡信息的确实往往会导致间接阴影的表现并不理想。刚好汽车底盘其实就是一个这样一个比较典型的 bad case。


在这个例子中用了一种更 trick 的方式去表现这种跟地面或者桌面的接触阴影。就是在汽车模型的横截面用黑色渲染了一帧,然后加上几层高斯模糊,作为平面上的接触阴影。这种实现非常廉价,而且效果整体还不错。当然这个只能针对现在这个场景,并不是所有场景都适用的。



在做完这些优化后可以看到整体渲染的效果跟真实场景已经比较接近了,车底盘下面的阴影跟后面其它相机画面中的车也比较一致。


当然还有不少可以优化的地方,比如刚才提到的从相机画面中提取出环境光贴图, 可以让车身的反射跟后面其它车的反射更加的接近。


总结


——


这次分享大概从 AR 应用示例的介绍,百度小游戏中 AR 的集成和能力介绍以及一个 AR 应用的开发三部分介绍了一下,我们最后再来总结下这其中的一些重点。


在集成 ARKit 和 ARCore 的时候,我们在小游戏 Runtime 中做了渲染和数据的统一管理,去统一了两者一些不同的概念,保证提供给开发者一个一致的接口,并且在接口设计上能够实现高效访问,更符合前端的开发习惯。


除了 ARKit 和 ARCore,我们也去扩展了像人脸这样的能力,后续也会继续加入肢体骨骼,手势,物体的识别和追踪功能。我们希望能够利用更多深度学习的能力去实现更强大的感知世界的能力从而实现更丰富的 AR 效果。


最后我们通过一个 case 去演示了如何在小游戏中开发一个可用的 AR demo。这过程中我们去优化了平面检测中的交互,加入了像基于物理的渲染,间接阴影这样渲染技术去保证渲染的场景和现实场景更融合。这些渲染效果其实 THREE.js 都有现成的模块可以用,这个 demo 也大概只花了一个周末的时间。所以我们希望是能够把现在强大的 Web 生态和百度小游戏结合起来,能够让开发者非常便捷的去开发高质量的 AR 游戏和 AR 应用。

参考资料

https://immersive-web.github.io/webxr/

更多推荐

百度 App 网络深度优化系列《一》DNS 优化


百度 App 网络深度优化系列《二》连接优化


百度 App Android H5 首屏优化实践


百度 App iOS 工程化实践:EasyBox 破冰之旅


本文转载自百度 App 技术。


原文链接:


https://mp.weixin.qq.com/s/z67t7_xFUDIVvQmGruG4zg


2019-11-28 08:002769

评论

发布
暂无评论
发现更多内容

手机运存与内存有什么区别?

InfoQ IT百科

有研究显示,现在年轻人越来越不愿意换手机了。下一代智能手机在硬件上出现哪些更新,才会让你有换机的冲动?

InfoQ IT百科

日志脱敏是什么意思?为什么要做日志脱敏?

行云管家

数据安全 日志脱敏

银行为什么要上堡垒机?选择哪家好?有案例吗?

行云管家

运维 网络安全 银行 堡垒机

Kafka生成消息时的3种分区策略

华为云开发者联盟

kafka 分区 Default Partitioner 分区策略 Partitioner

射频芯片在手机上起到什么作用?

InfoQ IT百科

购买不同品牌的手机,怎么对比硬件配置?

InfoQ IT百科

虎符交易所Hoo研究院|币海寻珠——四月上半月区块链投融事件Top20

区块链前沿News

区块链 投资 虎符研究院

OPLG:新一代云原生可观测最佳实践

阿里巴巴云原生

自动化测试的生命周期是什么?

禅道项目管理

自动化测试 生命周期

友好型公链Neo,助力开发者轻松掌握区块链智能合约

TinTinLand

区块链

手机摄像头芯片主要有哪些?

InfoQ IT百科

2019年华为鸿蒙加入手机系统阵营,如何看待鸿蒙这三年的发展?

InfoQ IT百科

前三个月免费试用!博睿数据告警平台OneAlert火热大促进行中

博睿数据

摆脱 AI 生产“小作坊”:如何基于 Kubernetes 构建云原生 AI 平台

阿里巴巴云原生

2021金三银四跳槽必备:阿里Java岗面试突击笔记终开源!,springmvc实战视频

爱好编程进阶

Java 面试 后端开发

星环科技平滑迁移方案加速国产化替代,助力大数据基础软件自主可控

星环科技

ActiveMQ消息存储持久化,华为java面试难度

爱好编程进阶

Java 面试 后端开发

netty系列之:netty中常用的xml编码解码器

程序那些事

Java Netty 程序那些事 4月月更

手机摄像头越多拍照效果越好吗?

InfoQ IT百科

手机刷新率越高越好吗?

InfoQ IT百科

CPU和GPU有什么区别?

InfoQ IT百科

从构建到治理,业内首本微服务治理技术白皮书正式发布(含免费下载链接)

阿里巴巴云原生

Android系统和iOS系统两大系统占据了手机操作系统98%的市场份额,国产手机操作系统还应该从哪些方面努力才能实现逆袭?

InfoQ IT百科

最近几年,OPPO 、小米等手机厂商都开始走自研芯片之路,这条路能跑通吗?

InfoQ IT百科

2020年java岗合集面试复盘,凭借这些文档掌握80%就去进阿里,大牛自我总结500页“Java成长笔记”

爱好编程进阶

Java 面试 后端开发

CRM系统改善客户体验的方法

低代码小观

CRM CRM系统 客户关系管理系统 客户体验 客户体验管理

如何看待现阶段国内手机操作系统的竞争格局?

InfoQ IT百科

【Zeekr_Tech】ROS/ROS 2介绍

Zeekr_Tech

操作系统 机器人

70道Java开发面试题及答案,2022最新大厂高频微服务面试总结

爱好编程进阶

Java 面试 后端开发

C语言的三子棋,用22天总结了一份完美的SQL学习笔记

爱好编程进阶

Java 面试 后端开发

AR在百度小游戏中的探索与实践_文化 & 方法_百度App技术_InfoQ精选文章