Skip to content

Instantly share code, notes, and snippets.

@menangen
Last active October 27, 2019 19:38
Show Gist options
  • Save menangen/3d35ad28679471f318acd1d5e3ccc1d4 to your computer and use it in GitHub Desktop.
Save menangen/3d35ad28679471f318acd1d5e3ccc1d4 to your computer and use it in GitHub Desktop.
MetalKIT
import Cocoa
import MetalKit
// Our macOS specific view controller
class GameViewController: NSViewController {
var renderer: Renderer!
var mtkView: MTKView!
override func viewDidLoad() {
super.viewDidLoad()
guard let mtkView = self.view as? MTKView else {
print("View attached to GameViewController is not an MTKView")
return
}
// Select the device to render with. We choose the default device
guard let defaultDevice = MTLCreateSystemDefaultDevice() else {
print("Metal is not supported on this device")
return
}
mtkView.device = defaultDevice
mtkView.preferredFramesPerSecond = 1
mtkView.framebufferOnly = false
guard let newRenderer = Renderer(metalKitView: mtkView) else {
print("Renderer cannot be initialized")
return
}
renderer = newRenderer
renderer.mtkView(mtkView, drawableSizeWillChange: mtkView.drawableSize)
mtkView.delegate = renderer
}
}
import MetalKit
class Renderer: NSObject, MTKViewDelegate {
public let device: MTLDevice
let commandQueue: MTLCommandQueue
var pipelineState: MTLRenderPipelineState!
var ctxImage: CIContext!
var fpsCount = 0
init?(metalKitView: MTKView) {
self.device = metalKitView.device!
self.commandQueue = self.device.makeCommandQueue()!
self.ctxImage = CIContext(mtlDevice: self.device)
super.init()
}
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
}
func draw(in view: MTKView) {
let commandBuffer = commandQueue.makeCommandBuffer()
let image = NSImage(named: "Ground")?.cgImage(forProposedRect: nil, context: nil, hints: nil)
let texture = view.currentDrawable!.texture
self.ctxImage.render(
CIImage(cgImage: image!),
to: texture,
commandBuffer: commandBuffer,
bounds:
CGRect(
origin: CGPoint(x: 20 + fpsCount, y: 20),
size: CGSize(width: 128, height: 128)),
colorSpace: CGColorSpaceCreateDeviceRGB()
)
commandBuffer!.present(view.currentDrawable!)
commandBuffer!.commit()
fpsCount += 1
}
}
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct VertexIn {
packed_float3 position;
packed_float3 color;
};
struct VertexOut {
float4 position [[position]];
float4 color;
};
vertex VertexOut vertex_main(device const VertexIn *vertices [[buffer(0)]],
uint vertexId [[vertex_id]]) {
VertexOut out;
out.position = float4(vertices[vertexId].position, 1);
out.color = float4(vertices[vertexId].color, 1);
return out;
}
fragment float4 fragment_main(VertexOut in [[stage_in]]) {
return in.color;
}
// Created by menangen on 02.11.2018.
// Our platform independent renderer class
import MetalKit
class TriangleRenderer: NSObject, MTKViewDelegate {
public let device: MTLDevice
let commandQueue: MTLCommandQueue
var pipelineState: MTLRenderPipelineState!
var fpsCount: Float = 0.0
init?(metalKitView: MTKView) {
self.device = metalKitView.device!
self.commandQueue = self.device.makeCommandQueue()!
let library = device.makeDefaultLibrary()
let pipelineDescriptor = MTLRenderPipelineDescriptor()
pipelineDescriptor.colorAttachments[0].pixelFormat = metalKitView.colorPixelFormat
pipelineDescriptor.vertexFunction = library!.makeFunction(name: "vertex_main")
pipelineDescriptor.fragmentFunction = library!.makeFunction(name: "fragment_main")
pipelineDescriptor.sampleCount = 4
do {
pipelineState = try device.makeRenderPipelineState(descriptor: pipelineDescriptor)
} catch {
print("Error with device.makeRenderPipelineState")
}
super.init()
}
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
}
func draw(in view: MTKView) {
guard let commandBuffer = commandQueue.makeCommandBuffer() else { return }
guard let passDescriptor = view.currentRenderPassDescriptor else { return }
guard let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: passDescriptor) else { return }
let vertexData: [Float] = [
-1.0, 0.0, 0,
0 + self.fpsCount, 1.0 - self.fpsCount, 0.25 + self.fpsCount,
-1.0, 1.0, 0,
0 + self.fpsCount * 0.5, self.fpsCount, 0.75,
0.0, 1.0, 0,
0 + self.fpsCount * 0.2, 0.15 + self.fpsCount * 0.5, 1.0 - self.fpsCount,
-1.0, 0.0, 0,
0.0 + self.fpsCount, 0, 0.0 + self.fpsCount,
0.0, 0.0, 0,
0.2 + self.fpsCount * 0.5, 0.0 + self.fpsCount, 1.0 - self.fpsCount,
0.0, 1.0, 0,
0.2 + self.fpsCount * 0.5, 0.2 + self.fpsCount * 0.5, 1.0 - self.fpsCount
/*
-1.0, -1.0, 0,
0 + self.fpsCount, 1.0 - self.fpsCount, 0.25 + self.fpsCount,
-1.0, 1.0, 0,
0 + self.fpsCount * 0.5, self.fpsCount, 0.75,
1.0, -1.0, 0,
0 + self.fpsCount * 0.2, 0.15 + self.fpsCount * 0.5, 1.0 - self.fpsCount,
-1.0, 1.0, 0,
0.0 + self.fpsCount, 0, 0.0 + self.fpsCount,
1.0, -1.0, 0,
0.2 + self.fpsCount * 0.5, 0.0 + self.fpsCount, 1.0 - self.fpsCount,
1.0, 1.0, 0,
0.2 + self.fpsCount * 0.5, 0.2 + self.fpsCount * 0.5, 1.0 - self.fpsCount*/
]
encoder.setVertexBytes(vertexData, length: vertexData.count * MemoryLayout<Float>.stride, index: 0)
encoder.setRenderPipelineState(pipelineState)
encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 6)
encoder.endEncoding()
commandBuffer.present(view.currentDrawable!)
commandBuffer.commit()
self.fpsCount += 0.001
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment