源码
1. Swift
OpenGL源码
首先看下工程组织结构
接着看一下sb文件
下面就是源码了
1. Array+Helpers.swift
import Foundation//// MARK: - Array Helpers///// Array extension to help with size/memory calculations when working with OpenGL.extension Array { // // MARK: - Instance Methods // /// Returns the memory size/footprint (in bytes) of a given array. /// /// - Returns: Integer value representing the memory size the array. func size() -> Int { return count * MemoryLayout.size(ofValue: self[0]) } }
2. Vertex.swift
import GLKit//// MARK: - Vertex///// Structure to hold a vertex's position and color data.struct Vertex { /// Stores the X coordinate of a vertex. var x: GLfloat /// Stores the Y coordinate of a vertex. var y: GLfloat /// Stores the Z coordinate of a vertex. var z: GLfloat /// Stores the red color value of a vertex. var r: GLfloat /// Stores the green color value of a vertex. var g: GLfloat /// Stores the blue color value of a vertex. var b: GLfloat /// Stores the alpha value of a vertex. var a: GLfloat }
3. ViewController.swift
import GLKit final class ViewController: GLKViewController { var Vertices = [ Vertex(x: 1, y: -1, z: 0, r: 1, g: 0, b: 0, a: 1), Vertex(x: 1, y: 1, z: 0, r: 0, g: 1, b: 0, a: 1), Vertex(x: -1, y: 1, z: 0, r: 0, g: 0, b: 1, a: 1), Vertex(x: -1, y: -1, z: 0, r: 0, g: 0, b: 0, a: 1), ] var Indices: [GLubyte] = [0, 1, 2, 2, 3, 0] private var context: EAGLContext? private var effect = GLKBaseEffect() private var rotation: Float = 0.0 private var ebo = GLuint() private var vbo = GLuint() private var vao = GLuint() deinit { tearDownGL() } private func setupGL() { context = EAGLContext(api: .openGLES3) EAGLContext.setCurrent(context) if let view = view as? GLKView, let context = context { view.context = context delegate = self } // Helper variables to identify the position and color attributes for OpenGL calls. let vertexAttribColor = GLuint(GLKVertexAttrib.color.rawValue) let vertexAttribPosition = GLuint(GLKVertexAttrib.position.rawValue) // The size, in memory, of a Vertex structure. let vertexSize = MemoryLayout<Vertex>.stride let colorOffset = MemoryLayout<GLfloat>.stride * 3 let colorOffsetPointer = UnsafeRawPointer(bitPattern: colorOffset) // VAO // Generate and bind a vertex array object. glGenVertexArraysOES(1, &vao) glBindVertexArrayOES(vao) // VBO glGenBuffers(1, &vbo) glBindBuffer(GLenum(GL_ARRAY_BUFFER), vbo) glBufferData(GLenum(GL_ARRAY_BUFFER), Vertices.size(), Vertices, GLenum(GL_STATIC_DRAW)) glEnableVertexAttribArray(vertexAttribPosition) glVertexAttribPointer(vertexAttribPosition, 3, GLenum(GL_FLOAT), GLboolean(UInt8(GL_FALSE)), GLsizei(vertexSize), nil) // Enable the colors vertex attribute to then specify information about how the color of a vertex is stored. glEnableVertexAttribArray(vertexAttribColor) glVertexAttribPointer(vertexAttribColor, 4, GLenum(GL_FLOAT), GLboolean(UInt8(GL_FALSE)), GLsizei(vertexSize), colorOffsetPointer) // EBO glGenBuffers(1, &ebo) glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), ebo) glBufferData(GLenum(GL_ELEMENT_ARRAY_BUFFER), Indices.size(), Indices, GLenum(GL_STATIC_DRAW)) glBindBuffer(GLenum(GL_ARRAY_BUFFER), 0) glBindVertexArrayOES(0) } /// Perform cleanup, and delete buffers and memory. private func tearDownGL() { EAGLContext.setCurrent(context) glDeleteBuffers(1, &vao) glDeleteBuffers(1, &vbo) glDeleteBuffers(1, &ebo) EAGLContext.setCurrent(nil) context = nil } override func viewDidLoad() { super.viewDidLoad() setupGL() } } extension ViewController: GLKViewControllerDelegate { func glkViewControllerUpdate(_ controller: GLKViewController) { let aspect = fabsf(Float(view.bounds.size.width) / Float(view.bounds.size.height)) let projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0), aspect, 4.0, 10.0) effect.transform.projectionMatrix = projectionMatrix var modelViewMatrix = GLKMatrix4MakeTranslation(0.0, 0.0, -6.0) rotation += 90 * Float(timeSinceLastUpdate) modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, GLKMathDegreesToRadians(rotation), 0, 0, 1) effect.transform.modelviewMatrix = modelViewMatrix } override func glkView(_ view: GLKView, drawIn rect: CGRect) { glClearColor(0.85, 0.85, 0.85, 1.0) glClear(GLbitfield(GL_COLOR_BUFFER_BIT)) effect.prepareToDraw() glBindVertexArrayOES(vao) glDrawElements(GLenum(GL_TRIANGLES), GLsizei(Indices.count), GLenum(GL_UNSIGNED_BYTE), nil) glBindVertexArrayOES(0) } }
下面看一下实现效果
Metal源码
首先还是看下工程组织结构
接着看sb中的内容
下面就是源码了
1. Array+Helpers.swift
import Foundation// MARK: - Array Helpers/// Array extension to help with size/memory calculations when working with OpenGL.extension Array { // MARK: - Instance Methods /// Returns the memory size/footprint (in bytes) of a given array. /// /// - Returns: Integer value representing the memory size the array. func size() -> Int { return count * MemoryLayout.size(ofValue: self[0]) } }
2. Vertex.swift
import GLKit//// MARK: - Vertex///// Structure to hold a vertex's position and color data.struct Vertex { /// Stores the X coordinate of a vertex. var x: GLfloat /// Stores the Y coordinate of a vertex. var y: GLfloat /// Stores the Z coordinate of a vertex. var z: GLfloat /// Stores the red color value of a vertex. var r: GLfloat /// Stores the green color value of a vertex. var g: GLfloat /// Stores the blue color value of a vertex. var b: GLfloat /// Stores the alpha value of a vertex. var a: GLfloat } struct SceneMatrices { var projectionMatrix: GLKMatrix4 = GLKMatrix4Identity var modelviewMatrix: GLKMatrix4 = GLKMatrix4Identity }
3. ViewController.swift
import GLKit import MetalKit final class ViewController: UIViewController { @IBOutlet weak var metalView: MTKView! private var vertexBuffer: MTLBuffer! private var indicesBuffer: MTLBuffer! private var metalDevice: MTLDevice! private var metalCommandQueue: MTLCommandQueue! private var pipelineState: MTLRenderPipelineState! var Vertices = [ Vertex(x: 1, y: -1, z: 0, r: 1, g: 0, b: 0, a: 1), Vertex(x: 1, y: 1, z: 0, r: 0, g: 1, b: 0, a: 1), Vertex(x: -1, y: 1, z: 0, r: 0, g: 0, b: 1, a: 1), Vertex(x: -1, y: -1, z: 0, r: 0, g: 0, b: 0, a: 1), ] var Indices: [UInt32] = [0, 1, 2, 2, 3, 0] private var rotation: Float = 0.0 private var ebo = GLuint() private var vbo = GLuint() private var vao = GLuint() private var sceneMatrices = SceneMatrices() private var uniformBuffer: MTLBuffer! private var lastUpdateDate = Date() private func setupMetal() { metalDevice = MTLCreateSystemDefaultDevice() // 1 metalCommandQueue = metalDevice.makeCommandQueue() // 2 metalView.device = metalDevice // 3 metalView.delegate = self // 4 let vertexBufferSize = Vertices.size() vertexBuffer = metalDevice.makeBuffer(bytes: &Vertices, length: vertexBufferSize, options: .storageModeShared) let indicesBufferSize = Indices.size() indicesBuffer = metalDevice.makeBuffer(bytes: &Indices, length: indicesBufferSize, options: .storageModeShared) let defaultLibrary = metalDevice.makeDefaultLibrary()! let fragmentProgram = defaultLibrary.makeFunction(name: "basic_fragment") let vertexProgram = defaultLibrary.makeFunction(name: "basic_vertex") // 1 let pipelineStateDescriptor = MTLRenderPipelineDescriptor() pipelineStateDescriptor.vertexFunction = vertexProgram pipelineStateDescriptor.fragmentFunction = fragmentProgram pipelineStateDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm // 2 pipelineState = try! metalDevice.makeRenderPipelineState(descriptor: pipelineStateDescriptor) // 3 } override func viewDidLoad() { super.viewDidLoad() setupMetal() } }// MARK: - MTKView Delegate Extensionextension ViewController: MTKViewDelegate { // 1 func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { let aspect = fabsf(Float(size.width) / Float(size.height)) // 1 let projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0), aspect, 4.0, 10.0) // 2 sceneMatrices.projectionMatrix = projectionMatrix // 3 } // 2 func draw(in view: MTKView) { // 1 guard let drawable = view.currentDrawable else { return } let renderPassDescriptor = MTLRenderPassDescriptor() // 2 renderPassDescriptor.colorAttachments[0].texture = drawable.texture // 3 renderPassDescriptor.colorAttachments[0].loadAction = .clear // 4 renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColor(red: 0.85, green: 0.85, blue: 0.85, alpha: 1.0) // 5 // 6 guard let commandBuffer = metalCommandQueue.makeCommandBuffer() else { return } // 7 guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) else { return } // Frame drawing goes here renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0) // 1 // Update logic var modelViewMatrix = GLKMatrix4MakeTranslation(0.0, 0.0, -6.0) let timeSinceLastUpdate = lastUpdateDate.timeIntervalSince(Date()) rotation += 90 * Float(timeSinceLastUpdate) // 1 modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, GLKMathDegreesToRadians(rotation), 0, 0, 1) // 2 sceneMatrices.modelviewMatrix = modelViewMatrix // Set uniform buffer let uniformBufferSize = MemoryLayout.size(ofValue: sceneMatrices) uniformBuffer = metalDevice.makeBuffer(bytes: &sceneMatrices, length: uniformBufferSize, options: .storageModeShared) // 2 renderEncoder.setVertexBuffer(uniformBuffer, offset: 0, index: 1) // 3 renderEncoder.setRenderPipelineState(pipelineState) renderEncoder.drawIndexedPrimitives(type: .triangle, indexCount: Indices.count, indexType: .uint32, indexBuffer: indicesBuffer, indexBufferOffset: 0) // 2 renderEncoder.endEncoding() // 8 commandBuffer.addCompletedHandler { _ in self.lastUpdateDate = Date() } commandBuffer.present(drawable) // 9 commandBuffer.commit() // 10 } }
具体效果同OpenGL一样,这里就不展示了。
后记
本篇主要讲述了将项目从OpenGL转化到Metal,感兴趣的给个赞或者关注~~
作者:刀客传奇
链接:https://www.jianshu.com/p/ad2ceae81a2b
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦