Added init for Metal in SwiftUIKit
This commit is contained in:
parent
749631e664
commit
7b33f525ed
|
@ -3,3 +3,4 @@
|
|||
/Packages
|
||||
/*.xcodeproj
|
||||
xcuserdata/
|
||||
build
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
//
|
||||
// Primitive.swift
|
||||
// MetalTutoral
|
||||
//
|
||||
// Created by developer on 10/22/19.
|
||||
// Copyright © 2019 developer. All rights reserved.
|
||||
//
|
||||
|
||||
import MetalKit
|
||||
|
||||
@available(iOS 9.0, *)
|
||||
class Primitive {
|
||||
static func importObj(device: MTLDevice, size: Float) -> MTKMesh {
|
||||
let allocator = MTKMeshBufferAllocator(device: device)
|
||||
var url = URL(string: "/Users/developer/Documents/cube.obj")
|
||||
let vertexDescriptor = MDLVertexDescriptor()
|
||||
let vertexLayout = MDLVertexBufferLayout()
|
||||
vertexLayout.stride = MemoryLayout<Vertex>.stride
|
||||
vertexDescriptor.layouts = [vertexLayout]
|
||||
vertexDescriptor.attributes = [MDLVertexAttribute(name: MDLVertexAttributePosition, format: MDLVertexFormat.float2, offset: 0, bufferIndex: 0),
|
||||
MDLVertexAttribute(name: MDLVertexAttributeNormal, format: MDLVertexFormat.float2, offset: MemoryLayout<vector_float2>.stride, bufferIndex: 0)]
|
||||
// vertexDescriptor.attributes = [MDLVertexAttribute(name: MDLVertexAttributePosition, format: MDLVertexFormat.float3, offset: 0, bufferIndex: 0),
|
||||
// MDLVertexAttribute(name: MDLVertexAttributeColor, format: MDLVertexFormat.float4, offset: MemoryLayout<vector_float3>.stride, bufferIndex: 0),
|
||||
// MDLVertexAttribute(name: MDLVertexAttributeTextureCoordinate, format: MDLVertexFormat.float2, offset: MemoryLayout<vector_float3>.stride+MemoryLayout<vector_float4>.stride, bufferIndex: 0),
|
||||
// MDLVertexAttribute(name: MDLVertexAttributeNormal, format: MDLVertexFormat.float3, offset: MemoryLayout<vector_float3>.stride + MemoryLayout<vector_float4>.stride +
|
||||
// MemoryLayout<vector_float2>.stride, bufferIndex: 0)]
|
||||
var error: NSError?
|
||||
let asset = MDLAsset(url: url!,vertexDescriptor: vertexDescriptor, bufferAllocator: allocator, preserveTopology: true, error: &error)
|
||||
if error != nil{
|
||||
print(error)
|
||||
}
|
||||
|
||||
let model = asset.object(at: 0) as! MDLMesh
|
||||
var mesh : MTKMesh
|
||||
do {
|
||||
mesh = try MTKMesh(mesh: model, device: device)
|
||||
} catch let error {
|
||||
fatalError(error.localizedDescription)
|
||||
}
|
||||
|
||||
return mesh
|
||||
}
|
||||
|
||||
static func makeCube(device: MTLDevice, size: Float) -> MDLMesh {
|
||||
let allocator = MTKMeshBufferAllocator(device: device)
|
||||
let mesh = MDLMesh(boxWithExtent: [size, size, size],
|
||||
segments: [1,1,1],
|
||||
inwardNormals: false,
|
||||
geometryType: .triangles,
|
||||
allocator: allocator)
|
||||
return mesh
|
||||
}
|
||||
|
||||
static func makeTriangle(device: MTLDevice, size: Float) -> MDLMesh {
|
||||
let allocator = MTKMeshBufferAllocator(device: device)
|
||||
|
||||
//create vertex buffer
|
||||
let vertices: [vector_float2] = [vector_float2(0, 0), vector_float2(0.1, 0), vector_float2(0.1,0.1)]
|
||||
let vertexBuffer = allocator.newBuffer(MemoryLayout<vector_float2>.stride * vertices.count, type: .vertex)
|
||||
let vertexMap = vertexBuffer.map()
|
||||
vertexMap.bytes.assumingMemoryBound(to: vector_float2.self).assign(from: vertices, count: vertices.count)
|
||||
|
||||
//create index buffer
|
||||
let indices: [UInt16] = [UInt16(0), UInt16(1), UInt16(2)]
|
||||
let indexBuffer = allocator.newBuffer(MemoryLayout<UInt16>.stride * indices.count, type: .index)
|
||||
let indexMap = indexBuffer.map()
|
||||
indexMap.bytes.assumingMemoryBound(to: UInt16.self).assign(from: indices, count: indices.count)
|
||||
|
||||
let submesh = MDLSubmesh(indexBuffer: indexBuffer,
|
||||
indexCount: indices.count,
|
||||
indexType: .uInt16,
|
||||
geometryType: .points,
|
||||
material: nil)
|
||||
|
||||
|
||||
let vertexDescriptor = MDLVertexDescriptor()
|
||||
vertexDescriptor.attributes[0] = MDLVertexAttribute(name: MDLVertexAttributePosition,
|
||||
format: .float2,
|
||||
offset: 0,
|
||||
bufferIndex: 0)
|
||||
vertexDescriptor.layouts[0] = MDLVertexBufferLayout(stride: MemoryLayout<vector_float2>.stride)
|
||||
|
||||
let mesh = MDLMesh(vertexBuffer: vertexBuffer,
|
||||
vertexCount: vertices.count,
|
||||
descriptor: vertexDescriptor,
|
||||
submeshes: [submesh])
|
||||
|
||||
|
||||
return mesh
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
//
|
||||
// CustomRenderer.swift
|
||||
// SwiftUIKit
|
||||
//
|
||||
// Created by Zach Eriksen on 1/19/20.
|
||||
//
|
||||
|
||||
import MetalKit
|
||||
|
||||
@available(iOS 9.0, *)
|
||||
class CustomRenderer: NSObject, Renderer {
|
||||
// Dummy
|
||||
func getMesh() -> MDLMesh {
|
||||
return Primitive.makeCube(device: device, size: 1)
|
||||
}
|
||||
|
||||
var mesh: MTKMesh?
|
||||
var vertexBuffer: MTLBuffer?
|
||||
var pipelineState: MTLRenderPipelineState?
|
||||
var vertexFunction: MTLFunction?
|
||||
var fragmentFunction: MTLFunction?
|
||||
var clearColor: MTLClearColor?
|
||||
var renderMethod: ((MTLRenderCommandEncoder) -> Void)?
|
||||
|
||||
internal var vertexShaderName: String = "vertex_main_moving"
|
||||
internal var fragmentShaderName: String = "fragment_main"
|
||||
var timer: Float = 0
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
func mesh(_ closure: (MTLDevice) -> MDLMesh) -> Self {
|
||||
do{
|
||||
mesh = try MTKMesh(mesh: closure(device), device: device)
|
||||
} catch let error {
|
||||
print(error.localizedDescription)
|
||||
}
|
||||
|
||||
vertexBuffer = mesh?.vertexBuffers[0].buffer
|
||||
return self
|
||||
}
|
||||
|
||||
func vertex(shaderName: () -> String) -> Self {
|
||||
let library = device.makeDefaultLibrary()
|
||||
vertexFunction = library?.makeFunction(name: shaderName())
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func fragment(shaderName: () -> String) -> Self {
|
||||
let library = device.makeDefaultLibrary()
|
||||
fragmentFunction = library?.makeFunction(name: shaderName())
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func clear(color: () -> MTLClearColor) -> Self {
|
||||
clearColor = color()
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func render(encoder: @escaping (MTLRenderCommandEncoder) -> Void) -> Self {
|
||||
renderMethod = encoder
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func load(metalView: MTKView) {
|
||||
let pipelineDescriptor = MTLRenderPipelineDescriptor()
|
||||
pipelineDescriptor.vertexFunction = vertexFunction
|
||||
pipelineDescriptor.fragmentFunction = fragmentFunction
|
||||
|
||||
if let mesh = mesh {
|
||||
pipelineDescriptor.vertexDescriptor = MTKMetalVertexDescriptorFromModelIO(mesh.vertexDescriptor)
|
||||
}
|
||||
pipelineDescriptor.colorAttachments[0].pixelFormat = metalView.colorPixelFormat
|
||||
do {
|
||||
pipelineState = try device.makeRenderPipelineState(descriptor: pipelineDescriptor)
|
||||
} catch let error {
|
||||
fatalError(error.localizedDescription)
|
||||
}
|
||||
|
||||
// Protocol
|
||||
if let color = clearColor {
|
||||
metalView.clearColor = color
|
||||
}
|
||||
metalView.delegate = self
|
||||
}
|
||||
|
||||
func configure(renderEncoder: MTLRenderCommandEncoder) -> MTLRenderCommandEncoder? {
|
||||
//pipeline state
|
||||
guard let pipelineState = pipelineState,
|
||||
let mesh = mesh else {
|
||||
return nil
|
||||
}
|
||||
//pre-processing
|
||||
timer += 0.05
|
||||
var currentTime = sin(timer)
|
||||
var al = abs(currentTime)
|
||||
|
||||
//render encoder init
|
||||
renderEncoder.setVertexBytes(¤tTime,
|
||||
length: MemoryLayout<Float>.stride,
|
||||
index: 1)
|
||||
renderEncoder.setFragmentBytes(&al,
|
||||
length: MemoryLayout<Float>.stride,
|
||||
index: 0)
|
||||
|
||||
renderEncoder.setRenderPipelineState(pipelineState)
|
||||
renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
|
||||
|
||||
for submesh in mesh.submeshes {
|
||||
renderEncoder.drawIndexedPrimitives(type: .triangle,
|
||||
indexCount: submesh.indexCount,
|
||||
indexType: submesh.indexType,
|
||||
indexBuffer: submesh.indexBuffer.buffer,
|
||||
indexBufferOffset: submesh.indexBuffer.offset)
|
||||
|
||||
}
|
||||
|
||||
return renderEncoder
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 9.0, *)
|
||||
extension CustomRenderer: MTKViewDelegate {
|
||||
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
func draw(in view: MTKView) {
|
||||
draw(metalView: view)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// Vertex.swift
|
||||
// MetalTutoral
|
||||
//
|
||||
// Created by developer on 10/28/19.
|
||||
// Copyright © 2019 developer. All rights reserved.
|
||||
//
|
||||
|
||||
import MetalKit
|
||||
|
||||
struct Vertex {
|
||||
var vertex: float2
|
||||
|
||||
init(x: Float, y: Float) {
|
||||
self.vertex = float2(x, y)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
////
|
||||
//// MeshRenderer.swift
|
||||
//// MetalTutoral
|
||||
////
|
||||
//// Created by developer on 11/12/19.
|
||||
//// Copyright © 2019 developer. All rights reserved.
|
||||
////
|
||||
|
||||
import MetalKit
|
||||
|
||||
@available(iOS 9.0, *)
|
||||
class ColorChangeRenderer: NSObject, Renderer {
|
||||
var mesh: MTKMesh?
|
||||
var vertexBuffer: MTLBuffer?
|
||||
var pipelineState: MTLRenderPipelineState?
|
||||
|
||||
internal var vertexShaderName: String = "vertex_main"
|
||||
internal var fragmentShaderName: String = "fragment_main_change"
|
||||
var timer: Float = 0
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
let mdlMesh = getMesh()
|
||||
|
||||
do{
|
||||
mesh = try MTKMesh(mesh: mdlMesh, device: device)
|
||||
} catch let error {
|
||||
print(error.localizedDescription)
|
||||
}
|
||||
|
||||
vertexBuffer = mesh?.vertexBuffers[0].buffer
|
||||
|
||||
}
|
||||
|
||||
func getMesh() -> MDLMesh {
|
||||
return Primitive.makeCube(device: device, size: 1)
|
||||
}
|
||||
|
||||
func load(metalView: MTKView) {
|
||||
let library = device.makeDefaultLibrary()
|
||||
let vertexFunction = library?.makeFunction(name: vertexShaderName)
|
||||
let fragmentFunction = library?.makeFunction(name: fragmentShaderName)
|
||||
|
||||
let pipelineDescriptor = MTLRenderPipelineDescriptor()
|
||||
pipelineDescriptor.vertexFunction = vertexFunction
|
||||
pipelineDescriptor.fragmentFunction = fragmentFunction
|
||||
if let mesh = mesh {
|
||||
pipelineDescriptor.vertexDescriptor = MTKMetalVertexDescriptorFromModelIO(mesh.vertexDescriptor)
|
||||
}
|
||||
pipelineDescriptor.colorAttachments[0].pixelFormat = metalView.colorPixelFormat
|
||||
do {
|
||||
pipelineState = try device.makeRenderPipelineState(descriptor: pipelineDescriptor)
|
||||
} catch let error {
|
||||
fatalError(error.localizedDescription)
|
||||
}
|
||||
|
||||
// Protocol
|
||||
metalView.clearColor = MTLClearColor(red: 1, green: 1, blue: 0.8, alpha: 1)
|
||||
metalView.delegate = self
|
||||
}
|
||||
|
||||
func configure(renderEncoder: MTLRenderCommandEncoder) -> MTLRenderCommandEncoder? {
|
||||
guard let pipelineState = pipelineState,
|
||||
let mesh = mesh else {
|
||||
return nil
|
||||
}
|
||||
|
||||
timer += 0.05
|
||||
var currentTime = sin(timer)
|
||||
var al = abs(currentTime)
|
||||
renderEncoder.setFragmentBytes(&al,
|
||||
length: MemoryLayout<Float>.stride,
|
||||
index: 0)
|
||||
|
||||
renderEncoder.setRenderPipelineState(pipelineState)
|
||||
renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
|
||||
|
||||
for submesh in mesh.submeshes {
|
||||
renderEncoder.drawIndexedPrimitives(type: .triangle,
|
||||
indexCount: submesh.indexCount,
|
||||
indexType: submesh.indexType,
|
||||
indexBuffer: submesh.indexBuffer.buffer,
|
||||
indexBufferOffset: submesh.indexBuffer.offset)
|
||||
|
||||
}
|
||||
|
||||
return renderEncoder
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 9.0, *)
|
||||
extension ColorChangeRenderer: MTKViewDelegate {
|
||||
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
func draw(in view: MTKView) {
|
||||
draw(metalView: view)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
////
|
||||
//// MeshRenderer.swift
|
||||
//// MetalTutoral
|
||||
////
|
||||
//// Created by developer on 11/12/19.
|
||||
//// Copyright © 2019 developer. All rights reserved.
|
||||
////
|
||||
|
||||
import MetalKit
|
||||
@available(iOS 9.0, *)
|
||||
class MeshRenderer: NSObject, Renderer {
|
||||
var mesh: MTKMesh?
|
||||
var vertexBuffer: MTLBuffer?
|
||||
var pipelineState: MTLRenderPipelineState?
|
||||
|
||||
internal var vertexShaderName: String = "vertex_main"
|
||||
internal var fragmentShaderName: String = "fragment_main_test"
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
let mdlMesh = getMesh()
|
||||
|
||||
do{
|
||||
mesh = try MTKMesh(mesh: mdlMesh, device: device)
|
||||
} catch let error {
|
||||
print(error.localizedDescription)
|
||||
}
|
||||
|
||||
vertexBuffer = mesh?.vertexBuffers[0].buffer
|
||||
|
||||
}
|
||||
|
||||
func getMesh() -> MDLMesh {
|
||||
return Primitive.makeCube(device: device, size: 1)
|
||||
}
|
||||
|
||||
func load(metalView: MTKView) {
|
||||
let library = device.makeDefaultLibrary()
|
||||
let vertexFunction = library?.makeFunction(name: vertexShaderName)
|
||||
let fragmentFunction = library?.makeFunction(name: fragmentShaderName)
|
||||
|
||||
let pipelineDescriptor = MTLRenderPipelineDescriptor()
|
||||
pipelineDescriptor.vertexFunction = vertexFunction
|
||||
pipelineDescriptor.fragmentFunction = fragmentFunction
|
||||
if let mesh = mesh {
|
||||
pipelineDescriptor.vertexDescriptor = MTKMetalVertexDescriptorFromModelIO(mesh.vertexDescriptor)
|
||||
}
|
||||
pipelineDescriptor.colorAttachments[0].pixelFormat = metalView.colorPixelFormat
|
||||
do {
|
||||
pipelineState = try device.makeRenderPipelineState(descriptor: pipelineDescriptor)
|
||||
} catch let error {
|
||||
fatalError(error.localizedDescription)
|
||||
}
|
||||
|
||||
// Protocol
|
||||
metalView.clearColor = MTLClearColor(red: 1, green: 1, blue: 0.8, alpha: 1)
|
||||
metalView.delegate = self
|
||||
}
|
||||
|
||||
func configure(renderEncoder: MTLRenderCommandEncoder) -> MTLRenderCommandEncoder? {
|
||||
guard let pipelineState = pipelineState,
|
||||
let mesh = mesh else {
|
||||
return nil
|
||||
}
|
||||
renderEncoder.setRenderPipelineState(pipelineState)
|
||||
renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
|
||||
|
||||
for submesh in mesh.submeshes {
|
||||
renderEncoder.drawIndexedPrimitives(type: .triangle,
|
||||
indexCount: submesh.indexCount,
|
||||
indexType: submesh.indexType,
|
||||
indexBuffer: submesh.indexBuffer.buffer,
|
||||
indexBufferOffset: submesh.indexBuffer.offset)
|
||||
|
||||
}
|
||||
|
||||
return renderEncoder
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 9.0, *)
|
||||
extension MeshRenderer: MTKViewDelegate {
|
||||
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
func draw(in view: MTKView) {
|
||||
draw(metalView: view)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// Renderer.swift
|
||||
// MetalTutoral
|
||||
//
|
||||
// Created by developer on 10/22/19.
|
||||
// Copyright © 2019 developer. All rights reserved.
|
||||
//
|
||||
|
||||
import MetalKit
|
||||
|
||||
class MetalDevice {
|
||||
static var shared: MetalDevice = MetalDevice()
|
||||
|
||||
var device: MTLDevice
|
||||
var commandQueue: MTLCommandQueue
|
||||
|
||||
init() {
|
||||
guard let device = MTLCreateSystemDefaultDevice(),
|
||||
let commandQueue = device.makeCommandQueue() else {
|
||||
fatalError("GPU not available")
|
||||
}
|
||||
self.device = device
|
||||
self.commandQueue = commandQueue
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 9.0, *)
|
||||
protocol Renderer {
|
||||
var device: MTLDevice { get }
|
||||
var commandQueue: MTLCommandQueue { get }
|
||||
var mesh: MTKMesh? { get set }
|
||||
var vertexBuffer: MTLBuffer? { get set }
|
||||
var pipelineState: MTLRenderPipelineState? { get set }
|
||||
|
||||
var vertexShaderName: String { get }
|
||||
var fragmentShaderName: String { get }
|
||||
|
||||
func getMesh() -> MDLMesh
|
||||
func load(metalView: MTKView)
|
||||
func configure(renderEncoder: MTLRenderCommandEncoder) -> MTLRenderCommandEncoder?
|
||||
}
|
||||
|
||||
@available(iOS 9.0, *)
|
||||
extension Renderer {
|
||||
var device: MTLDevice {
|
||||
return MetalDevice.shared.device
|
||||
}
|
||||
|
||||
var commandQueue: MTLCommandQueue {
|
||||
return MetalDevice.shared.commandQueue
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: MTKViewDelegate
|
||||
@available(iOS 9.0, *)
|
||||
extension Renderer {
|
||||
//Called once per frame, regenerate the command buffer
|
||||
func draw(metalView view: MTKView) {
|
||||
guard let descriptor = view.currentRenderPassDescriptor,
|
||||
let commandBuffer = self.commandQueue.makeCommandBuffer(),
|
||||
let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor),
|
||||
let configuredEncoder = configure(renderEncoder: renderEncoder) else {
|
||||
return
|
||||
}
|
||||
|
||||
//drawing code goes here
|
||||
configuredEncoder.endEncoding()
|
||||
|
||||
guard let drawable = view.currentDrawable else {
|
||||
return
|
||||
}
|
||||
|
||||
//Present and commit the drawable texture to the GPU
|
||||
commandBuffer.present(drawable)
|
||||
commandBuffer.commit()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
//
|
||||
// Renderer.swift
|
||||
// MetalTutoral
|
||||
//
|
||||
// Created by developer on 10/22/19.
|
||||
// Copyright © 2019 developer. All rights reserved.
|
||||
//
|
||||
|
||||
import MetalKit
|
||||
|
||||
@available(iOS 9.0, *)
|
||||
class TriangleRenderer: NSObject, Renderer {
|
||||
var mesh: MTKMesh?
|
||||
var vertexBuffer: MTLBuffer?
|
||||
var pipelineState: MTLRenderPipelineState?
|
||||
|
||||
internal var vertexShaderName: String = "vertex_main_moving"
|
||||
internal var fragmentShaderName: String = "fragment_main"
|
||||
var timer: Float = 0
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
let mdlMesh = getMesh()
|
||||
|
||||
do{
|
||||
mesh = try MTKMesh(mesh: mdlMesh, device: device)
|
||||
} catch let error {
|
||||
print(error.localizedDescription)
|
||||
}
|
||||
|
||||
vertexBuffer = mesh?.vertexBuffers[0].buffer
|
||||
|
||||
}
|
||||
|
||||
func getMesh() -> MDLMesh {
|
||||
return Primitive.makeTriangle(device: device, size: 1)
|
||||
}
|
||||
|
||||
func load(metalView: MTKView) {
|
||||
let library = device.makeDefaultLibrary()
|
||||
let vertexFunction = library?.makeFunction(name: vertexShaderName)
|
||||
let fragmentFunction = library?.makeFunction(name: fragmentShaderName)
|
||||
|
||||
let pipelineDescriptor = MTLRenderPipelineDescriptor()
|
||||
pipelineDescriptor.vertexFunction = vertexFunction
|
||||
pipelineDescriptor.fragmentFunction = fragmentFunction
|
||||
|
||||
if let mesh = mesh {
|
||||
pipelineDescriptor.vertexDescriptor = MTKMetalVertexDescriptorFromModelIO(mesh.vertexDescriptor)
|
||||
}
|
||||
pipelineDescriptor.colorAttachments[0].pixelFormat = metalView.colorPixelFormat
|
||||
do {
|
||||
pipelineState = try device.makeRenderPipelineState(descriptor: pipelineDescriptor)
|
||||
} catch let error {
|
||||
fatalError(error.localizedDescription)
|
||||
}
|
||||
|
||||
// Protocol
|
||||
metalView.clearColor = MTLClearColor(red: 1, green: 1, blue: 0.8, alpha: 1)
|
||||
metalView.delegate = self
|
||||
}
|
||||
|
||||
func configure(renderEncoder: MTLRenderCommandEncoder) -> MTLRenderCommandEncoder? {
|
||||
guard let pipelineState = pipelineState,
|
||||
let mesh = mesh else {
|
||||
return nil
|
||||
}
|
||||
timer += 0.05
|
||||
var currentTime = sin(timer)
|
||||
var al = abs(currentTime)
|
||||
renderEncoder.setVertexBytes(¤tTime,
|
||||
length: MemoryLayout<Float>.stride,
|
||||
index: 1)
|
||||
renderEncoder.setFragmentBytes(&al,
|
||||
length: MemoryLayout<Float>.stride,
|
||||
index: 0)
|
||||
|
||||
renderEncoder.setRenderPipelineState(pipelineState)
|
||||
renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
|
||||
|
||||
for submesh in mesh.submeshes {
|
||||
renderEncoder.drawIndexedPrimitives(type: .triangle,
|
||||
indexCount: submesh.indexCount,
|
||||
indexType: submesh.indexType,
|
||||
indexBuffer: submesh.indexBuffer.buffer,
|
||||
indexBufferOffset: submesh.indexBuffer.offset)
|
||||
|
||||
}
|
||||
|
||||
return renderEncoder
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 9.0, *)
|
||||
extension TriangleRenderer: MTKViewDelegate {
|
||||
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
func draw(in view: MTKView) {
|
||||
draw(metalView: view)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// Shaders.metal
|
||||
// MetalTutoral
|
||||
//
|
||||
// Created by developer on 10/22/19.
|
||||
// Copyright © 2019 developer. All rights reserved.
|
||||
//
|
||||
|
||||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
// Describes vertex attributes that match the descriptor
|
||||
struct VertexIn {
|
||||
float4 position [[attribute(0)]];
|
||||
};
|
||||
|
||||
// Implement a vertex shader that returns the vertices passed in as a float4
|
||||
vertex float4 vertex_main_moving(const VertexIn vertexIn [[stage_in]], constant float &timer [[ buffer(1) ]]) {
|
||||
float4 position = vertexIn.position;
|
||||
position.x *= cos(timer);
|
||||
position.y *= sin(timer);
|
||||
return position;
|
||||
}
|
||||
|
||||
vertex float4 vertex_main(const VertexIn vertexIn [[stage_in]]) {
|
||||
float4 position = vertexIn.position;
|
||||
return position;
|
||||
}
|
||||
|
||||
fragment float4 fragment_main() {
|
||||
return float4(1, 0, 0, 1);
|
||||
}
|
||||
|
||||
fragment float4 fragment_main_test() {
|
||||
return float4(1, 1, 0, 1);
|
||||
}
|
||||
|
||||
//fragment float4 fragment_main_change(VertexOut in [[stage_in]]) {
|
||||
// return float4(in.normal, 1);
|
||||
//}
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// MetalView.swift
|
||||
// SwiftUIKit
|
||||
//
|
||||
// Created by Zach Eriksen on 1/19/20.
|
||||
//
|
||||
|
||||
import MetalKit
|
||||
|
||||
@available(iOS 9.0, *)
|
||||
class MetalView: MTKView {
|
||||
private var renderer: Renderer
|
||||
|
||||
init(renderer: Renderer) {
|
||||
self.renderer = renderer
|
||||
|
||||
super.init(frame: .zero, device: renderer.device)
|
||||
|
||||
self.renderer.load(metalView: self)
|
||||
}
|
||||
|
||||
required init(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue