相信大家在开发苹果平台应用时,或多或少使用过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中给视图绘制颜色比较复杂,下面是主要过程。
-
首先我们使用使用
MTKView,这是MetalKit中的类。在storyboard中我们将View的class改为MTKView -
然后给
MTKView设置device属性mtkView.device = MTLCreateSystemDefaultDevice() -
要将视图的内容设置单一背景色,可以设置其
clearColor属性。mtkView.clearColor = MTLClearColor(red: 0.5, green: 1.0, blue: 1.0, alpha: 1.0) -
设置MTKViewDelegate
mtkView.delegate = render这个代理需要实现两个方法
-
mtkView(_:drawableSizeWillChange:)当绘制区域变化时,系统会调用这个方法,我们可以在这个方法更改一些设置。
-
draw(in:)当时图需要更新时,系统会调用这个方法,我们一般在这个方法中创建命令缓冲区,编码绘制命令,提交命令缓冲区,以便GPU执行。
-
-
创建渲染管道描述符
guard let renderPassDesriptor = view.currentRenderPassDescriptor else { return }渲染管道描述符在 Metal 中的作用是定义一次渲染管道的配置,它用于描述 GPU 在渲染时如何处理一系列的渲染目标(例如纹理或帧缓冲)。我们可以免费从
MTKView中免费获得一个渲染管道描述符 -
创建渲染管道
let commanderEncoder = commanderBuffer?.makeRenderCommandEncoder(descriptor: renderPassDesriptor)你通过使用
MTLRenderCommandEncoder对象将渲染通道编码到命令缓冲区来创建渲染通道。调用命令缓冲区的makeRenderCommandEncoder(descriptor:)方法,并传入渲染通道描述符。我们可以使用
commanderEncoder编码绘制命令,我们需要在编码结束后调用endEncodingcommanderEncoder?.endEncoding() -
在屏幕上显示可绘制对象
guard let drawable = view.currentDrawable else { return } commanderBuffer?.present(drawable)这段方法告诉 Metal在渲染完成后显示纹理。在本例中,这意味着被擦除的纹理将成为视图的新背景。
-
提交命令缓冲区
commanderBuffer?.commit()
总结
使用 Core Graphics 绘制视图背景色简单直接,但在需要高性能渲染时,Metal 提供了更高的灵活性和控制力。通过 MTKView 和 Metal 的渲染管道,我们可以更精确地控制图形渲染过程,实现更复杂的图形效果。掌握这些基础知识对于深入理解和使用 Metal 至关重要。 源码