Metal入门资料007-MetalKit第六部分

作者: 张芳涛 | 来源:发表于2018-06-12 10:34 被阅读11次

    写在前面:

    对Metal技术感兴趣的同学,可以关注我的专题:Metal专辑
    也可以关注我个人的简书账号:张芳涛
    所有的代码存储的Github地址是:Metal

    正文

    我们来看看使用较新的MetalKit框架与使用较早的Metal框架之间有什么区别。 虽然它们仍然共存,但是MetalKit引入了一些强大的功能,例如:

    • 容易的texture纹理加载(甚至用几行代码进行异步加载)。
    • Model I/O网格和Metal缓冲区之间高效的数据传输。
    • MTKView - 一个方便的Metal-aware视图(后面会有更详细的介绍)。

    我将首先提醒你我们在第一章中看到的程序是什么样的:

    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()
        }
      }
    }
    

    就是这样! 简单和优雅的方式来清除你的背景颜色到你选择的自定义颜色。 现在让我们切换到使用没有MTKViewMetal框架,所以我们需要改为NSView(或iOS中的UIView)的子类。

    import Cocoa
    
    class MetalView: NSView {
    

    您会立即注意到一些错误信号,表明以下属性默认不会再提供给我们:

    • a device
    • a drawable
    • a render pass descriptor

    我们来解决这个问题。 首先,由于NSView不是Metal-aware,我们需要创建一个CAMetalLayer并告诉NSView使用它作为其背景层。 CAMetalLayer是一个核心动画层,管理用于渲染其内容的纹理池。 要使用Metal进行渲染,我们需要通过从视图的layerClass()类方法中返回它,将此类用作视图的背景层。

    override class func layerClass() -> AnyClass {
    return CAMetalLayer.self
    }
    
    var metalLayer: CAMetalLayer {
    return self.layer as! CAMetalLayer
    }
    

    接下来,在render()函数中创建一个新设备并告诉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类,以再次看到为什么这是使用Metal在我们的应用中呈现内容的首选方式:

    @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,currentDrawablecurrentRenderPassDescriptor。 另外值得一提的是,该类为其MTKViewDelegate属性提供了一个协议。 要详细了解这些属性和功能,请参阅MTKView参考文档。

    相关文章

      网友评论

        本文标题:Metal入门资料007-MetalKit第六部分

        本文链接:https://www.haomeiwen.com/subject/ldkleftx.html