@@ -1,5 +1,3 @@
1−// TODO: Make shader ignore metaballs that are outside a certain area of tolerance (eg ±100 from borders)
3// TODO: Metaballs from texture to buffer
1// TODO: Metaballs from texture to buffer
4// TODO: Use async dispatch to free up main queue
2// TODO: Use async dispatch to free up main queue
5// TODO: Refactor update into 2 calls: metalRendering() and textureToImage()
3// TODO: Refactor update into 2 calls: metalRendering() and textureToImage()
@@ -62,7 +60,7 @@ class MetalMetaballRenderer: MetaballRenderer {
62 height / threadGroupCounts.height, 1)
60 height / threadGroupCounts.height, 1)
64 // Create up-to-date metaball buffer
62 // Create up-to-date metaball buffer
65− let metaballInfoTexture = metaballTexture(metaballs)
63+ let metaballInfoBuffer = metaballBuffer(metaballs)
67 // Send commands to metal and render
65 // Send commands to metal and render
68 let commandBuffer = context.commandQueue.commandBuffer()
66 let commandBuffer = context.commandQueue.commandBuffer()
@@ -70,7 +68,7 @@ class MetalMetaballRenderer: MetaballRenderer {
70 let commandEncoder = commandBuffer.computeCommandEncoder()
68 let commandEncoder = commandBuffer.computeCommandEncoder()
71 commandEncoder.setComputePipelineState(pipeline)
69 commandEncoder.setComputePipelineState(pipeline)
72 commandEncoder.setTexture(renderingTexture, atIndex: 0)
70 commandEncoder.setTexture(renderingTexture, atIndex: 0)
73− commandEncoder.setTexture(metaballInfoTexture, atIndex: 1)
71+ commandEncoder.setBuffer(metaballInfoBuffer, offset: 0, atIndex: 0)
74 commandEncoder.dispatchThreadgroups(threadGroups,
72 commandEncoder.dispatchThreadgroups(threadGroups,
75 threadsPerThreadgroup: threadGroupCounts)
73 threadsPerThreadgroup: threadGroupCounts)
76 commandEncoder.endEncoding()
74 commandEncoder.endEncoding()
@@ -127,7 +125,7 @@ class MetalMetaballRenderer: MetaballRenderer {
127 return image
125 return image
130− func metaballTexture(metaballs: [Metaball]) -> MTLTexture {
128+ func metaballBuffer(metaballs: [Metaball]) -> MTLBuffer {
131 // Create Float array for buffer
129 // Create Float array for buffer
132 // Exclude metaballs far from the view's bounds
130 // Exclude metaballs far from the view's bounds
133 let border: CGFloat = 100
131 let border: CGFloat = 100
@@ -144,19 +142,10 @@ class MetalMetaballRenderer: MetaballRenderer {
144 // Add array size to start of array so metal knows how far to go
142 // Add array size to start of array so metal knows how far to go
145 floats[0] = Float(floats.count) / 2
143 floats[0] = Float(floats.count) / 2
147− // Create texture
145+ // Create buffer
148− let size = floats.count
146+ let buffer = context.device.newBufferWithBytes(floats, length: floats.count * sizeof(Float), options: .StorageModeShared)
149− let textureDescriptor =
147+
150− MTLTextureDescriptor.texture2DDescriptorWithPixelFormat(
151− .R32Float, width: size, height: 1, mipmapped: false)
152− let texture = context.device.newTextureWithDescriptor(textureDescriptor)
154− // Copy array info into texture
155− let region = MTLRegionMake2D(0, 0, size, 1)
156− texture.replaceRegion(region, mipmapLevel: 0, withBytes: floats,
157− bytesPerRow: sizeof(Float) * size)
159− return texture
148+ return buffer
162 func updateFrame() {
151 func updateFrame() {