[MetalKit]2-Using-MetalKit-part-1使用MetalKit1

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

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

MetalKit系統文章目錄


MetalKit 框架是在 WWDC 2015 上釋出的,它給原Metal框架帶來了大量改進和新特性.認識 MTKView, NSView/UIView的一個子類. 它內建了一個Metal layer層,也同時管理著幀緩衝器framebuffer及其渲染目標附件render target attachments,還管理著繪製迴圈draw loop.

讓我們建立一個Cocoa Application(因為iOS模擬器不支援Metal).確保只有SwiftUse Strotyboards區域是選中狀態.接下來,建立一個新的類,名為MetalView.swift繼承於NSView(暫時).然後,到storyboard中選中View Controller下面的View,設定Identity Inspector中的類為MetalView型別,如下圖.

chapter02-1.png

View Controller也是同樣操作,刪除Identity InspectorClass下面的View Controller,因為我們用不到它.刪除ViewController.swift因為我也不需要它了.現在回到MetalView.swift檔案中,輸入import MetalKit.有兩種方法可以讓我們的類支援繪製:遵守MTKViewDelegate協議並實現它的drawInView(:)方法,或者繼承MTKView並重寫它的drawRect(:)方法.這裡我們選擇後者,所以將類的型別從NSView改為MTKView,並建立一個新方法名為render(),內容如下:

func render() {
    let device = MTLCreateSystemDefaultDevice()!
    self.device = device
    let rpd = MTLRenderPassDescriptor()
    let bleen = MTLClearColor(red: 0, green: 0.5, blue: 0.5, alpha: 1)
    rpd.colorAttachments[0].texture = currentDrawable!.texture
    rpd.colorAttachments[0].clearColor = bleen
    rpd.colorAttachments[0].loadAction = .Clear
    let commandQueue = device.newCommandQueue()
    let commandBuffer = commandQueue.commandBuffer()
    let encoder = commandBuffer.renderCommandEncoderWithDescriptor(rpd)
    encoder.endEncoding()
    commandBuffer.presentDrawable(currentDrawable!)
    commandBuffer.commit()
}
複製程式碼

讓我們一行一行來細看這些程式碼.首先,我們建立一個device.我們將其設定為我們view的屬性device,否則該屬性為nil程式會崩潰.作為一個可選項,我們可以在繪製之前修改view的drawable屬性.接著,建立一個render pass descriptor(渲染通道描述符) 以便我們配置渲染通道為current drawable’s texture附著上初始顏色.為了有趣一點,我們建立一個很棒的顏色,由一半藍色一半綠色組成,叫bleen.最後,我們使用命令緩衝器來建立render command encoder來執行繪製命令.對於每個繪製迴圈,當currentRenderPassDescriptor查詢時,建立一個新的MTLRenderPassDescriptor物件.這個物件是基於currentDrawable物件建立的.畫面顯示並不是MTKView處理的,所以我們必須自己先檢查currentRenderPassDescriptorcurrentDrawable都為為nil,然後再呼叫presentDrawable(:)方法.

讓我們參考一下Metal 文件中的細節.Metal框架包含若干物件:

  • device裝置-對GPU的抽象,處理命令佇列中的渲染和計算命令
  • command queue命令佇列-一個命令緩衝器的序列佇列,確保儲存的命令按順序執行
  • command buffer命令緩衝器-儲存從命令編碼器中編譯出的指令.當能問執行完所有命令後Metal會通知應用程式.
  • command encoder命令編碼器-將API命令編譯成GPU硬體命令-共有三種型別的編碼器:render(供圖形渲染),compute(供資料並行處理)及blit(供資源複製操作).目前我們只需關注render command encoder渲染命令編碼器
  • states狀態-例如混合和深度
  • shaders著色器-原始碼
  • resources資源-紋理和資料緩衝器

我們在本系列的下一節中將討論最後3個物件.當前我們只關注device,queue,bufferencoder.Render Command Encoder (RCE)渲染命令編碼器為每一個單獨的渲染通道提供硬體命令,這意味著所有的渲染都被送入一個單一的framebuffer幀緩衝器物件中(目標集合中).如果另一個幀緩衝器需要被渲染,會建立一個新的RCE.RCE會為從graphics popeline圖形管線中給出的vertex頂點fragment片段確定狀態,並且插入resources,state changesdraw calls.利用RCE的一個優點是無需繪製時編譯;應用可以決定編譯和狀態檢查何時發生,這樣為程式設計師提供了很大的效能優勢.

讓我們再回到我們的程式碼.在drawRect(:) 方法中呼叫render()方法:

override func drawRect(dirtyRect: NSRect) {
    super.drawRect(dirtyRect)
    render()
}
複製程式碼

如果你執行應用,你將會看到一個漂亮的,純粹的bleen-ish螢幕:

chapter02-2.png

在下一節中,我們終於開始介紹shaders,載入textures及管理model data模型資料.程式碼 source code 釋出於Github上.

下次見!

相關文章