ARkit知多少---從青銅到王者

ARKit

Introducing ARKit

iOS 11 引入 ARKit,這是 個全新的框架,允許開發者輕松地為 iPhone 和 iPad 創建 與倫比 的增強現實體驗。通過將虛擬對象和虛擬信息同 戶周圍的環境相互融合,ARKit 使得應用跳出屏幕的限制,讓它們能夠以全新的方式與現實世界進行交互。

AR作品.png

基礎技術視覺慣性里程計

ARKit 使用視覺慣性里程計 (Visual Inertial Odometry, VIO) 來精準追蹤周圍的世界。VIO 將攝像頭的傳感器數據同 Core Motion 數據進行融合。這兩種數據允許設備能夠高精度地感測設備在房間內的動作,而且無需額外校準。

場景識別與光亮估計

借助 ARKit,iPhone 和 iPad 可以分析相機界面中所呈現的場景,并在房間當中尋找水平面。 ARKit 不僅可以檢測諸如桌子和地板之類的水平面 ,還可以在較小特征點 (feature points) 上追蹤和放置對象。ARKit 還利用攝像頭傳感器來估算場景當中的可見光總亮度,并為虛擬對象添加符合環境照明的光量 。

性能硬件與渲染優化

ARKit 運行在 Apple A9 和 A10 處 器上。這些處 器能夠為 ARKit 提供突破性的性能,從而可以實現快速場景識別,并且還可以讓您基于現實世界場景,來構建詳細并引人注目的虛擬內容。 您可以利用 Metal、Scenekit 以及諸如 Unity、虛幻引擎之類的第三方具,來對 ARKit 進行優化。

ARKit

ARKit 將 iOS 設備的攝像頭和設備動作檢測 (Motion) 功能,集成到您的應用或者游戲當中,從而為用戶提供增強現實體驗。

所謂的增強現實 (Augmented Reality, AR),指的是向設備攝像頭產生的實時動態視圖中,添加 2D 或者 3D 元素,然后用某種方法讓這些元素看起來就處于現實世界當中,所產生一種用戶體驗。ARKit 提供了設備動作追蹤、相機場景捕獲和 級場景處 ,并讓 AR 元素的展示變得極為便利,從而大大簡化了建立 AR 用戶體驗的操作難度。
探索 AR 的概念、特性,以及了解構建優秀 AR 場景的最佳實踐。

  1. ARSession類
    這是一個單例, 是 ARKit 的核心類, 用于控制設備攝像頭,處理傳感器數據,對捕獲的圖像進行分析等等。
  2. ARSessionConfiguration類
    跟蹤設備方向的一個基本配置, 在運行時,需要指定AR運行的配置
  3. ARWorldTrackingSessionConfiguration類 配置跟蹤設備的方向和位置,以及檢測設備攝像頭所看到的現實世界的表面
  4. ARSCNView類
    來增強相機通過 3D SceneKit 所捕捉到的內容并展示 AR 效果的一個 view
  5. ARSKView類
    來增強相機通過 2D SpriteKit 所捕捉到的內容并展示 AR 效果的 個 view
  6. ARAnchor類
    真實世界的位置和方向, 于在一個AR場景中放置 個物體
  7. ARPlaneAnchor類
    在 個AR Session 會話中檢測一個真實世界中平面的位置和方向的相關信息
  8. ARHitTestResult類
    在一個AR Session會話中通過檢測相機視圖中的一個點來獲取真實世界中表面的相關信息
  9. ARFrame類
    捕獲一個視頻圖像和位置追蹤信息作為一個AR 會話的 部分。
  10. ARCamera類 在一個AR會話中攝像機的位置和成像特征信息為捕獲視頻幀
  11. ARLightEstimate類 在 個AR會話中估計場景照明信息關聯到 個捕獲的視頻幀
    Understanding Augmented Reality

探索 AR 的概念、特性,以及了解構建優秀 AR 場景的最佳實踐。

對于所有的 AR 場景中,最基本要求是:創建并追蹤現實空間和虛擬空間之間的關系,其中, 現實空間是用戶所處的世界,虛擬空間是可對可視化內容進 建模的世界,這同時也是 ARKit 的 基本特征。當您的應 將這些虛擬內容與實時視頻結合,并一起顯示的時候,用戶就可以體驗到所謂的「增強現實」:您的虛擬內容成為 真實世界的一部分,盡管這只是「錯覺」而已。

How World Tracking Works

為 在現實世界和虛擬世界之間建立對應關系,ARKit 使用一種被稱為視覺慣性里程計的技術。這項技術會將 iOS 設備的動作感測硬件信息,加上對可見場景的計算機視覺分析功能,然后 與設備的攝像頭相結合。ARKit 將會去識別場景圖像當中的顯著特征,然后在視頻幀中追蹤這些特征位置的距離,然后再將這些信息與動作感測數據進行比較。從而成具備設備位置和動作特征的高精度模型。
全局追蹤 (World Tracking) 同樣也可以分析和識別場景當中的內容。通過使用點擊測試 (hit- testing) 法(參見ARHitTestResult類),從而找到與相機圖像中的某個點所對應的真實世界 。如果您在 Session (會話) 配置當中啟 planeDetection配置的話,那么 ARKit 就會去檢測相機圖像當中的水平面,并報告其位置和大小。您可以使用點擊測試所生成的結果,或者使用所檢測到的水平面,從而就可以在場景當中放置虛擬內容,或者與之進行交互。

Best Practices and Limitations

全局追蹤是一項不精確的科學 (inexact science)。盡管在這個過程當中,經常會產生可觀的準確度,從而讓 AR 的體驗更加真實。然而,它嚴重依賴于設備物理環境的相關細節, 這些細節并不總是一致,有些時候也難以實時測量,這也就導致這些物理細節往往都會存在某種程度的錯誤。要建立高品質的 AR 體驗,那么請注意下述這些注意事項和提 :
基于可見的照明條件來設計 AR 場景。全局追蹤涉及到圖像分析的相關內容,因此就需要我們提供清晰的圖像。如果攝像頭沒有辦法看到相關的物理細節,比如說攝像頭拍到的是空空如也的墻壁,或者場景的光線實在太暗的話,那么全局追蹤的質量就會大大降低。
根據追蹤質量的相關信息來給用戶進 反饋提 。全局追蹤會將圖像分析與設備的動作模式關聯起來。如果設備正在移動的話,那么 ARKit 就可以 好地對場景進行建模,這樣即便設備只是微晃動,也不會影響追蹤質量。但是一旦用戶的動作過多、過快或者晃動過于激烈,就會導致圖像變得模糊,或者導致視頻幀中要追蹤的特征之間的距離過大,從 致使追蹤質量的降低。 ARCamera類能夠提供追蹤狀態,此外還能提供導致該狀態出現的相關原因,您可以在 UI 上展示這些信息,告訴用戶如何解決追蹤質量低這個問題。
給水平面檢測預留點時間來生成清晰的結果,一旦您獲得所需的結果后,就禁止水平面檢測。 開始對水平面進行檢測的時候,所檢測到的水平面位置和范圍很可能不準確。不過隨著時間的推 移,只要水平面仍然保持在場景當中,那么 ARKit 就能夠較為精確地估計水平面的位置和范圍。 當場景中有一個比較 的平坦表 的話,就算您已經使用過這個水平面來放置內容,那么ARKit 可能還會繼續對水平面的錨點位置、范圍和變換點進行修正。

ARSession類

這是一個單 , 是 ARKit 的核心類,用于控制設備攝像頭,處理傳感器數據,對捕獲的圖像進行分析等等

  • 每 個使 ARKit創建的AR 工程必須要有一個ARSession單例對象. 如果你使 ARSCNView或者 ARSKView來更容易的創建AR 工程的一部分, 這個View已經包含 個ARSession實例. 如果你使用自己編寫的渲染器來渲染AR內容, 你必須實例化和持有一個ARSession對象
  • 運行個會話必須要有相關配置: 可以實例化 ARSessionConfiguration或者它的子類 ARWorldTrackingSessionConfiguration, 這些類確定, 相對于現實世界, ARKit跟蹤設備的位置和 運動,從 影響您可以創建的基于"增強現實”技術的類型
     //run 法的聲明:
  //開始為session在指定的配置和選項下處 AR
//configuration  個對象,定義 會話的運動和現場跟蹤 為
//ARSession.RunOptions 這是 個結構體, 所以當使 系統默認的時候可以寫個[], 當你改變它的配置的時候, 這個選項會影響怎么過渡 個AR會話的狀態
func run(_ configuration: ARSessionConfiguration, options: ARSession.RunOptions = [])
//pause 法的聲明: func pause()
//代理
//代理方法可以實現接收視頻幀圖像捕獲和跟蹤狀態的AR會話 
// 里面幾個方法都是可選
var delegate: ARSessionDelegate?
//代理隊列 , 如果沒有設置的話, 默認 主隊列 var delegateQueue: DispatchQueue?
//實現里面的方法可以對AR會話的狀態進行改變 protocol ARSessionObserver
-顯示和影響AR內容
var currentFrame: ARFrame?
  func add(anchor: ARAnchor)
  func remove(anchor: ARAnchor)

Building a Basic AR Experience 構建基本的 AR 場景

配置 AR Session,然后使 SceneKit 或者 SpriteKit 來展示 AR 內容。

如果您使用ARSCNView或者 ARSKView類的話,那么 ARKit 就可自行滿足創建 AR 場景的基本要求:即每個視圖的背景用實時的相機圖像來展 ,然后還可以渲染您提供的 2D 或者 3D 覆蓋 物 (overlay),從而構建出「這些覆蓋物實際上是位于現實世界中」這樣一種錯覺。要使用這些視圖類的話,您可以根據您所想要創建的 AR 場景類型來進行配置,然后為覆蓋物選定位置和表達式。
如果您需要構建自定義的視圖來展示AR 場景的話,請參閱使 Metal 來展示AR 場景一節。
本文所涉及的代碼均可以在 Xcode 項目模板當中找到。如果要獲取完整的
![Uploading WX20170817-101815@2x_308642.png . . .]代碼,請使 “Augmented Reality” 模板來創建一個新的 iOS 應 ,然后在彈出的 Content Technology 菜單當中選擇 SceneKit或者SpriteKit。

Configure and Run the AR Session / 配置 AR Session 并運行

ARSCNView和 ARSKView類都是包含在 ARSession當中的, ARSession對象則 來管 設備動 作追蹤和進 圖像處 的,也就是創建 AR 場景的必需品。但是,要運行 Session,您 先必須選擇一種 Session 配置。


您所選擇的配置對象的類型,決定您所創建的 AR 場景的風格和質量:
在具備 A9 或者更高版本處理器的 iOS 設備當中,ARWorldTrackingSessionConfiguration 類提供高精度的設備動作追蹤功能,可以幫助您將虛擬內容「放置」在現實世界中的某個表面上。
在 ARKit 所支持的其他設備當中,ARSessionConfiguration這個基礎類則提供基本的動作追蹤功能,可以提供略弱的沉浸式 AR 體驗。
要啟動 AR Session,那么 先要使用您所需要的配置,來創建 Session 配置對象,然后對 ARSCNView或者 ARSKView實 中的 session對象調用 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)
    }

重要
只有當視圖即將展示在屏幕的時候,才能夠運 視圖 Session。

當您配置完 AR Session 之后,就可以使用 SceneKit 或者 SpriteKit ,來將虛擬內容放置到視圖當 中 。

Providing 3D Virtual Content with SceneKit 使 SceneKit 來提供 3D 虛 擬元素

使用SceneKit 在您的 AR 場景中放置逼真的三維圖像。

由于 ARKit 會 動將 SceneKit 空間與現實世界進 匹配,因此只需要放置一個虛擬對象,然后 讓其位于 個看起來比較真實的位置,這就需要您適當地設置 SceneKit 對象的位置。例如,在默認配置下,以下代碼會將 個 10 立方厘米的立 體放置在相機初始位置的前 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 場景中放置 個對象。該對象會自動追蹤真實世界的位置, 因為 ARKit 將 SceneKit 空間與現實世界空間互相匹配起來
此外,您也可以使 ARAnchor 類來追蹤現實世界的位置,可以自行創建錨點并將其添加到 Session 當中,也可以對 ARKit 動創建的錨點進行觀察 (observing)。 如,當水平面檢測啟用的時候,ARKit 會為每個檢測到的 平 添加錨點,并保持更新。要為這些錨點添加可視化內容的話,就需要實現 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 / 遵循設計 3D 資源時的最佳實踐

使用SceneKit 基于物理引擎的照明模型,以獲得更為逼真的外觀。(參 SCNMaterial類和SceneKit 代碼項目當中的 「Badger: Advanced Rendering」。)

打上環境光遮蔽陰影 (Bake ambient occlusion shading),使得物體在各種場景照明條件下能夠正常亮起。

如果您打算創建一個虛擬對象,并打算將其放置在 AR 的真實平 (real-world flat surface) 上, 那么請在 3D 素材中的對象下 ,添加一個帶有柔和陰影紋理的透明平 。

Providing 2D Virtual Content with SpriteKit(使 SpriteKit 來提供 2D 虛 擬元素)

使 SpriteKit 在您的 3D AR 場景中放置 維圖像。
SpriteKit 只包含有 2D 元素,但是增強現實則涉及到現實世界的 3D 空間。因此,使用ARSKView類來創建 AR 場景,這樣就可以在真實世界對應的 3D 位置 ( ARAnchor對象) 中放置 2D 精靈元素 ( SKNode) 對象)。當用戶移動設備的時候,視圖會自動旋轉并縮放與錨點相對應的 SpriteKit 結點,看起來這些元素能夠追蹤相機所看到的真實世界。
舉個例子,您可以將 2D 圖像以漂浮的方式,放置在 3D 空間當中:

// 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: "?? ") }

上面的這個 view(_:nodeFor:) 法將會返回一個 SKLabelNode對象, 以展示本標簽。與大多數 SpriteKit 結點 樣,這個類將會創建一個 2D 的可視化表 ,因此ARSKView類將會以廣告牌的樣式來展示這個結點:精靈可以通過(圍繞 z 軸)縮放以及旋轉,讓其看起來能夠跟隨錨點的 3D 位置,但是卻始終面向相機。

Displaying an AR Experience with Metal(使 Metal 來展 AR 場景)

通過渲染相機圖像,以及使用位置追蹤信息來展 覆蓋(overlay)物,從 來構建自定義的 AR 視圖場景。
ARKit 中內置了一些視圖類,從而能夠輕松地 SceneKit 或者 SpriteKit 來展 AR 場景。然而, 如果您使用的是自己的渲染引擎(或者集成 第三方引擎),那么 ARKit 還提供自定義視圖以及其他的支持環境,來展示 AR 場景。


在所有的 AR 場景中, 先就是要配置一個 ARSession對象, 來管理攝像頭拍攝和對設備動作進行處理。Session 定義并維護現實空間和虛擬空間之間的關聯關系,其中,現實空間是用戶所處的世界,虛擬空間是可對可視化內容進行建模的世界。如果要在自定義視圖當中展示您的 AR 場景的話,那么您需要:

  1. 從 Session 中檢索視頻幀和追蹤信息
  2. 將這些幀圖像作為背景,渲染到自定義視圖當中
  3. 使用追蹤信息,從而在相機圖像上方定位并繪制 AR 內容

本 所涉及的代碼均可以在 Xcode 項目模板當中找到。如果要獲取完整的示例代碼,請使用 “Augmented Reality” 模板來創建一個新的 iOS 應用,然后在彈出的 Content Technology 菜單當中選擇 “Metal”

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

請自行創建并維護 ARSession實例,然后根據您所希望提供的 AR 場景類型,使 合適的 Session 配置來運行這個實例。(要實現這點的話,請參閱「構建基本的 AR 場景」。)

Session 從攝像機當中捕獲視頻,然后在建模的 3D 空間中追蹤設備的位置和方向,并提供 ARFrame對象。每個 ARFrame對象都包含有單獨的視頻幀 (frame) 圖像和被捕獲時的設備位置追蹤信息。

要訪問 AR Session 中 成的 ARFrame對象的話,有以下兩種方法,使用何種方法取決于您應用的設計模式是偏好主動拉取 (pull) 還是被動推送 (push)。

如果您傾向于定時獲取視頻幀的話(也就是主動拉取設計模式),那么請使用 Session 的 currentFrame屬性,這樣就可以在每次重繪視圖內容的時候,獲取當前的幀圖像和追蹤信息。 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)
      }
}

相反,如果您的應用設計傾向于使用被動推送模式的話,那么請實現session(_:didUpdate:)代理方法,當每個視頻幀被捕獲之后,Session 就會調用這個代理方法(默認每秒捕獲 60 幀)。

獲得 個視頻幀之后,您就需要繪制相機圖像 ,然后將 AR 場景中包含的所有覆蓋物進行更新和展示 。

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

每個 ARFrame對象的 capturedImage屬性都包含 從設備相機中捕獲的像素緩沖區 (pixel buffer)。要將這個圖像作為背景繪制到自定義視圖當中,您需要從圖像內容中構建紋 (texture),然后提交使用這些紋理進行GPU 渲染的命令。

像素緩沖區的內容將被編碼為雙 (biplanar) YCbCr 數據格式(也成為 YUV);要渲染圖像的話,您需要將這些像素數據轉換為可繪制的 RGB 格式。對于 Metal 渲染 ,最高效的方法便是使用 GPU 著 代碼 (shader code) 來執行這個轉換 。借助CVMetalTextureCacheAPI,可以從像素緩沖區中生成兩個 Metal 紋理 —— 一個用于決定緩沖區的亮度 (Y),一個用于決定緩沖區的色度 (CbCr) 。

func updateCapturedImageTextures(frame: ARFrame) {
// Create two textures (Y and CbCr) from the provided frame's captured image //從所提供的視頻幀中,根據其中所捕獲的圖像,創建兩個紋  (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
  }

接下來,使用借助顏色變換矩陣將 YCbCr 轉換為 RGB 的函數片段,完成這兩個紋理的繪制,我們這里將整個渲染命令進行編碼

fragment float4 capturedImageFragmentShader(ImageColorInOut in [[stage_in]],
                                              texture2d<float, access::sample>
  capturedImageTextureY [[ texture(kTextureIndexY) ]],
                                              texture2d<float, access::sample>
  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;
  }

請使 用displayTransform(withViewportSize:orientation:) 法來確保整個相機圖像完全覆蓋 整 個視圖。關于如何使 這個方法,以及完整的 Metal 管道配置代碼,請參閱完整的 Xcode 模 板。(請使 “Augmented Reality” 模板來創建一個新的 iOS 應用 ,然后在彈出的 Content Technology 菜單當中選擇 “Metal”。)

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

AR 場景通常側重于渲染 3D 覆蓋物,使得這些內容似乎是從相機中所看到的真實世界的 部分。 為 實現這種效果,我們使 ARAnchor類,來對 3D 內容相對于現實世界空間的位置和方向進行建模。錨點提供 變換 (transform) 屬性,在渲染的時候可供參考。

舉個例子,當用戶點擊屏幕的時候,Xcode 模板會在設備前面約 20 厘米處,創建一個錨點。

 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)
} }

在您的渲染引擎當中,使用每個 ARAnchor對象的 transform屬性來放置虛擬內容。Xcode 模板 在內部的 handleTap 方法中,使用添加到 Session 當中每個錨點來定位一個簡單的立方體網格 (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..<anchorInstanceCount {
          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
      }
}

在更為復雜的 AR 場景中,您可以使用點擊測試或者水平面檢測,來尋找真實世界當中曲面的位 置。要了解關于此內容的詳細信息,請參閱 planeDetection屬性和hitTest(_:types:) 法。對于這 兩者 ,ARKit 都會生成 ARAnchor對象作為結果,因此您仍然需要使用錨點的 transform 屬性來放置虛擬內容。

Render with Realistic Lighting(根據實際光照度進行渲染)

當您在場景中配置用于繪制 3D 內容的著色器時,請使用每個 ARFrame對象當中的預計光照度信息,來產生更為逼真的陰影:

// 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 配置,以及所使用的渲染命令,請參見完整的 Xcode 模板。(請使用 “Augmented Reality” 模板來創建一個新的 iOS 應用,然后在彈出的 Content Technology 菜單當中選擇 “Metal”。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容