本系列文章是對 metalkit.org 上面MetalKit內容的全面翻譯和學習.html
讓咱們來看看新的MetalKit
框架和之前的Metal
框架有什麼不一樣.它們是同時共存的,可是,MetalKit
引入了一些強勁的新特性,好比:git
紋理
更容易加載(只需幾行代碼就能夠異步加載).Model I/O
網格mash和Metal
緩衝器buffer之間的高效數據傳輸.MTKView
-一個方便的Metal-aware Metal認識的
視圖(咱們稍後會深刻研究它).我將從回顧第一篇中的程序開始:github
import MetalKit
class MetalView: MTKView {
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
render()
}
func render() {
device = MTLCreateSystemDefaultDevice()
if let rpd = currentRenderPassDescriptor, drawable = currentDrawable {
rpd.colorAttachments[0].clearColor = MTLClearColorMake(0, 0.5, 0.5, 1.0)
let command_buffer = device!.newCommandQueue().commandBuffer()
let command_encoder = command_buffer.renderCommandEncoderWithDescriptor(rpd)
command_encoder.endEncoding()
command_buffer.presentDrawable(drawable)
command_buffer.commit()
}
}
}
複製代碼
就是這樣!簡單優雅清理設備的背景色.如今咱們切換到Metal
框架,它並無MTKView
,因此咱們必須繼承於NSView
(iOS
上是UIView
).swift
import Cocoa
class MetalView: NSView {
複製代碼
你會直接注意到一些錯誤提示,顯示下面的屬性默認狀況下沒有提供給咱們:app
讓咱們修復這些錯誤.首先,由於NSView
不是Metal-aware Metal認識的
,咱們須要建立一個CAMetalLayer
並告訴NSView
將其用作本身的支持層.CAMetalLayer
是Core Animation
層,它管理着一個用來渲染內容的紋理池.爲了使用Metal
來渲染,咱們須要用這個類做爲咱們視圖的支持層,經過在視圖的layerClass() 類方法中返回圖層來實現:框架
override class func layerClass() -> AnyClass {
return CAMetalLayer.self
}
var metalLayer: CAMetalLayer {
return self.layer as! CAMetalLayer
}
複製代碼
接下來,在render() 函數中建立一個新的device
並告訴metalLayer去引用它,還要設置層使用的像素格式.而後,建立一個drawable
.注意,咱們並無使用MTKView
提供的currentDrawable
.而是,CAMetalLayer
提供了一個nextDrawable給咱們使用.最後,建立一個渲染通道描述符.仍是須要注意,咱們沒有提供currentRenderPassDescriptor
:異步
let device = MTLCreateSystemDefaultDevice()!
metalLayer.device = device
metalLayer.pixelFormat = .BGRA8Unorm
let drawable = metalLayer.nextDrawable()
let texture = drawable!.texture
let rpd = MTLRenderPassDescriptor()
複製代碼
在結束本章節以前,讓咱們看一下MTKView類,去看看爲何這是在咱們的app中用Metal
渲染內容的最佳方式:ide
@available(OSX 10.11, *)
public class MTKView : NSView, NSCoding {
public init(frame frameRect: CGRect, device: MTLDevice?)
public init(coder: NSCoder)
weak public var delegate: MTKViewDelegate?
public var device: MTLDevice?
public var currentDrawable: CAMetalDrawable? { get }
public var framebufferOnly: Bool
public var presentsWithTransaction: Bool
public var colorPixelFormat: MTLPixelFormat
public var depthStencilPixelFormat: MTLPixelFormat
public var sampleCount: Int
public var clearColor: MTLClearColor
public var clearDepth: Double
public var clearStencil: UInt32
public var depthStencilTexture: MTLTexture? { get }
public var multisampleColorTexture: MTLTexture? { get }
public func releaseDrawables()
public var currentRenderPassDescriptor: MTLRenderPassDescriptor? { get }
public var preferredFramesPerSecond: Int
public var enableSetNeedsDisplay: Bool
public var autoResizeDrawable: Bool
public var drawableSize: CGSize
public var paused: Bool
public func draw()
}
@available(OSX 10.11, *)
public protocol MTKViewDelegate : NSObjectProtocol {
public func mtkView(view: MTKView, drawableSizeWillChange size: CGSize)
public func drawInMTKView(view: MTKView)
}
複製代碼
在這一大堆屬性中,注意咱們感興趣的幾個:device, currentDrawable和currentRenderPassDescriptor. 另外一個值得注意的地方,是這個類提供了一個協議,MTKViewDelegate屬性.想要了解更多關於這些屬性和函數的知識,要去看MTKView的參考文檔.函數
源代碼source code 已發佈在Github上.
下次見!