寫在前面:
對(duì)Metal技術(shù)感興趣的同學(xué)众雷,可以關(guān)注我的專題:Metal專輯
也可以關(guān)注我個(gè)人的簡書賬號(hào):張芳濤
所有的代碼存儲(chǔ)的Github地址是:Metal
正文
我們來看看使用較新的MetalKit
框架與使用較早的Metal
框架之間有什么區(qū)別氮唯。 雖然它們?nèi)匀还泊娲趼ǎ荕etalKit引入了一些強(qiáng)大的功能揖膜,例如:
- 容易的
texture
紋理加載(甚至用幾行代碼進(jìn)行異步加載)。 -
Model I/O
網(wǎng)格和Metal
緩沖區(qū)之間高效的數(shù)據(jù)傳輸窖剑。 -
MTKView
- 一個(gè)方便的Metal-aware
視圖(后面會(huì)有更詳細(xì)的介紹)聪轿。
我將首先提醒你我們?cè)诘谝徽轮锌吹降某绦蚴鞘裁礃拥模?/p>
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()
}
}
}
就是這樣! 簡單和優(yōu)雅的方式來清除你的背景顏色到你選擇的自定義顏色涡扼。 現(xiàn)在讓我們切換到使用沒有MTKView
的Metal
框架稼跳,所以我們需要改為NSView
(或iOS
中的UIView
)的子類。
import Cocoa
class MetalView: NSView {
您會(huì)立即注意到一些錯(cuò)誤信號(hào)吃沪,表明以下屬性默認(rèn)不會(huì)再提供給我們:
- a device
- a drawable
- a render pass descriptor
我們來解決這個(gè)問題汤善。 首先,由于NSView
不是Metal-aware
,我們需要?jiǎng)?chuàng)建一個(gè)CAMetalLayer
并告訴NSView
使用它作為其背景層红淡。 CAMetalLayer
是一個(gè)核心動(dòng)畫層不狮,管理用于渲染其內(nèi)容的紋理池。 要使用Metal
進(jìn)行渲染在旱,我們需要通過從視圖的layerClass()
類方法中返回它摇零,將此類用作視圖的背景層。
override class func layerClass() -> AnyClass {
return CAMetalLayer.self
}
var metalLayer: CAMetalLayer {
return self.layer as! CAMetalLayer
}
接下來桶蝎,在render()
函數(shù)中創(chuàng)建一個(gè)新設(shè)備并告訴metalLayer
它擁有它驻仅,并且設(shè)置圖層將使用的像素格式。 然后登渣,創(chuàng)建一個(gè)drawable
噪服。 請(qǐng)注意,我們沒有使用隨MTKView
一起提供的currentDrawable
胜茧。 而是粘优,CAMetalLayer
提供了一個(gè)nextDrawable
供我們使用。 最后呻顽,創(chuàng)建一個(gè)渲染通道描述符雹顺。 再次注意,我們沒有提供currentRenderPassDescriptor:
let device = MTLCreateSystemDefaultDevice()!
metalLayer.device = device
metalLayer.pixelFormat = .BGRA8Unorm
let drawable = metalLayer.nextDrawable()
let texture = drawable!.texture
let rpd = MTLRenderPassDescriptor()
在本節(jié)結(jié)束之前廊遍,讓我們看一下MTKView
類嬉愧,以再次看到為什么這是使用Metal
在我們的應(yīng)用中呈現(xiàn)內(nèi)容的首選方式:
@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)
}
在眾多屬性中,請(qǐng)注意我們特別感興趣的屬性:device昧碉,currentDrawable
和currentRenderPassDescriptor
英染。 另外值得一提的是,該類為其MTKViewDelegate
屬性提供了一個(gè)協(xié)議被饿。 要詳細(xì)了解這些屬性和功能四康,請(qǐng)參閱MTKView參考文檔。