本系列文章是對 http://metalkit.org 上面MetalKit內容的全面翻譯和學習.
MetalKit 框架是在 WWDC 2015 上發(fā)布的,它給原Metal框架帶來了大量改進和新特性.認識 MTKView, NSView/UIView
的一個子類. 它內置了一個Metal layer層,也同時管理著幀緩沖器framebuffer及其渲染目標附件render target attachments,還管理著繪制循環(huán)draw loop.
讓我們創(chuàng)建一個Cocoa Application
(因為iOS
模擬器不支持Metal
).確保只有Swift
和Use Strotyboards
區(qū)域是選中狀態(tài).接下來,創(chuàng)建一個新的類,名為MetalView.swift繼承于NSView
(暫時).然后,到storyboard中選中View Controller
下面的View
,設置Identity Inspector
中的類為MetalView
類型,如下圖.
對View Controller
也是同樣操作,刪除Identity Inspector
中Class
下面的View Controller
,因為我們用不到它.刪除ViewController.swift
因為我也不需要它了.現在回到MetalView.swift
文件中,輸入import MetalKit.有兩種方法可以讓我們的類支持繪制:遵守MTKViewDelegate
協(xié)議并實現它的drawInView(:)
方法,或者繼承MTKView
并重寫它的drawRect(:)
方法.這里我們選擇后者,所以將類的類型從NSView
改為MTKView,并創(chuàng)建一個新方法名為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()
}
讓我們一行一行來細看這些代碼.首先,我們創(chuàng)建一個device.我們將其設置為我們view的屬性device
,否則該屬性為nil
程序會崩潰.作為一個可選項,我們可以在繪制之前修改view的drawable
屬性.接著,創(chuàng)建一個render pass descriptor(渲染通道描述符)以便我們配置渲染通道為current drawable’s texture
附著上初始顏色.為了有趣一點,我們創(chuàng)建一個很棒的顏色,由一半藍色一半綠色組成,叫bleen.最后,我們使用命令緩沖器來創(chuàng)建render command encoder來執(zhí)行繪制命令.對于每個繪制循環(huán),當currentRenderPassDescriptor
查詢時,創(chuàng)建一個新的MTLRenderPassDescriptor
對象.這個對象是基于currentDrawable
對象創(chuàng)建的.畫面顯示并不是MTKView
處理的,所以我們必須自己先檢查currentRenderPassDescriptor
和currentDrawable
都為為nil
,然后再調用presentDrawable(:)
方法.
讓我們參考一下Metal 文檔中的細節(jié).Metal
框架包含若干對象:
-
device設備
-對GPU
的抽象,處理命令隊列中的渲染和計算命令 -
command queue命令隊列
-一個命令緩沖器的串行隊列,確保儲存的命令按順序執(zhí)行 -
command buffer命令緩沖器
-儲存從命令編碼器中編譯出的指令.當能問執(zhí)行完所有命令后Metal會通知應用程序. -
command encoder命令編碼器
-將API
命令編譯成GPU
硬件命令-共有三種類型的編碼器:render
(供圖形渲染),compute
(供數據并行處理)及blit
(供資源復制操作).目前我們只需關注render command encoder渲染命令編碼器
-
states狀態(tài)
-例如混合和深度 -
shaders著色器
-源碼 -
resources資源
-紋理和數據緩沖器
我們在本系列的下一節(jié)中將討論最后3個對象.當前我們只關注device
,queue
,buffer
和encoder
.Render Command Encoder (RCE)渲染命令編碼器
為每一個單獨的渲染通道提供硬件命令,這意味著所有的渲染都被送入一個單一的framebuffer幀緩沖器
對象中(目標集合中).如果另一個幀緩沖器需要被渲染,會創(chuàng)建一個新的RCE.RCE會為從graphics popeline圖形管線
中給出的vertex頂點
和fragment片段
確定狀態(tài),并且插入resources
,state changes
和draw calls
.利用RCE
的一個優(yōu)點是無需繪制時編譯;應用可以決定編譯和狀態(tài)檢查何時發(fā)生,這樣為程序員提供了很大的性能優(yōu)勢.
讓我們再回到我們的代碼.在drawRect(:)方法中調用render()
方法:
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
render()
}
如果你運行應用,你將會看到一個漂亮的,純粹的bleen-ish
屏幕:
在下一節(jié)中,我們終于開始介紹shaders
,加載textures
及管理model data模型數據
.代碼 source code 發(fā)布于Github
上.
下次見!