Scene Kit (翻譯)

前言

Scene Kit(SK)是WWDC12推出OS X平臺的屬於Cocoa類的3D渲染引擎框架。初版已經有不錯了而且後續又增長了一些強大的功能好比着色修改,限制。當蘋果推出新系統Mavericks時又增長了骨架動畫。今年,SK變得更增強大了,新增支持粒子效果,物理模擬,腳本事件,多程渲染,最重要得是支持iOS平臺。node

從一開始,我就發現SK最強大與區別是它與其餘圖形處理框架的整合,好比CI,CA還有SK。這意味着除了遊戲工程師外一些有興趣遊戲開發的Cocoa開發也能對SK立刻上手。swift

SK基礎

SK以OpenGL爲基石,對外開放高級API,你能夠用OC或者swift建立出光,幾何圖形,物質,還有攝像機對象。若是你用過OpenGL早先沒有着色器的版本,那估計會讓你想起那段關於被系統限制而不能方便配置的很差的記憶。幸運的是,如今不會在這樣了。高級配置對於大部分通常得任務已經足夠了-甚至是更高級的東西好比動態着色還有層次效果。數組

甚至,SK還可讓你調用低級接口去調用OpenGL着色代碼去進行渲染(GLSL)。框架

結點

除去光,幾何體,物質還有相機,SK使用了節點層級來組織自身的內容。每一個節點都包含位置,旋轉度,還有相對父節點的縮放度,反過來也關聯自身的父節點,如此特性遞歸到根節點。爲了給其餘對象中的某個一個3D座標,每一個節點被鏈接到節點羣的某一個節點上。節點層級用以下的方法管理:ide

addChildNode(_:)
insertChildNode(_: atIndex:)
removeFromParentNode()

如同iOS以及OS X中管理視圖層級的方式同樣。測試

幾何學對象

SK提出內置簡單形狀幾何學對象好比像箱子,球體,飛機,圓錐體,對於遊戲來講,大部分你要作的就是從一個文件中載入3D模型。你能夠導入或者導出COLLADA文件採起關聯文件名的方式引用文件:動畫

let chessPieces = SCNScene(named: "chess pieces") // SCNScene?

若文件所包含得場景須要被徹底展現,那它能夠做爲整個場景視圖的場景。若是場景包含許多對象,而且這些對象只有部分是須要展現在屏幕上的,那麼他們能夠經過名字索引找到,能夠將他們加入場景而且在場景視圖中進行渲染。編碼

if let knight = chessPieces.rootNode.childNodeWithName("Knight", recursively: true) {
    sceneView.scene?.rootNode.addChildNode(knight)
}

在導入文件的原始結點和包含着其餘任一或者全部得子結點,包括附帶了幾何體對象,光,攝像機。搜尋一樣名字的子結點會指向一個相對的對象。人工智能

這裏有圖。。spa

當一個場景有多個模型拷貝的時候,好比,爲了展現兩個其實在國際象棋的棋盤上,你會拷貝結點或者克隆(遞歸拷貝)它。這樣這份結點的拷貝引用了同一個物質幾何體對象。涼粉拷貝都指向了同一個幾何體對象。因此改變一個物質,這個幾何體對象將也不得不被拷貝而且擁有一個新的物質依附在它身上。拷貝一個幾何體對象比較迅速而且代價較小,由於拷貝仍是指向了同一份頂點數據。

根據操縱骨動畫集合體對象導入的結點有一個皮膚對象用來提供訪問骨架結點層級喝用來管理骨頭喝幾何體對象的關係。個別的骨頭能夠被移動和旋轉;可是,更復雜的動畫會改變多個骨頭-舉個栗子, a character’s walk cycle - 更多是從一個文件加載並加到對象中去。

SK中的光是徹底動態的。這使得他們更容易被獲取而且更易於使用,可是一樣意味着SK提供的光源跟一個完整功能的遊戲引擎比起來不夠先進。這裏有四種不一樣的光:周圍光,指向性光,點光,聚光。

在不少狀況下,特定一個旋轉座標系和一個角度並非最感知的方法去識別一個物體上的光。在這些狀況下,這個給出光得結點的位置喝朝向可以經過另一個結點進行限制。添加一個「look at」-約束一位置這束光線將會一直指向這個結點,及時結點移動了。

let spot = SCNLight()
spot.type = SCNLightTypeSpot
spot.castsShadow = true

let spotNode = SCNNode()
spotNode.light = spot
spotNode.position = SCNVector3(x: 4, y: 7, z: 6)

let lookAt = SCNLookAtConstraint(target: knight)
spotNode.constraints = [lookAt]

動畫

SK中任意對象任意屬性都是可動畫的。就想Cocoa,這意味着你須要建立一個CAAnimation關鍵路徑(哪怕是「position.x」)並添加到動畫對象。相似的,你能夠改變你動畫相關得值在SCNTransaction動做「begin」與「commit」。上述兩種方式十分相同,毫無二致。

let move = CABasicAnimation(keyPath: "position.x")
move.byValue  = 10
move.duration = 1.0
knight.addAnimation(move, forKey: "slide right")

SK一樣支持Sprite Kit動做方式的動畫API。這就容許你去建立一串動畫而後調用自定義的block代碼與其餘動畫同時運行,這些動做做爲遊戲循環的一部分,而且每一幀都進行更新數據層值,而不只僅是表象層結點。

事實上,若是你曾經使用過Sprite Kit,那你對SK將有似曾相識的感受,不一樣的是此次是3D世界。在iOS8和OS X 10.10,上述兩個框架能夠一塊兒協做。在使用Sprite Kit的時候,2D能夠混雜3D模型一塊兒使用。在使用SK開發的時候,Sprite Kit的場景以及紋理能夠被用做SK的紋理,而且Sprite Kit場景能夠被用做一種2D覆蓋在SK場景之上。

使用SK寫遊戲

動做跟紋理並非Scene KitSprite Kit惟一共同的東西。當使用SK進行遊戲編碼的時候,這種感受與2D框架是很是類似的。在上述兩種開發框架下,遊戲輪迴有以下同樣的步驟,同樣的代理回調。

  1. 更新場景
  2. 運行動畫/動做
  3. 仿真物理
  4. 執行約束
  5. 渲染

請看輪迴方向 ->
圖片描述
每一幀都有一個回調而且用來執行遊戲運行相關的邏輯好比像輸入源句柄,人工智能,或者是遊戲劇本。

輸入源句柄

SK使用相同的輸入機制,例如鍵盤事件,鼠標事件,點擊事件,還有Cocoa與Cocoa Touch產品中手勢識別,主要的不一樣是這裏只有一個視圖那就是場景視圖。對於鍵盤事件或者縮放,快滑,旋轉手勢,它可能僅僅是知道這些事件發生了,可是好比點擊或者長按拖動,此類事件則須要更多的信息。

對於這些狀況,場景視圖須要使用-hitTest(_: options:)來進行點擊測試。與一般視圖以及圖層不一樣的是(只返回點擊的子視圖或者子圖層),SK中返回的是有交點幾何體對象以及攝像機穿過該點的射線的數組。每個點擊結果包含着點擊幾何體歸屬結點,還有交點的詳細信息(點擊座標,紋理座標)。大多數情形,這些信息足夠知道了所觸碰的第一個結點是:

if let firstHit = sceneView.hitTest(tapLocation, options: nil)?.first as? SCNHitTestResult {
    let hitNode = firstHit.node
    // do something with the node that was hit...
}

默認渲染擴展

光,材質配置,雖然容易協同工做,可是也只能讓你走這麼遠(限制你)。若是你已經用上了OpenGL的着色器,你能夠用其進行渲染來配置材質,進而作到徹底的自定義。而後,若是你只是想修改默認的渲染,SK剔除四點能夠將着色器代碼片斷(GLSL)注入到默認的渲染代碼中。在不一樣的切入點,SK提供了數據入口例如變換矩陣,幾何體數據,紋理示例,還有渲染顏色輸出。

舉個栗子,在入口點的數行着色器代碼片斷能夠被用來扭曲幾何體對象X軸方向全部的點。能夠經過定義一個方程去建立一個渲染變換並把這個變換應用到這些X軸點和幾何體的正常化。一樣也能夠定義一個「不變」變量來決定物體的扭曲度:

// a function that creates a rotation transform matrix around X
mat4 rotationAroundX(float angle)
{
    return mat4(1.0,    0.0,         0.0,        0.0,
                0.0,    cos(angle), -sin(angle), 0.0,
                0.0,    sin(angle),  cos(angle), 0.0,
                0.0,    0.0,         0.0,        1.0);
}

#pragma body

uniform float twistFactor = 1.0;
float rotationAngle = _geometry.position.x * twistFactor;
mat4 rotationMatrix = rotationAroundX(rotationAngle);

// position is a vec4
_geometry.position *= rotationMatrix;

// normal is a vec3
vec4 twistedNormal = vec4(_geometry.normal, 1.0) * rotationMatrix;
_geometry.normal   = twistedNormal.xyz;

着色修改器能夠被依附到任意個幾何體對象上或是其下的人一個材質上。上述兩個類都是支持KVC,這意味着你能夠爲任意的Keys設置值。在着色修改器中已經聲明瞭「扭曲因子」使SK觀察Key和重綁定的不變值任什麼時候候只要值發生變化。便可以使用KVC進行簡單得改變屬性值:

torus.setValue(5.0, forKey: "twistFactor")

一樣能夠靠建立一個CAAnimation來獲取關鍵路徑:

let twist = CABasicAnimation(keyPath: "twistFactor")
twist.fromValue = 5
twist.toValue   = 0
twist.duration  = 2.0

torus.addAnimation(twist, forKey: "Twist the torus")

圖片描述

延遲着色

有些圖形效果不能在一次的渲染過程當中達成,即便是純OpenGL。解決方案是序列化不一樣的着色器操做來進行預處理操做或者延遲着色。SK在這種處理技術上使用的是SCNTechnique類。它建立一個字典來定義繪畫過程,輸入輸出,着色文件,符號等等。

第一步一般是SK默認渲染,輸出源是顏色和場景的層級深度。若是你不想顏色被着色,材質能夠被設置常量光模型,或者場景中的全部光能夠被替代成單一週圍光。

舉個栗子,經過SK初始值傳參以及二次傳參的天然值獲取深度,同時在第三次傳參的時候對兩者進行邊緣探測,你能夠在沿着大綱略圖和邊緣畫出清晰的輪廓:

圖片描述

相關文章
相關標籤/搜索