你好,Metal!

373 阅读3分钟

相信大家在开发苹果平台应用时,或多或少使用过Metal。掌握Metal技术越来越有必要,特别是在我们需要渲染高质量图片或者需要进行复杂计算时,Metal不可或缺。今天我们从一个简单的渲染例子开始,开启Metal的旅程。

使用Core Graphics给视图绘制颜色

class ColorView: NSView {
    override func draw(_ dirtyRect: NSRect) {
        let colorToDraw = NSColor(red: 0.5, green: 1.0, blue: 1.0, alpha: 1.0)
        colorToDraw.setFill()
        bounds.fill()
    }
}

看起来很简单,1. 设置填充颜色 2. 矩形填充。Core Graphics 是构建在Metal的上层,相对来说简单,屏蔽了底层的渲染代码。

注意 这里不要直接使用dirtyRect,这是因为在macOS 14中 NSView的属性ClipToBounds默认改为false, 而在之前的系统中默认是true, 推荐使用Bounds.

使用Metal给视图绘制颜色

在Metal中给视图绘制颜色比较复杂,下面是主要过程。

  1. 首先我们使用使用MTKView,这是MetalKit中的类。在storyboard中我们将Viewclass改为MTKView

  2. 然后给MTKView设置device属性

    mtkView.device = MTLCreateSystemDefaultDevice()
    
  3. 要将视图的内容设置单一背景色,可以设置其 clearColor 属性。

    mtkView.clearColor = MTLClearColor(red: 0.5, green: 1.0, blue: 1.0, alpha: 1.0)
    
  4. 设置MTKViewDelegate

    mtkView.delegate = render
    

    这个代理需要实现两个方法

    • mtkView(_:drawableSizeWillChange:)

      当绘制区域变化时,系统会调用这个方法,我们可以在这个方法更改一些设置。

    • draw(in:)

      当时图需要更新时,系统会调用这个方法,我们一般在这个方法中创建命令缓冲区,编码绘制命令,提交命令缓冲区,以便GPU执行。

  5. 创建渲染管道描述符

    guard let renderPassDesriptor = view.currentRenderPassDescriptor else {
        return
    }
    

    渲染管道描述符 在 Metal 中的作用是定义一次渲染管道的配置,它用于描述 GPU 在渲染时如何处理一系列的渲染目标(例如纹理或帧缓冲)。

    我们可以免费从MTKView中免费获得一个渲染管道描述符

  6. 创建渲染管道

    let commanderEncoder = commanderBuffer?.makeRenderCommandEncoder(descriptor: renderPassDesriptor)
    

    你通过使用 MTLRenderCommandEncoder 对象将渲染通道编码到命令缓冲区来创建渲染通道。调用命令缓冲区的 makeRenderCommandEncoder(descriptor:) 方法,并传入渲染通道描述符。

    我们可以使用commanderEncoder编码绘制命令,我们需要在编码结束后调用endEncoding

    commanderEncoder?.endEncoding()
    
  7. 在屏幕上显示可绘制对象

    guard let drawable = view.currentDrawable else {
        return
    }
    commanderBuffer?.present(drawable)
    

    这段方法告诉 Metal在渲染完成后显示纹理。在本例中,这意味着被擦除的纹理将成为视图的新背景。

  8. 提交命令缓冲区

    commanderBuffer?.commit()
    

总结

使用 Core Graphics 绘制视图背景色简单直接,但在需要高性能渲染时,Metal 提供了更高的灵活性和控制力。通过 MTKView 和 Metal 的渲染管道,我们可以更精确地控制图形渲染过程,实现更复杂的图形效果。掌握这些基础知识对于深入理解和使用 Metal 至关重要。 源码