本系列文章是对 metalkit.org 上面MetalKit内容的全面翻译和学习.git
MetalKit 框架是在 WWDC 2015 上发布的,它给原Metal框架带来了大量改进和新特性.认识 MTKView, NSView/UIView
的一个子类. 它内置了一个Metal layer层,也同时管理着帧缓冲器framebuffer及其渲染目标附件render target attachments,还管理着绘制循环draw loop.github
让咱们建立一个Cocoa Application
(由于iOS
模拟器不支持Metal
).确保只有Swift
和Use Strotyboards
区域是选中状态.接下来,建立一个新的类,名为MetalView.swift继承于NSView
(暂时).而后,到storyboard中选中View Controller
下面的View
,设置Identity Inspector
中的类为MetalView
类型,以下图. swift
对View Controller
也是一样操做,删除Identity Inspector
中Class
下面的View Controller
,由于咱们用不到它.删除ViewController.swift
由于我也不须要它了.如今回到MetalView.swift
文件中,输入import MetalKit.有两种方法可让咱们的类支持绘制:遵照MTKViewDelegate
协议并实现它的drawInView(:)
方法,或者继承MTKView
并重写它的drawRect(:)
方法.这里咱们选择后者,因此将类的类型从NSView
改成MTKView,并建立一个新方法名为render()
,内容以下:app
func render() {
let device = MTLCreateSystemDefaultDevice()!
self.device = device
let rpd = MTLRenderPassDescriptor()
let bleen = MTLClearColor(red: 0, green: 0.5, blue: 0.5, alpha: 1)
rpd.colorAttachments[0].texture = currentDrawable!.texture
rpd.colorAttachments[0].clearColor = bleen
rpd.colorAttachments[0].loadAction = .Clear
let commandQueue = device.newCommandQueue()
let commandBuffer = commandQueue.commandBuffer()
let encoder = commandBuffer.renderCommandEncoderWithDescriptor(rpd)
encoder.endEncoding()
commandBuffer.presentDrawable(currentDrawable!)
commandBuffer.commit()
}
复制代码
让咱们一行一行来细看这些代码.首先,咱们建立一个device.咱们将其设置为咱们view的属性device
,不然该属性为nil
程序会崩溃.做为一个可选项,咱们能够在绘制以前修改view的drawable
属性.接着,建立一个render pass descriptor(渲染通道描述符) 以便咱们配置渲染通道为current drawable’s texture
附着上初始颜色.为了有趣一点,咱们建立一个很棒的颜色,由一半蓝色一半绿色组成,叫bleen.最后,咱们使用命令缓冲器来建立render command encoder来执行绘制命令.对于每一个绘制循环,当currentRenderPassDescriptor
查询时,建立一个新的MTLRenderPassDescriptor
对象.这个对象是基于currentDrawable
对象建立的.画面显示并非MTKView
处理的,因此咱们必须本身先检查currentRenderPassDescriptor
和currentDrawable
都为为nil
,而后再调用presentDrawable(:)
方法.框架
让咱们参考一下Metal 文档中的细节.Metal
框架包含若干对象:ide
device设备
-对GPU
的抽象,处理命令队列中的渲染和计算命令command queue命令队列
-一个命令缓冲器的串行队列,确保储存的命令按顺序执行command buffer命令缓冲器
-储存从命令编码器中编译出的指令.当能问执行完全部命令后Metal会通知应用程序.command encoder命令编码器
-将API
命令编译成GPU
硬件命令-共有三种类型的编码器:render
(供图形渲染),compute
(供数据并行处理)及blit
(供资源复制操做).目前咱们只需关注render command encoder渲染命令编码器
states状态
-例如混合和深度shaders着色器
-源码resources资源
-纹理和数据缓冲器咱们在本系列的下一节中将讨论最后3个对象.当前咱们只关注device
,queue
,buffer
和encoder
.Render Command Encoder (RCE)渲染命令编码器
为每个单独的渲染通道提供硬件命令,这意味着全部的渲染都被送入一个单一的framebuffer帧缓冲器
对象中(目标集合中).若是另外一个帧缓冲器须要被渲染,会建立一个新的RCE.RCE会为从graphics popeline图形管线
中给出的vertex顶点
和fragment片断
肯定状态,而且插入resources
,state changes
和draw calls
.利用RCE
的一个优势是无需绘制时编译;应用能够决定编译和状态检查什么时候发生,这样为程序员提供了很大的性能优点.oop
让咱们再回到咱们的代码.在drawRect(:) 方法中调用render()
方法:post
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
render()
}
复制代码
若是你运行应用,你将会看到一个漂亮的,纯粹的bleen-ish
屏幕: 性能
在下一节中,咱们终于开始介绍shaders
,加载textures
及管理model data模型数据
.代码 source code 发布于Github
上.
下次见!