写在前面:
对Metal技术感兴趣的同学,可以关注我的专题:Metal专辑
也可以关注我个人的简书账号:张芳涛
所有的代码存储的Github地址是:Metal
正文
接下来,我们会使用playground进行项目开发(其实,不同平台下面的代码我一样会提供的)。
我们首先为OS X创建一个新的Xcode
playground
。一旦创建完成,点击Show the Assistant editor
按钮,并按下Command + 1
以显示项目导航器。 你的playground
应该是这样的:
我们要做的第一件事就是在项目导航器中的Resources
(资源)文件夹下创建Shaders.metal
,并使用与本系列前一集相同的源代码。 接下来,我们在Sources
文件夹下创建MathUtils.swift
和MetalView.swift
。 我们在MathUtils.swift
中做的唯一改变是我们为Vertex
结构创建了一个方便的初始化程序:
struct Vertex {
var position: vector_float4
var color: vector_float4
init(pos: vector_float4, col: vector_float4) {
position = pos
color = col
}
}
在MetalView.swift
中,我们需要做出更多更改。 首先,我们需要公开课程,因为我们将从Sources
文件夹以外调用它。 因此,初始化器和drawRect(:)
方法也需要公开。 此外,我们将创建第二个初始化程序,以便我们可以创建具有给定frame
(帧)的MetalView
:
public class MetalView: MTKView {
...
required public init(coder: NSCoder) {
super.init(coder: coder)
}
override public init(frame frameRect: CGRect, device: MTLDevice?) {
super.init(frame: frameRect, device: device)
createBuffers()
registerShaders()
}
...
}
接下来,我们需要做一个相当奇怪的改变,因为正如你注意到的那样,创建一个库:
let library = device.newDefaultLibrary()!
失败的时候显示以下错误消息:
MTLLibrary.mm:1016: failed assertion `filepath must not be nil.'
由于playground
没有我们可以使用的默认filepath
(文件路径),我们需要创建自己的文件路径:
func registerShaders() {
let path = NSBundle.mainBundle().pathForResource("Shaders", ofType: "metal")
let input: String?
let library: MTLLibrary
let vert_func: MTLFunction
let frag_func: MTLFunction
do {
input = try String(contentsOfFile: path!, encoding: NSUTF8StringEncoding)
library = try device!.newLibraryWithSource(input!, options: nil)
vert_func = library.newFunctionWithName("vertex_func")!
frag_func = library.newFunctionWithName("fragment_func")!
let rpld = MTLRenderPipelineDescriptor()
rpld.vertexFunction = vert_func
rpld.fragmentFunction = frag_func
rpld.colorAttachments[0].pixelFormat = .BGRA8Unorm
rps = try device!.newRenderPipelineStateWithDescriptor(rpld)
} catch let e {
Swift.print("\(e)")
}
}
注意,我们告诉playground
找到一个名为Shader.metal
的资源存在的路径。 接下来,我们将该文件转换为一个大的String
,然后我们从这个源创建库。
最后,我们去playground
的主页面,并创建一个新的MetalView
与给定的框架。 然后我们告诉playground
向我们展示实时视图:
import Cocoa
import XCPlayground
let device = MTLCreateSystemDefaultDevice()!
let frame = NSRect(x: 0, y: 0, width: 300, height: 300)
let view = MetalView(frame: frame, device: device)
XCPlaygroundPage.currentPage.liveView = view
如果您在Assistant editor
中显示Timeline
,则应该有相似的视图: