[MetalKit]9-Using-MetalKit-part-8使用MetalKit8

蘋果API搬運工發表於2017-12-14

本系列文章是對 metalkit.org 上面MetalKit內容的全面翻譯和學習.

MetalKit系統文章目錄


現在,你可以注意到我很喜歡Swift.同時我也是個Xcodeplaygrounds的狂熱愛好者.本週我們會把我們的Metal程式碼放到playground中.歡呼吧,為了playgrounds中的Metal原型!

讓我們從建立一個新的OS XXcodeplayground開始.建立好後,單擊Show the Assistant editor按鈕並按下Command + 1顯示Project navigator導航區.你的playground看起來應該這樣:

chapter08_1.png

第一件事就是在Project navigator中的Resources資料夾下建立Shaders.metal,程式碼和本系列前一章節保持一致.然後,我們在Sources資料夾下建立MathUtils.swiftMetalView.swift.惟一要改動的地方是在MathUtils.swift中為Vertex結構體建立一個初始化方法:

struct Vertex {
    var position: vector_float4
    var color: vector_float4
    init(pos: vector_float4, col: vector_float4) {
        position = pos
        color = col
    }
}
複製程式碼

MetalView.swift中我們需要改的多一些.首先,我們要讓類是public,因為我們將在Sources資料夾外呼叫它.因此,初始化方法和drawRect(:) 方法也必須是public的.同時,我們再建立第二個初始化方法,這樣我們就可能建立一個指定frameMetalView了:

public class MetalView: MTKView {
    ... 
    required public init(coder: NSCoder) {
        super.init(coder: coder)
    }

    override public init(frame frameRect: CGRect, device: MTLDevice?) {
        super.init(frame: frameRect, device: device)
        createBuffers()
        registerShaders()
    }
    ... 
}
複製程式碼

下一步,我們需要做一些奇妙的改動,建立一個Library:

let library = device.newDefaultLibrary()!
複製程式碼

提示錯誤資訊:

MTLLibrary.mm:1016: failed assertion `filepath must not be nil.'
複製程式碼

這是因為playground沒有預設的filepath來給我們使用,我們需要自己建立:

func registerShaders() {
    let path = NSBundle.mainBundle().pathForResource("Shaders", ofType: "metal")
    let input: String?
    let library: MTLLibrary
    let vert_func: MTLFunction
    let frag_func: MTLFunction
    do {
        input = try String(contentsOfFile: path!, encoding: NSUTF8StringEncoding)
        library = try device!.newLibraryWithSource(input!, options: nil)
        vert_func = library.newFunctionWithName("vertex_func")!
        frag_func = library.newFunctionWithName("fragment_func")!
        let rpld = MTLRenderPipelineDescriptor()
        rpld.vertexFunction = vert_func
        rpld.fragmentFunction = frag_func
        rpld.colorAttachments[0].pixelFormat = .BGRA8Unorm
        rps = try device!.newRenderPipelineStateWithDescriptor(rpld)
    } catch let e {
        Swift.print("\(e)")
    }
}
複製程式碼

注意,我們告訴playground去找到名為Shaders型別為metal的資源的存放路徑.然後,我們將檔案轉換為一個長的String並用這些資源建立library.

最後,我們到playground的主頁並建立一個帶有frame的MetalView.然後我們告訴playground展示活躍檢視:

import Cocoa
import XCPlayground

let device = MTLCreateSystemDefaultDevice()!
let frame = NSRect(x: 0, y: 0, width: 300, height: 300)
let view = MetalView(frame: frame, device: device)
XCPlaygroundPage.currentPage.liveView = view
複製程式碼

如果你顯示了Assistant editor區的Timeline,你會看到一個類似的檢視:

chapter08_2.png

原始碼source code 已釋出在Github上.

下次見!

相關文章