14-《ARKit by Tutorials》讀書筆記1:開始入門

說明

ARKit系列文章目錄node

本文是Ray Wenderlich上《ARKit by Tutorials》的讀書筆記,主要講內容概要和讀後感  swift

ARKit的主要特色:

  • 追蹤
  • 場景理解
  • 光照估計
  • 場景交互
  • 公制計量單位
  • 渲染集成

ARKit的主要侷限性:session

  • 平面檢測須要花費必定時間
  • 動做處理滯後:不能運動過快
  • 低光照條件
  • 光滑無紋理平面
  • 幽靈穿透效果:不能正確處理遮擋效果

Xcode已經集成了AR項目的建立入口,直接能夠建立一個自帶小飛機的AR工程.

項目組織和管理

文件中的代碼組織

  • Properties: 類的屬性.
  • Outlets: xib上的元素.
  • Actions: 執行的動做.
  • View Management: 視圖生命週期等方法.
  • Initialization: 初始化方法.
  • ARSCNViewDelegate 協議extension:AR代理方法

session控制

  • Pausing:ARSession.pause()能夠用來暫停會話.
  • Resuming:ARSession.run()可恢復一個暫停的session.
  • Updating:ARSession.run(ARSessionConfig)能夠更新配置項.
  • Resetting: ARSession.run(_:options:)能夠重置session. 當session狀態改變時,能夠在代理方法中處理:
func session(_ session: ARSession, 
  cameraDidChangeTrackingState camera: ARCamera) {
  switch camera.trackingState {
    // 1
    case .notAvailable:
      trackingStatus = "Tracking:  Not available!"
    // 2  
    case .normal:
      trackingStatus = "Tracking: All good!"
    // 3 
    case .limited(let reason):
      switch reason {
        case .excessiveMotion:
          trackingStatus = "Tracking: Limited due to 
            excessive motion!"
        // 3.1  
        case .insufficientFeatures:
          trackingStatus = "Tracking: Limited due to 
            insufficient features!"
        // 3.2
        case .initializing:
          trackingStatus = "Tracking: Initializing..."
        // 3.3
        case .relocalizing:
          trackingStatus = "Tracking: Relocalizing..."
        }
    }
  }
}
複製代碼

調試選項

能夠打開AR視圖的debug選項來幫助調試:app

sceneView.debugOptions = []
複製代碼

可配置項以下:async

  • Feature points:顯示檢測到的特徵點.
  • World origin:紅綠藍三色線交叉組成的世界座標原點.
  • Bounding boxes:3D物體的邊界盒.
  • Wireframe:3D物體線框圖.

着色器,材質和紋理

在SceneKit中可用的光照模型(着色器)以下: ide

材質是2D圖片,能夠包裹在3D幾何體周圍提供特殊屬性,好比color顏色, specularity高光, reflectivity反射率, shininess發光率, roughness粗糙度, metalness金屬度 甚至transparency透明度.
具體能夠看我之前寫的SceneKit系列文章 Lights燈光, Materials材質, Shadows陰影

基於物理的渲染(PBR)

PBR光照模型是新引入的特性,可讓你的3D物體看起來更真實.工具

下面咱們來重點學習一下其中的特性:post

Environment map環境貼圖

環境貼圖是一種cube map立方體貼圖,好比天空盒子shybox是這樣的: 學習

SceneKit還支持其它類型的立方體貼圖:

環境貼圖有兩方面做用:一方面相似於reflection map反射貼圖,能夠在高反射率表面看到環境圖像的反射;另外一方面,對於支持PBR的3D物體,能夠提供真實的光照環境.以下: 測試

Diffuse map漫反射貼圖

漫反射貼圖提供基礎顏色,無需考慮燈光和其它特效.

須要注意的是,漫反射貼圖能夠經過圖片的alpha通道來指定透明度.好比在地球外面再包層大氣雲層圖,你只能看到大氣層的不透明部分.

Normal map法線貼圖

所謂法線,就是垂直於幾何體表面的向量.能夠用來計算光線的反射等效果.

法線貼圖經過圖片的RGB通道來定義了像素級的表面法線.用來與光線混合計算,模擬表面的凹凸效果.這樣無需增長多邊形及頂點數據,就模擬出了真實的表面.

Height map高度貼圖

高度貼圖並非PBR光照模型的一部分,可是也值得你們學習.高度貼圖是黑白圖像,白色表明物體的最高點,黑色表明最低點.

高度貼圖和法線貼圖能夠互相轉換,網上有免費工具Normal Map Online — available at bit.ly/1ELCePX

Occlusion map閉塞貼圖

也就是ambient occlusion map環境光閉塞貼圖(OA貼圖).用來阻止環境光照亮閉塞的區域,好比牆壁上的裂縫裏.黑白貼圖,黑色表明不可照亮,白色表明能夠照亮.

Emission map發光貼圖/發射貼圖

定義了光照和陰影來製造一種發光效果.例如地球黑夜的燈光(須要關閉光照.PBR下停用環境貼圖):

Self-illumination map自發光貼圖

自發光貼圖在其它全部效果以後才應用;能夠用來給最終效果上色,增亮或變暗

Displacement map位移貼圖

在法線貼圖中,咱們能夠在光滑表面創造出像素級的不一樣高度,但它只是幻像,只是改變了光線的反射而已.

在位移貼圖中,咱們能夠真正地改變表面地形.灰色到白色表示凸起,灰色到黑色表示凹陷:

Metalness and roughness maps金屬度和粗糙度貼圖

PBR的主要特性就是可以展現出可見的微觀細節,就是用金屬度和粗糙度貼圖來實現的:

  • 金屬度:從後往前,逐漸加強.
  • 粗糙度:從左到右,逐漸加強.

Metalness map金屬度貼圖

金屬度模擬了物體表面的屬性,如反射,折射和菲涅耳反射.該灰度紋理中,黑色表明非金屬,白色表明金屬性表面:

Roughness map粗糙度貼圖

粗糙度貼圖模擬了真實世界表面的微觀細節.產生明亮或暗淡的外觀.該灰度紋理中,黑色表明最粗糙,白色表明最光滑表面:

Detect plane表面檢測

Anchor錨點

錨點是3D物體的參考點,和UIView中的anchor錨點相似.對3D物體應用的transform變換也是相對於錨點的.

添加了新錨點

當平面檢測發現平面時,會添加一個錨點,並建立一個SCNNode,並調用代理方法:

// 1
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
  // 2
  guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
  // 3
  DispatchQueue.main.async {
    // 4
    let planeNode = self.createARPlaneNode(
      planeAnchor: planeAnchor,
      color: UIColor.yellow.withAlphaComponent(0.5))
     // 5
     node.addChildNode(planeNode)
  }
}
複製代碼

錨點更新

當錨點更新時,也會調用代理方法:

// 1
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
  // 2
  guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
    // 3
    DispatchQueue.main.async {
      // 4
      self.updateARPlaneNode(planeNode: node.childNodes[0],
        planeAchor: planeAnchor)
    }
}

複製代碼

Physics物理效果

Physics body物理形體

首先要了解的是就是physics body物理形體的概念:

  • static body:靜態形體,在物理模擬中能夠與其它物體發生做用,但自身不受影響,始終在原來位置上.如牆壁.
  • dynamic body:動態形體,在物理模擬中徹底由物理引擎控制並能夠與其它物理形體發生做用.如小球.
  • kinematic body:動力學形體,在物理模擬中不受物理引擎控制,但能夠經過代碼來移動.如電梯.

Physics body type物理形體的形狀

還有SceneKit內置的物體形狀:

並可調節各個參數:

還能夠調整整個場景的物理效果速度及物理模擬幀數:

scene.physicsWorld.speed = 0.05 //效果就像慢鏡頭

scene.physicsWorld.timeStep = 1.0 / 60.0 //每秒60幀;若是物體運動速度過快,須要增長幀數以提升精度,但也會提升CPU的負載.
複製代碼

Force力

力使用3維向量SCNVector3表示,使用applyForce(_: atPosition: impluse:)方法來添加一個力,並指定位置.一個力能夠同時影響線速度和角速度. impluse脈衝狀只做用一次,好比踢一個球,非脈衝狀的則能夠持續做用. Position位置能夠影響力的做用效果

更多物理效果相關內容,能夠參考physics物理效果

燈光和陰影

在AR中給物體添加陰影通常有兩種方法:

  • 在物體下面放上一塊淺灰紋理的平面,這樣彷彿就有了陰影.這也就是所謂的將光照和陰影"烘焙"進紋理中.
  • 在物體下面放一塊平面,並將平面的Reflectivity設置爲0;再添加一個光源,並將光源的Mode改成Deferred,這樣就能產生實時的陰影了.

同時文章中還提供了,如何用代碼來禁止某個物體寫入顏色緩衝區.

func hideARPlaneNodes() {
    // 1
    for anchor in
      (self.sceneView.session.currentFrame?.anchors)! {
      // 2 
      if let node = self.sceneView.node(for: anchor) {
        // 3
        for child in node.childNodes {
          // 4
          let material = child.geometry?.materials.first!
          material?.colorBufferWriteMask = []
        }
      }
    }
}
複製代碼

更多相關內容能夠看我之前寫的SceneKit系列文章Lights燈光, Shadows陰影以及官方Demo解讀中關於陰影的官方解讀蘋果官方AR變色龍Demo解讀

Hit testing命中測試

命中測試能夠用來提供與3D物體的交互

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
  DispatchQueue.main.async {
    // 1
    if let touchLocation = touches.first?.location(
      in: self.sceneView) {
      // 2
      if let hit = self.sceneView.hitTest(touchLocation,
        options: nil).first {
        // 3
        if hit.node.name == "dice" {
          // 4
          hit.node.removeFromParentNode()
          self.diceCount += 1
        }
      }
    }
  }
}
複製代碼

第一部分讀書筆記結束!

相關文章
相關標籤/搜索