ARkit

ARkit

Introducing ARKit

iOS 11引入ARKit份帐,這是 個(gè)全新的框架讽挟,允許開發(fā)者輕松地為iPhone和iPad創(chuàng)建 與倫比

的增強(qiáng)現(xiàn)實(shí)體驗(yàn)碳胳。通過(guò)將虛擬對(duì)象和虛擬信息同 戶周圍的環(huán)境相互融合,ARKit使得應(yīng) 跳出

屏幕的限制豺鼻,讓它們能夠以全新的 式與現(xiàn)實(shí)世界進(jìn) 交互超燃。

基礎(chǔ)技術(shù)視覺(jué)慣性 程計(jì)

ARKit使 視覺(jué)慣性 程計(jì)(Visual Inertial Odometry, VIO)來(lái)精準(zhǔn)追蹤周圍的世界。VIO將攝像

頭的傳感器數(shù)據(jù)同Core Motion數(shù)據(jù)進(jìn) 融合拘领。這兩種數(shù)據(jù)允許設(shè)備能夠 精度地感測(cè)設(shè)備在房

間內(nèi)的動(dòng)作意乓, 且 需額外校準(zhǔn)。

場(chǎng)景識(shí)別與光亮估

借助ARKit约素,iPhone和iPad可以分析相機(jī)界 中所呈現(xiàn)的場(chǎng)景届良,并在房間當(dāng)中尋找 平 。ARKit不僅可以檢測(cè)諸如桌 和地板之類的 平 圣猎,還可以在較 特征點(diǎn)(feature points)上追蹤

和放置對(duì)象邓深。ARKit還? 攝像頭傳感器來(lái)估算場(chǎng)景當(dāng)中的可 光總亮度,并為虛擬對(duì)象添加符

合環(huán)境照明 的光 量没。

性能硬件與渲染優(yōu)化

ARKit運(yùn) 在Apple A9和A10處 器上梨熙。這些處 器能夠?yàn)锳RKit提供突破性的性能,從 可

以實(shí)現(xiàn)快速場(chǎng)景識(shí)別欠啤,并且還可以讓您基于現(xiàn)實(shí)世界場(chǎng)景荚藻,來(lái)構(gòu)建詳細(xì)并引 注 的虛擬內(nèi)容。

您可以Metal洁段、Scenekit以及諸如Unity应狱、虛幻引擎之類的第三? 具,來(lái)對(duì)ARKit進(jìn) 優(yōu)

化祠丝。

ARKit

ARKit將iOS設(shè)備的攝像頭和設(shè)備動(dòng)作檢測(cè)(Motion)功能疾呻,集成到您的應(yīng) 或者游戲當(dāng)中,從

為 戶提供增強(qiáng)現(xiàn)實(shí)體驗(yàn)写半。

>所謂的增強(qiáng)現(xiàn)實(shí)(Augmented Reality, AR)岸蜗,指的是向設(shè)備攝像頭產(chǎn) 的實(shí)時(shí)動(dòng)態(tài)視圖中,添加2D或者3D元素叠蝇,然后 某種 法讓這些元素看起來(lái)就處于現(xiàn)實(shí)世界當(dāng)中璃岳,所產(chǎn)? 種 戶體

驗(yàn)。ARKit提供 設(shè)備動(dòng)作追蹤、相機(jī)場(chǎng)景捕獲和 級(jí)場(chǎng)景處 矾睦,并讓AR元素的展 變得極為

晦款,從? 簡(jiǎn)化 建立AR戶體驗(yàn)的 作難度。

探索AR的概 枚冗、特性缓溅,以及 解構(gòu)建優(yōu)秀AR場(chǎng)景的最佳實(shí)踐。1.1.ARSession類

這是 個(gè)單,是ARKit的核 類赁温, 于控制設(shè)備攝像頭坛怪,處 傳感器數(shù)據(jù),對(duì)捕獲的圖像進(jìn)

分析等等股囊。

2.ARSessionConfiguration類

跟蹤設(shè)備 向的 個(gè)基本配置,在運(yùn) 時(shí)袜匿,需要指定AR運(yùn) 的配置

ARWorldTrackingSessionConfiguration類

配置跟蹤設(shè)備的 向和位置,以及檢測(cè)設(shè)備攝像頭所看到的現(xiàn)實(shí)世界的表

ARSCNView類

來(lái)增強(qiáng)相機(jī)通過(guò)3D SceneKit所捕捉到的內(nèi)容并展AR效果的 個(gè)view

ARSKView類

來(lái)增強(qiáng)相機(jī)通過(guò)2D SpriteKit所捕捉到的內(nèi)容并展AR效果的 個(gè)view

ARAnchor類

真實(shí)世界的位置和 向,于在 個(gè)AR場(chǎng)景中放置 個(gè)物體

ARPlaneAnchor類

在 個(gè)AR Session會(huì)話中檢測(cè) 個(gè)真實(shí)世界中平 的位置和 向的相關(guān)信息

ARHitTestResult類

在 個(gè)AR Session會(huì)話中通過(guò)檢測(cè)相機(jī)視圖中的 個(gè)點(diǎn)來(lái)獲取真實(shí)世界中表 的相關(guān)信息

ARFrame類

捕獲 個(gè)視頻圖像和位置追蹤信息作為 個(gè)AR會(huì)話的 部分。

ARCamera類

在 個(gè)AR會(huì)話中攝像機(jī)的位置和成像特征信息為捕獲視頻幀

ARLightEstimate類

在 個(gè)AR會(huì)話中估計(jì)場(chǎng)景照明信息關(guān)聯(lián)到 個(gè)捕獲的視頻幀

Understanding Augmented Reality

>探索AR的概 稚疹、特性居灯,以及 解構(gòu)建優(yōu)秀AR場(chǎng)景的最佳實(shí)踐。

對(duì)于所有的AR場(chǎng)景? 内狗,最基本要求是:創(chuàng)建并追蹤現(xiàn)實(shí)空間和虛擬空間之間的關(guān)系怪嫌,其中,

現(xiàn)實(shí)空間是 戶所處的世界柳沙,虛擬空間是可對(duì)可視化內(nèi)容進(jìn) 建模的世界岩灭,這同時(shí)也是ARKit的

基本特征。當(dāng)您的應(yīng) 將這些虛擬內(nèi)容與實(shí)時(shí)視頻結(jié)合赂鲤,并 起顯 的時(shí)候噪径, 戶就可以體驗(yàn)到

所謂的「增強(qiáng)現(xiàn)實(shí)」:您的虛擬內(nèi)容成為 真實(shí)世界的 部分,盡管這只是「錯(cuò)覺(jué)」 已数初。

How World Tracking Works

為 在現(xiàn)實(shí)世界和虛擬世界之間建立對(duì)應(yīng)關(guān)系找爱,ARKit使? 種被稱為視覺(jué)慣性 程計(jì)的技

術(shù)。這項(xiàng)技術(shù)會(huì)將iOS設(shè)備的動(dòng)作感測(cè)硬件信息妙真,加上對(duì)可 場(chǎng)景的計(jì)算機(jī)視覺(jué)分析功能缴允,然后

與設(shè)備的攝像頭相結(jié)合。ARKit將會(huì)去識(shí)別場(chǎng)景圖像當(dāng)中的顯著特征珍德,然后在視頻幀中追蹤這些

特征位置的距離,然后再將這些信息與動(dòng)作感測(cè)數(shù)據(jù)進(jìn) 比較矗漾。從? 成具備設(shè)備位置和動(dòng)作特

征的 精度模型锈候。

全局追蹤(World Tracking)同樣也可以分析和識(shí)別場(chǎng)景當(dāng)中的內(nèi)容。通過(guò)使 點(diǎn)擊測(cè)試(hit-

testing)法(參ARHitTestResult類)敞贡,從 找到與相機(jī)圖像中的某個(gè)點(diǎn)所對(duì)應(yīng)的真實(shí)世界

泵琳。如果您在Session (會(huì)話)配置當(dāng)中啟planeDetection配置的話,那么ARKit就會(huì)去檢測(cè)

相機(jī)圖像當(dāng)中的 平 ,并報(bào)告其位置和? 获列。您可以使 點(diǎn)擊測(cè)試所 成的結(jié)果谷市,或者使 所

檢測(cè)到的 平 ,從 就可以在場(chǎng)景當(dāng)中放置虛擬內(nèi)容击孩,或者與之進(jìn) 交互迫悠。

Best Practices and Limitations

全局追蹤是 項(xiàng)不精確的科學(xué)(inexact science)。盡管在這個(gè)過(guò)程當(dāng)中巩梢,經(jīng)常會(huì)產(chǎn) 可觀的準(zhǔn)確

度创泄,從 讓AR的體驗(yàn) 加真實(shí)。然 括蝠,它嚴(yán)重依賴于設(shè)備物 環(huán)境的相關(guān)細(xì)節(jié)鞠抑, 這些細(xì)節(jié)并

不總是 致,有些時(shí)候也難以實(shí)時(shí)測(cè) 忌警,這也就導(dǎo)致這些物 細(xì)節(jié)往往都會(huì)存在某種程度的錯(cuò)

誤搁拙。要建立 品質(zhì)的AR體驗(yàn),那么請(qǐng)注意下述這些注意事項(xiàng)和提 :

基于可 的照明條件來(lái)設(shè)計(jì)AR場(chǎng)景法绵。全局追蹤涉及到 圖像分析的相關(guān)內(nèi)容感混,因此就需要我們

提供清晰的圖像。如果攝像頭沒(méi)有辦法看到相關(guān)的物 細(xì)節(jié)礼烈,比如說(shuō)攝像頭拍到的是? 空空如

也的墻壁弧满,或者場(chǎng)景的光線實(shí)在太暗的話,那么全局追蹤的質(zhì) 就會(huì)? 降低此熬。

根據(jù)追蹤質(zhì) 的相關(guān)信息來(lái)給 戶進(jìn) 反饋提 庭呜。全局追蹤會(huì)將圖像分析與設(shè)備的動(dòng)作模式關(guān)聯(lián)

起來(lái)。如果設(shè)備正在移動(dòng)的話犀忱,那么ARKit就可以 好地對(duì)場(chǎng)景進(jìn) 建模募谎,這樣即 設(shè)備只是

微晃動(dòng),也不會(huì)影響追蹤質(zhì) 阴汇。但是 旦 戶的動(dòng)作過(guò)多数冬、過(guò)快或者晃動(dòng)過(guò)于激烈,就會(huì)導(dǎo)致圖

像變得模糊搀庶,或者導(dǎo)致視頻幀中要追蹤的特征之間的距離過(guò) 拐纱,從 致使追蹤質(zhì) 的降低。ARCamera類能夠提供追蹤狀態(tài)哥倔,此外還能提供導(dǎo)致該狀態(tài)出現(xiàn)的相關(guān)原因秸架,您可以在UI上展

這些信息,告訴 戶如何解決追蹤質(zhì) 低這個(gè)問(wèn)題咆蒿。

給 平 檢測(cè)預(yù) 點(diǎn)時(shí)間來(lái) 成清晰的結(jié)果东抹, 旦您獲得所需的結(jié)果后蚂子,就禁? 平 檢測(cè)。

開始對(duì) 平 進(jìn) 檢測(cè)的時(shí)候缭黔,所檢測(cè)到的 平 位置和范圍很可能不準(zhǔn)確食茎。不過(guò)隨著時(shí)間的推

移,只要 平 仍然保持在場(chǎng)景當(dāng)中馏谨,那么ARKit就能夠較為精確地估計(jì) 平 的位置和范圍别渔。

當(dāng)場(chǎng)景中有 個(gè)比較 的平坦表 的話,就算您已經(jīng)使 過(guò)這個(gè) 平 來(lái)放置內(nèi)容田巴,那么ARKit可能還會(huì)繼續(xù)對(duì) 平 的錨點(diǎn)位置钠糊、范圍和變換點(diǎn)進(jìn) 修正。

ARSession類

>這是 個(gè)單,是ARKit的核 類壹哺, 于控制設(shè)備攝像頭抄伍,處 傳感器數(shù)據(jù),對(duì)捕獲的圖像進(jìn)

分析等等

每 個(gè)使ARKit創(chuàng)建的AR程必須要有 個(gè)ARSession單 對(duì)象.如果你使ARSCNView或者ARSKView來(lái) 容 的創(chuàng)建AR程的 部分,這個(gè)View已經(jīng)包含? 個(gè)ARSession實(shí).如果你使

編寫的渲染器來(lái)渲染AR內(nèi)容,你必須實(shí) 化和持有 個(gè)ARSession對(duì)象

運(yùn)? 個(gè)會(huì)話必須要有相關(guān)配置:可以實(shí) 化ARSessionConfiguration或者它的 類ARWorldTrackingSessionConfiguration,這些類確定,相對(duì)于現(xiàn)實(shí)世界, ARKit跟蹤設(shè)備的位置和

運(yùn)動(dòng),從 影響您可以創(chuàng)建的基于"增強(qiáng)現(xiàn)實(shí)”技術(shù)的類型

//run法的聲明:

//開始為session在指定的配置和選項(xiàng)下處AR

//configuration個(gè)對(duì)象,定義 會(huì)話的運(yùn)動(dòng)和現(xiàn)場(chǎng)跟蹤 為

//ARSession.RunOptions這是 個(gè)結(jié)構(gòu)體,所以當(dāng)使 系統(tǒng)默認(rèn)的時(shí)候可以寫個(gè)[],當(dāng)你改變它的配置

的時(shí)候,這個(gè)選項(xiàng)會(huì)影響怎么過(guò)渡 個(gè)AR會(huì)話的狀態(tài)

func run(_ configuration: ARSessionConfiguration, options: ARSession.RunOptions

= [])

//pause法的聲明:

func pause()

//代//代? 法可以實(shí)現(xiàn)接收視頻幀圖像捕獲和跟蹤狀態(tài)的AR會(huì)話//個(gè) 法都是可選

var delegate: ARSessionDelegate?

//代 隊(duì),如果沒(méi)有設(shè)置的話,默認(rèn) 主隊(duì)var delegateQueue: DispatchQueue?

//實(shí)現(xiàn)? 的 法可以對(duì)AR會(huì)話的狀態(tài)進(jìn) 改變protocol ARSessionObserver

-顯 和影響AR內(nèi)容

var currentFrame: ARFrame?

func add(anchor: ARAnchor)

func remove(anchor: ARAnchor)

Building a Basic AR Experience構(gòu)建基本的AR場(chǎng)景

配置AR Session管宵,然后使SceneKit或者SpriteKit來(lái)展AR內(nèi)容截珍。

如果您使ARSCNView或者ARSKView類的話,那么ARKit就可? 滿 創(chuàng)建AR場(chǎng)景的基本

要求:即每個(gè)視圖的背景 實(shí)時(shí)的相機(jī)圖像來(lái)展 箩朴,然后還可以渲染您提供的2D或者3D覆蓋

物(overlay)岗喉,從 構(gòu)建出「這些覆蓋物實(shí)際上是位于現(xiàn)實(shí)世界中」這樣 種錯(cuò)覺(jué)。要使 這些視

圖類的話炸庞,您可以根據(jù)您所想要?jiǎng)?chuàng)建的AR場(chǎng)景類型來(lái)進(jìn) 配置钱床,然后為覆蓋物選定位置和表

式。

如果您需要構(gòu)建 定義的視圖來(lái)展AR場(chǎng)景的話埠居,請(qǐng)參閱使Metal來(lái)展AR場(chǎng)景 節(jié)查牌。

本 所涉及的代碼均可以在Xcode項(xiàng) 模板當(dāng)中找到。如果要獲取完整的? 代碼滥壕,請(qǐng)使“Augmented Reality”模板來(lái)創(chuàng)建 個(gè)新的iOS應(yīng) 纸颜,然后在彈出的Content Technology菜單

當(dāng)中選擇SceneKit或者SpriteKit。

Configure and Run the AR Session /配置AR Session并運(yùn)

ARSCNView和ARSKView類都是包含在ARSession當(dāng)中的绎橘,ARSession對(duì)象則 來(lái)管 設(shè)備動(dòng)

作追蹤和進(jìn) 圖像處 的胁孙,也就是創(chuàng)建AR場(chǎng)景的必需品。但是称鳞,要運(yùn)Session涮较,您 先必須

選擇 種Session配置。

您所選擇的配置對(duì)象的類型胡岔,決定 您所創(chuàng)建的AR場(chǎng)景的 格和質(zhì) :

在具備A9或者? 版本處 器的iOS設(shè)備當(dāng)中法希,ARWorldTrackingSessionConfiguration類

提供? 精度的設(shè)備動(dòng)作追蹤功能,可以幫助您將虛擬內(nèi)容「放置」在現(xiàn)實(shí)世界中的某個(gè)表

上靶瘸。

在ARKit所 持的其他設(shè)備當(dāng)中苫亦,ARSessionConfiguration這個(gè)基礎(chǔ)類則提供 基本的動(dòng)作追蹤

功能,可以提供 弱的沉浸式AR體驗(yàn)怨咪。

要啟動(dòng)AR Session屋剑,那么 先要使 您所需要的配置,來(lái)創(chuàng)建Session配置對(duì)象诗眨,然后對(duì)ARSCNView或者ARSKView實(shí) 中的session對(duì)象調(diào)run(_:options:)法:

override func viewWillAppear(_ animated: Bool) {

super.viewWillAppear(animated)

// Create a session configuration

let configuration = ARWorldTrackingSessionConfiguration()

configuration.planeDetection = .horizontal

// Run the view's session

sceneView.session.run(configuration)

}

>重要

>只有當(dāng)視圖即將展 在屏幕的時(shí)候唉匾,才能夠運(yùn) 視圖Session。

當(dāng)您配置完AR Session之后匠楚,就可以使SceneKit或者SpriteKit巍膘,來(lái)將虛擬內(nèi)容放置到視圖當(dāng)

中 。

Providing 3D Virtual Content with SceneKit使SceneKit來(lái)提供3D虛

擬元素

>使SceneKit在您的AR場(chǎng)景中放置逼真的三維圖像芋簿。

由于ARKit會(huì) 動(dòng)將SceneKit空間與現(xiàn)實(shí)世界進(jìn) 匹配峡懈,因此只需要放置 個(gè)虛擬對(duì)象,然后

讓其位于 個(gè)看起來(lái)比較真實(shí)的位置与斤,這就需要您適當(dāng)?shù)卦O(shè)置SceneKit對(duì)象的位置肪康。 如,在

默認(rèn)配置下撩穿,以下代碼會(huì)將 個(gè)10立 厘米的立 體放置在相機(jī)初始位置的前20厘米處:

let cubeNode = SCNNode(geometry: SCNBox(width: 0.1, height: 0.1, length: 0.1,

chamferRadius: 0))

cubeNode.position = SCNVector3(0, 0, -0.2) // SceneKit/AR coordinates are in

meters

sceneView.scene.rootNode.addChildNode(cubeNode)

>上述代碼直接在視圖的SceneKit場(chǎng)景中放置? 個(gè)對(duì)象磷支。該對(duì)象會(huì) 動(dòng)追蹤真實(shí)世界的位置,

因?yàn)锳RKit將SceneKit空間與現(xiàn)實(shí)世界空間互相匹配 起來(lái)

此外食寡,您也可以使ARAnchor類來(lái)追蹤現(xiàn)實(shí)世界的位置雾狈,可以? 創(chuàng)建錨點(diǎn)并將其添加到Session當(dāng)中,也可以對(duì)ARKit動(dòng)創(chuàng)建的錨點(diǎn)進(jìn) 觀察(observing)抵皱。 如善榛,當(dāng) 平 檢測(cè)啟

的時(shí)候,ARKit會(huì)為每個(gè)檢測(cè)到的 平 添加錨點(diǎn)叨叙,并保持 新锭弊。要為這些錨點(diǎn)添加可視化內(nèi)容

的話,就需要實(shí)現(xiàn)ARSCNViewDelegate法擂错,如下所 :

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor:

ARAnchor) {

// This visualization covers only detected planes.

guard let planeAnchor = anchor as? ARPlaneAnchor else { return }

// Create a SceneKit plane to visualize the node using its position and

extent.

let plane = SCNPlane(width: CGFloat(planeAnchor.extent.x), height:

CGFloat(planeAnchor.extent.z))

let planeNode = SCNNode(geometry: plane)

planeNode.position = SCNVector3Make(planeAnchor.center.x, 0,

planeAnchor.center.z)

// SCNPlanes are vertically oriented in their local coordinate space.

// Rotate it to match the horizontal orientation of the ARPlaneAnchor.

planeNode.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0)

// ARKit owns the node corresponding to the anchor, so make the plane a child

node.

node.addChildNode(planeNode)

}

Follow Best Practices for Designing 3D Assets /遵循設(shè)計(jì)3D資源時(shí)的最佳實(shí)踐

>使SceneKit基于物 引擎的照明模型味滞,以 獲得 為逼真的外觀。(參SCNMaterial類和

SceneKit代碼項(xiàng) 當(dāng)中的 「Badger: Advanced Rendering」钮呀。)

打上環(huán)境光遮蔽陰影(Bake ambient occlusion shading)剑鞍,使得物體在各種場(chǎng)景照明條件下能夠

正常亮起。

>如果您打算創(chuàng)建 個(gè)虛擬對(duì)象爽醋,并打算將其放置在AR的真實(shí)平(real-world flat surface)上蚁署,

那么請(qǐng)?jiān)?D素材中的對(duì)象下 ,添加 個(gè)帶有柔和陰影紋 的透明平 蚂四。

Providing 2D Virtual Content with SpriteKit(使SpriteKit來(lái)提供2D虛

擬元素)

使SpriteKit在您的3D AR場(chǎng)景中放置 維圖像光戈。

SpriteKit只包含有2D元素哪痰,但是增強(qiáng)現(xiàn)實(shí)則涉及到現(xiàn)實(shí)世界的3D空間。因此久妆,使ARSKView類來(lái)創(chuàng)建AR場(chǎng)景晌杰,這樣就可以在真實(shí)世界對(duì)應(yīng)的3D位置( ARAnchor對(duì)象)中放置2D精靈元素( SKNode)對(duì)象)。當(dāng) 戶移動(dòng)設(shè)備的時(shí)候筷弦,視圖會(huì) 動(dòng)旋轉(zhuǎn)并縮放與錨點(diǎn)相對(duì)應(yīng)的SpriteKit結(jié)點(diǎn)肋演,看起來(lái)這些元素能夠追蹤相機(jī)所看到的真實(shí)世界。

舉個(gè)? 烂琴,您可以將2D圖像以漂浮的 式爹殊,放置在3D空間當(dāng)中:

// Create a transform with a translation of 0.2 meters in front of the camera.

var translation = matrix_identity_float4x4

translation.columns.3.z = -0.2

let transform = simd_mul(view.session.currentFrame.camera.transform, translation)

// Add a new anchor to the session.

let anchor = ARAnchor(transform: transform)

view.session.add(anchor: anchor)

// (Elsewhere...) Provide a label node to represent the anchor.

func view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? {

return SKLabelNode(text: "??")

}

上 的這個(gè)view(_:nodeFor:)法將會(huì)返回 個(gè)SKLabelNode對(duì)象, 以展? 本標(biāo)簽奸绷。與 多

數(shù)SpriteKit結(jié)點(diǎn) 樣梗夸,這個(gè)類將會(huì)創(chuàng)建 個(gè)2D的可視化表 ,因此ARSKView類將會(huì)以 告牌

的樣式來(lái)展 這個(gè)結(jié)點(diǎn):精靈可以通過(guò)(圍繞z軸)縮放以及旋轉(zhuǎn)健盒,讓其看起來(lái)能夠跟隨錨點(diǎn)的3D位置绒瘦,但是卻始終 向相機(jī)。

Displaying an AR Experience with Metal(使Metal來(lái)展AR場(chǎng)景)通過(guò)渲染相機(jī)圖像扣癣,以及使 位置追蹤信息來(lái)展 覆蓋(overlay)物惰帽,從 來(lái)構(gòu)建 定義的AR視

圖場(chǎng)景。

ARKit中內(nèi)置? 些視圖類父虑,從 能夠輕松地SceneKit或者SpriteKit來(lái)展AR場(chǎng)景该酗。然 ,

如果您使 的是? 的渲染引擎(或者集成 第三 引擎)士嚎,那么ARKit還提供? 定義視圖以

及其他的 持環(huán)境呜魄,來(lái)展AR場(chǎng)景。

在所有的AR場(chǎng)景中莱衩, 先就是要配置 個(gè)ARSession對(duì)象爵嗅, 來(lái)管 攝像頭拍攝和對(duì)設(shè)備動(dòng)作

進(jìn) 處 。Session定義并維護(hù)現(xiàn)實(shí)空間和虛擬空間之間的關(guān)聯(lián)關(guān)系笨蚁,其中睹晒,現(xiàn)實(shí)空間是 戶所

處的世界,虛擬空間是可對(duì)可視化內(nèi)容進(jìn) 建模的世界括细。如果要在 定義視圖當(dāng)中展 您的AR場(chǎng)景的話伪很,那么您需要:

從Session中檢索視頻幀和追蹤信息

將這些幀圖像作為背景,渲染到 定義視圖當(dāng)中

使 追蹤信息奋单,從 在相機(jī)圖像上 定位并繪制AR內(nèi)容

>本 所涉及的代碼均可以在Xcode項(xiàng) 模板當(dāng)中找到锉试。如果要獲取完整的? 代碼,請(qǐng)使“Augmented Reality”模板來(lái)創(chuàng)建 個(gè)新的iOS應(yīng) 览濒,然后在彈出的Content Technology菜單

當(dāng)中選擇“Metal”

Get Video Frames and Tracking Data from the Session(從Session中獲取視頻幀和追

蹤數(shù)據(jù))

請(qǐng)? 創(chuàng)建并維護(hù)ARSession實(shí) 呆盖,然后根據(jù)您所希望提供的AR場(chǎng)景類型拖云,使 合適的Session配置來(lái)運(yùn) 這個(gè)實(shí) 。(要實(shí)現(xiàn)這點(diǎn)的話絮短,請(qǐng)參閱「構(gòu)建基本的AR場(chǎng)景」江兢。)Session從攝像機(jī)當(dāng)中捕獲視頻昨忆,然后在建模的3D空間中追蹤設(shè)備的位置和 向丁频,并提供ARFrame對(duì)

象。每個(gè)ARFrame對(duì)象都包含有單獨(dú)的視頻幀(frame)圖像和被捕獲時(shí)的設(shè)備位置追蹤信息邑贴。

要訪問(wèn)AR Session中 成的ARFrame對(duì)象的話席里,有以下兩種 法,使 何種 法取決于您應(yīng)

的設(shè)計(jì)模式是偏好主動(dòng)拉取(pull)還是被動(dòng)推送(push)拢驾。

如果您傾向于定時(shí)獲取視頻幀的話(也就是主動(dòng)拉取設(shè)計(jì)模式)奖磁,那么請(qǐng)使Session的currentFrame屬性,這樣就可以在每次重繪視圖內(nèi)容的時(shí)候繁疤,獲取當(dāng)前的幀圖像和追蹤信息咖为。ARKit Xcode模板使? 如下 法:

// in Renderer class, called from MTKViewDelegate.draw(in:) via Renderer.update()

func updateGameState() {

guard let currentFrame = session.currentFrame else {

return

}

updateSharedUniforms(frame: currentFrame)

updateAnchors(frame: currentFrame)

updateCapturedImageTextures(frame: currentFrame)

if viewportSizeDidChange {

viewportSizeDidChange = false

updateImagePlane(frame: currentFrame)

}

}

相反,如果您的應(yīng) 設(shè)計(jì)傾向于使 被動(dòng)推送模式的話稠腊,那么請(qǐng)實(shí)現(xiàn)session(_:didUpdate:)代

法躁染,當(dāng)每個(gè)視頻幀被捕獲之后,Session就會(huì)調(diào) 這個(gè)代? 法(默認(rèn)每秒捕獲60幀)架忌。

獲得 個(gè)視頻幀之后吞彤,您就需要繪制相機(jī)圖像 ,然后將AR場(chǎng)景中包含的所有覆蓋物進(jìn)? 新

和展 叹放。

Draw the Camera Image(繪制相機(jī)圖像)

每個(gè)ARFrame對(duì)象的capturedImage屬性都包含 從設(shè)備相機(jī)中捕獲的像素緩沖區(qū)(pixel

buffer)饰恕。要將這個(gè)圖像作為背景繪制到 定義視圖當(dāng)中,您需要從圖像內(nèi)容中構(gòu)建紋(texture)井仰,然后提交使 這些紋 進(jìn)GPU渲染的命令埋嵌。

像素緩沖區(qū)的內(nèi)容將被編碼為雙(biplanar) YCbCr數(shù)據(jù)格式(也成為YUV);要渲染圖像的

話,您需要將這些像素?cái)?shù)據(jù)轉(zhuǎn)換為可繪制的RGB格式俱恶。對(duì)于Metal渲染? 雹嗦,最 效的 法

是使GPU著 代碼(shader code)來(lái)執(zhí) 這個(gè)轉(zhuǎn)換 。借助CVMetalTextureCacheAPI速那,可以

從像素緩沖區(qū)中 成兩個(gè)Metal紋——個(gè) 于決定緩沖區(qū)的亮度(Y)俐银, 個(gè) 于決定緩沖區(qū)的

度(CbCr)。

func updateCapturedImageTextures(frame: ARFrame) {

// Create two textures (Y and CbCr) from the provided frame's captured image//從所提供的視頻幀中端仰,根據(jù)其中所捕獲的圖像捶惜,創(chuàng)建兩個(gè)紋(Y and CbCr)

let pixelBuffer = frame.capturedImage

if (CVPixelBufferGetPlaneCount(pixelBuffer) < 2) {

return

}

capturedImageTextureY = createTexture(fromPixelBuffer: pixelBuffer,

pixelFormat:.r8Unorm, planeIndex:0)!

capturedImageTextureCbCr = createTexture(fromPixelBuffer: pixelBuffer,

pixelFormat:.rg8Unorm, planeIndex:1)!

}

func createTexture(fromPixelBuffer pixelBuffer: CVPixelBuffer, pixelFormat:

MTLPixelFormat, planeIndex: Int) -> MTLTexture? {

var mtlTexture: MTLTexture? = nil

let width = CVPixelBufferGetWidthOfPlane(pixelBuffer, planeIndex)

let height = CVPixelBufferGetHeightOfPlane(pixelBuffer, planeIndex)

var texture: CVMetalTexture? = nil

let status = CVMetalTextureCacheCreateTextureFromImage(nil,

capturedImageTextureCache, pixelBuffer, nil, pixelFormat, width, height,

planeIndex, &texture)

if status == kCVReturnSuccess {

mtlTexture = CVMetalTextureGetTexture(texture!)

}

return mtlTexture

}

接下來(lái),使 借助顏 變換矩陣將YCbCr轉(zhuǎn)換為RGB的函數(shù)片段荔烧,完成這兩個(gè)紋 的繪制吱七,我

們這 將整個(gè)渲染命令進(jìn) 編碼汽久。

fragment float4 capturedImageFragmentShader(ImageColorInOut in [[stage_in]],

texture2d

capturedImageTextureY [[ texture(kTextureIndexY) ]],

texture2d

capturedImageTextureCbCr [[ texture(kTextureIndexCbCr) ]]) {

constexpr sampler colorSampler(mip_filter::linear,

mag_filter::linear,

min_filter::linear);

const float4x4 ycbcrToRGBTransform = float4x4(

float4(+1.164380f, +1.164380f, +1.164380f, +0.000000f),

float4(+0.000000f, -0.391762f, +2.017230f, +0.000000f),

float4(+1.596030f, -0.812968f, +0.000000f, +0.000000f),

float4(-0.874202f, +0.531668f, -1.085630f, +1.000000f)

);

// Sample Y and CbCr textures to get the YCbCr color at the given texture

coordinate

float4 ycbcr = float4(capturedImageTextureY.sample(colorSampler,

in.texCoord).r,

capturedImageTextureCbCr.sample(colorSampler,

in.texCoord).rg, 1.0);

// Return converted RGB color

return ycbcrToRGBTransform * ycbcr;

}

請(qǐng)使displayTransform(withViewportSize:orientation:)法來(lái)確保整個(gè)相機(jī)圖像完全覆蓋 整

個(gè)視圖。關(guān)于如何使 這個(gè) 法踊餐,以及完整的Metal管道配置代碼景醇,請(qǐng)參閱完整的Xcode模

板。(請(qǐng)使“Augmented Reality”模板來(lái)創(chuàng)建 個(gè)新的iOS應(yīng) 吝岭,然后在彈出的Content

Technology菜單當(dāng)中選擇“Metal”三痰。)

Track and Render Overlay Content(追蹤并渲染覆蓋內(nèi)容)

>AR場(chǎng)景通常側(cè)重于渲染3D覆蓋物,使得這些內(nèi)容似乎是從相機(jī)中所看到的真實(shí)世界的 部分窜管。

為 實(shí)現(xiàn)這種效果散劫,我們使ARAnchor類,來(lái)對(duì)3D內(nèi)容相對(duì)于現(xiàn)實(shí)世界空間的位置和 向進(jìn)

建模幕帆。錨點(diǎn)提供 變換(transform)屬性获搏,在渲染的時(shí)候可供參考。

舉個(gè)? 失乾,當(dāng) 戶點(diǎn)擊屏幕的時(shí)候常熙,Xcode模板會(huì)在設(shè)備前? 約20厘米處,創(chuàng)建 個(gè)錨點(diǎn)碱茁。

func handleTap(gestureRecognize: UITapGestureRecognizer) {

// Create anchor using the camera's current position

if let currentFrame = session.currentFrame {

// Create a transform with a translation of 0.2 meters in front of the

camera

var translation = matrix_identity_float4x4

translation.columns.3.z = -0.2

let transform = simd_mul(currentFrame.camera.transform, translation)

// Add a new anchor to the session

let anchor = ARAnchor(transform: transform)

session.add(anchor: anchor)

}

}

在您的渲染引擎當(dāng)中裸卫,使 每個(gè)ARAnchor對(duì)象的transform屬性來(lái)放置虛擬內(nèi)容。Xcode模板

在內(nèi)部的handleTap法中早芭,使 添加到Session當(dāng)中每個(gè)錨點(diǎn)來(lái)定位 個(gè)簡(jiǎn)單的立 體 格(cube mesh):

func updateAnchors(frame: ARFrame) {

// Update the anchor uniform buffer with transforms of the current frame's

anchors

anchorInstanceCount = min(frame.anchors.count, kMaxAnchorInstanceCount)

var anchorOffset: Int = 0

if anchorInstanceCount == kMaxAnchorInstanceCount {

anchorOffset = max(frame.anchors.count - kMaxAnchorInstanceCount, 0)

}

for index in 0..

let anchor = frame.anchors[index + anchorOffset]

// Flip Z axis to convert geometry from right handed to left handed

var coordinateSpaceTransform = matrix_identity_float4x4

coordinateSpaceTransform.columns.2.z = -1.0

let modelMatrix = simd_mul(anchor.transform, coordinateSpaceTransform)

let anchorUniforms = anchorUniformBufferAddress.assumingMemoryBound(to:

InstanceUniforms.self).advanced(by: index)

anchorUniforms.pointee.modelMatrix = modelMatrix

}

}

在 為復(fù)雜的AR場(chǎng)景中彼城,您可以使 點(diǎn)擊測(cè)試或者 平 檢測(cè),來(lái)尋找真實(shí)世界當(dāng)中曲 的位

置退个。要 解關(guān)于此內(nèi)容的詳細(xì)信息募壕,請(qǐng)參閱planeDetection屬性和hitTest(_:types:)法。對(duì)于這

兩者? 语盈,ARKit都會(huì) 成ARAnchor對(duì)象作為結(jié)果舱馅,因此您仍然需要使 錨點(diǎn)的transform屬

性來(lái)放置虛擬內(nèi)容。

Render with Realistic Lighting(根據(jù)實(shí)際光照度進(jìn) 渲染)

當(dāng)您在場(chǎng)景中配置 于繪制3D內(nèi)容的著 器時(shí)刀荒,請(qǐng)使 每個(gè)ARFrame對(duì)象當(dāng)中的預(yù)計(jì)光照度信

息代嗤,來(lái)產(chǎn)? 為逼真的陰影:

// in Renderer.updateSharedUniforms(frame:):

// Set up lighting for the scene using the ambient intensity if provided

var ambientIntensity: Float = 1.0

if let lightEstimate = frame.lightEstimate {

ambientIntensity = Float(lightEstimate.ambientIntensity) / 1000.0

}

let ambientLightColor: vector_float3 = vector3(0.5, 0.5, 0.5)

uniforms.pointee.ambientLightColor = ambientLightColor * ambientIntensity

要 解該? 中的全部Metal配置,以及所使 的渲染命令缠借,請(qǐng)參 完整的Xcode模板干毅。(請(qǐng)

使“Augmented Reality”模板來(lái)創(chuàng)建 個(gè)新的iOS應(yīng) ,然后在彈出的Content Technology菜單當(dāng)中選擇“Metal”泼返。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末硝逢,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌渠鸽,老刑警劉巖叫乌,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異徽缚,居然都是意外死亡憨奸,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門凿试,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)排宰,“玉大人,你說(shuō)我怎么就攤上這事红省《罡鳎” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵吧恃,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我麻诀,道長(zhǎng)痕寓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任蝇闭,我火速辦了婚禮呻率,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘呻引。我一直安慰自己礼仗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布逻悠。 她就那樣靜靜地躺著元践,像睡著了一般。 火紅的嫁衣襯著肌膚如雪童谒。 梳的紋絲不亂的頭發(fā)上单旁,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音饥伊,去河邊找鬼象浑。 笑死,一個(gè)胖子當(dāng)著我的面吹牛琅豆,可吹牛的內(nèi)容都是我干的愉豺。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼茫因,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蚪拦!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤外盯,失蹤者是張志新(化名)和其女友劉穎摘盆,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體饱苟,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡孩擂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了箱熬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片类垦。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖城须,靈堂內(nèi)的尸體忽然破棺而出蚤认,到底是詐尸還是另有隱情,我是刑警寧澤糕伐,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布砰琢,位于F島的核電站,受9級(jí)特大地震影響良瞧,放射性物質(zhì)發(fā)生泄漏陪汽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一褥蚯、第九天 我趴在偏房一處隱蔽的房頂上張望挚冤。 院中可真熱鬧,春花似錦赞庶、人聲如沸训挡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)澜薄。三九已至,卻和暖如春誊锭,著一層夾襖步出監(jiān)牢的瞬間表悬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工丧靡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蟆沫,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓温治,卻偏偏與公主長(zhǎng)得像饭庞,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子熬荆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容