本文做者:yanxin1563前端
本文做者:git
shenyigithub
這篇文章是我對此次GMTC的移動AI專場中分享的「AR在百度小遊戲中的探索實踐」所作的記錄整理,並對其中一小部份內容作了一點微調。web
此次分享主要分爲三塊內容算法
1. 目前比較典型的AR應用的介紹,對如今應用的AR能力有一些瞭解瀏覽器
2.瀏覽器中的 AR以及百度小遊戲中AR 的集成方案微信
3.經過一個 case 介紹怎麼在百度小遊戲上去開發一個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 應用,也是一個營銷的場景。人臉的加強通常就是識別並追蹤前置攝像頭中的人臉畫面,識別出人臉上五官的特徵點,而後基於這些特徵點實現像表情觸發,人臉美妝和貼紙等效果。
剛剛介紹了六個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的場景以後可以作到兼容。
百度小遊戲做爲一個容器,包含了一個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遊戲或者應用的時候有更沉浸式的體驗。
除了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 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技術」,便可關注微信官方帳號;