使用Metal绘制简单的形状 ShapeMeal

简介

ShapeMetal提供一些简单接口使用Metal去绘制一些简单的图形。例如,如果想绘制一个矩形传入当前座标系下面的一个Rect区域即可,绘制圆传Center和Radius即可。该工程使用了POP的编程风格,舍弃了OOP的方式,不是因为OOP不好,我只是单纯的认为OOP不适合组件式开发。如果有同学对POP感兴趣,可以看一下国外大神对swift使用POP的理解。

创作原因

Metal作为苹果推出的图像渲染和深度学习的框架,相比于OpenGL更加贴合苹果的硬件设备,性能有很大的提高。但是太过底层,如果当我们需要在MTKView上面单纯的绘制一些简单的图形的时候,过程特别繁琐。下面是我碰到的问题:

  1. Metal的座标系是归一化的座标系,范围是从[-1, 1]。所以我们屏幕上使用的座标系系统不能直接在Metal中使用,每次都需要转换顶点,就是好麻烦。
  2. 如果我们使用Core Graphics框架来绘制一些简单的图形,例如,绘制一个矩形,我们只需要传入一个NSRect,就可以绘制出来我们想要的形状。但是如果是metal的话就需要生成5个顶点信息来绘制出一个矩形。(这里为什么是5个顶点,后面会介绍到。)

如果我们想要绘制一些简单的图形就要通过两个复杂的步骤,1.屏幕座标系转换到Metal座标系 -> 2. 生成对应的顶点信息。所以我就在想有没有办法来把这些不必要的过程封装一下,只需要传入屏幕上一些简单的座标就能使用metal渲染出自己想要的图形。所以ShapeMetal工程就产生了。

ShapeMetal

Code Structure

  1. 因为是绘制的操作所以首先我们需要封装一些绘制操作,我创建了一个绘制简单图形的protocol
//定义一些简单的绘制图形的接口
protocol ShapeMetalDrawable {
	func line(_ start: NSPoint, _ end: NSPoint)
	func rectangle(_ rect: NSRect)
	func circle(_ center: NSPoint, _ radius: CGFloat)
}

如果是使用Core Graphics来绘制我们可以这么实现这个协议(或者说是扩展这个协议)。

extension ShapeMetalDrawable Where Self: CGContext {
	  func line(_ start: NSPoint, _ end: NSPoint) {
        saveGState()
        addLines(between: [start, end])
        strokePath()
        restoreGState()
    }
	
	func circle(_ center: NSPoint, _ radius: CGFloat) {
		...
	}

	func rectangle(_ rect: NSRect) {
		...
	}
}

我使用这个协议在一个NSView上面绘制了一个宽度为10的红色线段。
在这里插入图片描述
下面是具体的代码实现,比较简单就不一一赘述

extension CGContext: ShapeMetalDrawable {
    
}
class ShapeView: NSView {
    override func draw(_ dirtyRect: NSRect) {
        guard let context = NSGraphicsContext.current?.cgContext else {
            return
        }
        let startPoint = dirtyRect.origin
        let endPoint   = NSPoint(x: dirtyRect.midX, y: dirtyRect.midY)
        context.setLineWidth(10)
        context.setStrokeColor(CGColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0))
        context.line(startPoint, endPoint)
    }
}

Draw with Metal

接下来我们进入正题,怎么使用Metal来做简单的图形绘制。首先我们可以确定的是苹果公司并没有在Metal中提供一些简单的接口去绘制简单的图形,其实想想也比较合理,如果是单纯的绘制一些简单的图形,我们完全可以选择比metal更高级的一些框架,例如CoreGraphics。但是有时我们可能会需要来绘制一些简单的图形在MTKView上面。

在MTKView上面绘制一些简单的图形,有以下步骤:

  1. 座标转换
转换
归一化
Screen座标
Metal座标
归一化座标
  1. 配置渲染管线和Shader
    如果不太了解这一块的同学,我建议先去了解一下Metal的基础知识。

  2. 根据Point数据生成Vertex数据。

我们的想法就是怎么把这些细节给隐藏掉,让接口越简单越好。例如如果我们想绘制一个圆形,只需在绘制目标的座标系统下把圆点的座标和半径传给一个绘制接口。

写到这突然不想写了, 自己去看代码吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章