本系列文章是對 metalkit.org 上面MetalKit內容的全面翻譯和學習.git
MetalKit 框架是在 WWDC 2015 上發佈的,它給原Metal框架帶來了大量改進和新特性.認識 MTKView, NSView/UIView
的一個子類. 它內置了一個Metal layer層,也同時管理着幀緩衝器framebuffer及其渲染目標附件render target attachments,還管理着繪製循環draw loop.github
讓咱們建立一個Cocoa Application
(由於iOS
模擬器不支持Metal
).確保只有Swift
和Use Strotyboards
區域是選中狀態.接下來,建立一個新的類,名爲MetalView.swift繼承於NSView
(暫時).而後,到storyboard中選中View Controller
下面的View
,設置Identity Inspector
中的類爲MetalView
類型,以下圖. swift
對View Controller
也是一樣操做,刪除Identity Inspector
中Class
下面的View Controller
,由於咱們用不到它.刪除ViewController.swift
由於我也不須要它了.如今回到MetalView.swift
文件中,輸入import MetalKit.有兩種方法可讓咱們的類支持繪製:遵照MTKViewDelegate
協議並實現它的drawInView(:)
方法,或者繼承MTKView
並重寫它的drawRect(:)
方法.這裏咱們選擇後者,因此將類的類型從NSView
改成MTKView,並建立一個新方法名爲render()
,內容以下:app
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
處理的,因此咱們必須本身先檢查currentRenderPassDescriptor
和currentDrawable
都爲爲nil
,而後再調用presentDrawable(:)
方法.框架
讓咱們參考一下Metal 文檔中的細節.Metal
框架包含若干對象:ide
device設備
-對GPU
的抽象,處理命令隊列中的渲染和計算命令command queue命令隊列
-一個命令緩衝器的串行隊列,確保儲存的命令按順序執行command buffer命令緩衝器
-儲存從命令編碼器中編譯出的指令.當能問執行完全部命令後Metal會通知應用程序.command encoder命令編碼器
-將API
命令編譯成GPU
硬件命令-共有三種類型的編碼器:render
(供圖形渲染),compute
(供數據並行處理)及blit
(供資源複製操做).目前咱們只需關注render command encoder渲染命令編碼器
states狀態
-例如混合和深度shaders着色器
-源碼resources資源
-紋理和數據緩衝器咱們在本系列的下一節中將討論最後3個對象.當前咱們只關注device
,queue
,buffer
和encoder
.Render Command Encoder (RCE)渲染命令編碼器
爲每個單獨的渲染通道提供硬件命令,這意味着全部的渲染都被送入一個單一的framebuffer幀緩衝器
對象中(目標集合中).若是另外一個幀緩衝器須要被渲染,會建立一個新的RCE.RCE會爲從graphics popeline圖形管線
中給出的vertex頂點
和fragment片斷
肯定狀態,而且插入resources
,state changes
和draw calls
.利用RCE
的一個優勢是無需繪製時編譯;應用能夠決定編譯和狀態檢查什麼時候發生,這樣爲程序員提供了很大的性能優點.oop
讓咱們再回到咱們的代碼.在drawRect(:) 方法中調用render()
方法:post
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
render()
}
複製代碼
若是你運行應用,你將會看到一個漂亮的,純粹的bleen-ish
屏幕: 性能
在下一節中,咱們終於開始介紹shaders
,加載textures
及管理model data模型數據
.代碼 source code 發佈於Github
上.
下次見!