updated to Swift 4
This commit is contained in:
parent
bc61d4f939
commit
2b3a0dce76
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
import MetalKit
|
||||||
|
import PlaygroundSupport
|
||||||
|
|
||||||
|
let frame = NSRect(x: 0, y: 0, width: 400, height: 400)
|
||||||
|
let delegate = MetalViewDelegate()
|
||||||
|
let view = MTKView(frame: frame, device: delegate.device)
|
||||||
|
view.clearColor = MTLClearColor(red: 0.9, green: 0.9, blue: 0.9, alpha: 1)
|
||||||
|
view.delegate = delegate
|
||||||
|
PlaygroundPage.current.liveView = view
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
|
||||||
|
#include <metal_stdlib>
|
||||||
|
using namespace metal;
|
||||||
|
|
||||||
|
struct VertexIn {
|
||||||
|
float4 position [[attribute(0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertexOut {
|
||||||
|
float4 position [[position]];
|
||||||
|
float4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Particle {
|
||||||
|
float4x4 initial_matrix;
|
||||||
|
float4x4 matrix;
|
||||||
|
float4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
vertex VertexOut vertex_main(const VertexIn vertex_in [[stage_in]],
|
||||||
|
constant Particle *particles [[buffer(1)]],
|
||||||
|
uint instanceid [[instance_id]]) {
|
||||||
|
VertexOut vertex_out;
|
||||||
|
Particle particle = particles[instanceid];
|
||||||
|
vertex_out.position = particle.matrix * vertex_in.position ;
|
||||||
|
vertex_out.color = particle.color;
|
||||||
|
return vertex_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment float4 fragment_main(VertexOut vertex_in [[stage_in]]) {
|
||||||
|
return vertex_in.color;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
|
||||||
|
import MetalKit
|
||||||
|
|
||||||
|
public class MetalViewDelegate: NSObject, MTKViewDelegate {
|
||||||
|
|
||||||
|
public var device: MTLDevice!
|
||||||
|
var queue: MTLCommandQueue!
|
||||||
|
var pipelineState: MTLRenderPipelineState!
|
||||||
|
var model: MTKMesh!
|
||||||
|
var particles: [Particle]!
|
||||||
|
var particlesBuffer: MTLBuffer!
|
||||||
|
var timer: Float = 0
|
||||||
|
|
||||||
|
struct Particle {
|
||||||
|
var initialMatrix = matrix_identity_float4x4
|
||||||
|
var matrix = matrix_identity_float4x4
|
||||||
|
var color = float4()
|
||||||
|
}
|
||||||
|
|
||||||
|
override public init() {
|
||||||
|
super.init()
|
||||||
|
initializeMetal()
|
||||||
|
}
|
||||||
|
|
||||||
|
func initializeBuffers() {
|
||||||
|
particles = [Particle](repeatElement(Particle(), count: 1000))
|
||||||
|
particlesBuffer = device.makeBuffer(length: particles.count * MemoryLayout<Particle>.stride, options: [])!
|
||||||
|
var pointer = particlesBuffer.contents().bindMemory(to: Particle.self, capacity: particles.count)
|
||||||
|
for _ in particles.enumerated() {
|
||||||
|
pointer.pointee.initialMatrix = translate(by: [Float(drand48()) / 10, Float(drand48()) * 10, 0])
|
||||||
|
pointer.pointee.color = float4(0.2, 0.6, 0.9, 1)
|
||||||
|
pointer = pointer.advanced(by: 1)
|
||||||
|
}
|
||||||
|
let allocator = MTKMeshBufferAllocator(device: device)
|
||||||
|
let sphere = MDLMesh(sphereWithExtent: [0.01, 0.01, 0.01], segments: [8, 8], inwardNormals: false, geometryType: .triangles, allocator: allocator)
|
||||||
|
do {
|
||||||
|
model = try MTKMesh(mesh: sphere, device: device)
|
||||||
|
} catch let e {
|
||||||
|
Swift.print("\(e)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initializeMetal() {
|
||||||
|
device = MTLCreateSystemDefaultDevice()
|
||||||
|
queue = device.makeCommandQueue()
|
||||||
|
initializeBuffers()
|
||||||
|
let library: MTLLibrary
|
||||||
|
do {
|
||||||
|
let path = Bundle.main.path(forResource: "Shaders", ofType: "metal")
|
||||||
|
let source = try String(contentsOfFile: path!, encoding: .utf8)
|
||||||
|
library = try device.makeLibrary(source: source, options: nil)
|
||||||
|
let descriptor = MTLRenderPipelineDescriptor()
|
||||||
|
descriptor.colorAttachments[0].pixelFormat = .bgra8Unorm
|
||||||
|
descriptor.vertexFunction = library.makeFunction(name: "vertex_main")
|
||||||
|
descriptor.fragmentFunction = library.makeFunction(name: "fragment_main")
|
||||||
|
descriptor.vertexDescriptor = MTKMetalVertexDescriptorFromModelIO(model.vertexDescriptor)
|
||||||
|
pipelineState = try device.makeRenderPipelineState(descriptor: descriptor)
|
||||||
|
} catch let error as NSError {
|
||||||
|
fatalError("library error: " + error.description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func translate(by: float3) -> float4x4 {
|
||||||
|
return float4x4(columns: (
|
||||||
|
float4( 1, 0, 0, 0),
|
||||||
|
float4( 0, 1, 0, 0),
|
||||||
|
float4( 0, 0, 1, 0),
|
||||||
|
float4( by.x, by.y, by.z, 1)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
func update() {
|
||||||
|
timer += 0.01
|
||||||
|
var pointer = particlesBuffer.contents().bindMemory(to: Particle.self, capacity: particles.count)
|
||||||
|
for _ in particles {
|
||||||
|
pointer.pointee.matrix = translate(by: [0, -3 * timer, 0]) * pointer.pointee.initialMatrix
|
||||||
|
pointer = pointer.advanced(by: 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { }
|
||||||
|
|
||||||
|
public func draw(in view: MTKView) {
|
||||||
|
update()
|
||||||
|
guard let commandBuffer = queue.makeCommandBuffer(),
|
||||||
|
let descriptor = view.currentRenderPassDescriptor,
|
||||||
|
let commandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor),
|
||||||
|
let drawable = view.currentDrawable else { fatalError() }
|
||||||
|
let submesh = model.submeshes[0]
|
||||||
|
commandEncoder.setRenderPipelineState(pipelineState)
|
||||||
|
commandEncoder.setVertexBuffer(model.vertexBuffers[0].buffer, offset: 0, index: 0)
|
||||||
|
commandEncoder.setVertexBuffer(particlesBuffer, offset: 0, index: 1)
|
||||||
|
commandEncoder.drawIndexedPrimitives(type: .triangle, indexCount: submesh.indexCount, indexType: submesh.indexType, indexBuffer: submesh.indexBuffer.buffer, indexBufferOffset: 0, instanceCount: particles.count)
|
||||||
|
commandEncoder.endEncoding()
|
||||||
|
commandBuffer.present(drawable)
|
||||||
|
commandBuffer.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<playground version='5.0' target-platform='macos' executeOnSourceChanges='false'>
|
||||||
|
<timeline fileName='timeline.xctimeline'/>
|
||||||
|
</playground>
|
||||||
7
particles/particle2.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
particles/particle2.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
Binary file not shown.
Loading…
Reference in New Issue