diff --git a/Metaballs/Renderer.swift b/Metaballs/Renderer.swift index b9801c0..a7d8ee0 100644 --- a/Metaballs/Renderer.swift +++ b/Metaballs/Renderer.swift @@ -86,22 +86,29 @@ class Renderer: NSObject, MTKViewDelegate { Vertex(position: Point(x: 1, y: 1), textureCoordinate: Point(x: 1, y: 1)) ] - let buffer = commandQueue.makeCommandBuffer() - buffer.label = "Compute + Render" - do { - let _ = try field.computeEncoderForSamplingKernel(withDevice: device, commandBuffer: buffer) + try field.updateBuffers() } catch let e { - print("\(e)") + NSLog("Error updating buffers: \(e)") } + let buffer = commandQueue.makeCommandBuffer() + buffer.label = "Render" + +// do { +// let _ = try field.computeEncoderForSamplingKernel(withDevice: device, commandBuffer: buffer) +// } catch let e { +// print("\(e)") +// } + if let renderPass = view.currentRenderPassDescriptor { let encoder = buffer.makeRenderCommandEncoder(descriptor: renderPass) encoder.label = "Render Pass" encoder.setViewport(MTLViewport(originX: 0.0, originY: 0.0, width: Double(view.drawableSize.width), height: Double(view.drawableSize.height), znear: -1.0, zfar: 1.0)) encoder.setRenderPipelineState(renderPipelineState) - encoder.setVertexBytes(points, length: points.count * MemoryLayout.size, at: 0) - encoder.setFragmentTexture(field.sampleTexture, at: 0) + encoder.setVertexBytes(points, length: points.count * MemoryLayout.stride, at: 0) + encoder.setFragmentBuffer(field.parametersBuffer, offset: 0, at: 0) + encoder.setFragmentBuffer(field.ballBuffer, offset: 0, at: 1) encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 6) encoder.endEncoding() diff --git a/Metaballs/Shaders.metal b/Metaballs/Shaders.metal index 1f0b2b2..f59abc4 100644 --- a/Metaballs/Shaders.metal +++ b/Metaballs/Shaders.metal @@ -24,6 +24,13 @@ typedef struct { float2 textureCoordinate; } RasterizerData; +typedef struct { + int2 size; + int numberOfBalls; +} Parameters; + +typedef half3 Ball; + vertex RasterizerData passthroughVertexShader(uint vid [[vertex_id]], constant Vertex* vertexes [[buffer(0)]]) @@ -35,19 +42,36 @@ passthroughVertexShader(uint vid [[vertex_id]], return out; } +float sampleAtPoint(float2, constant Ball*, uint); + fragment float4 -sampleToColorShader(RasterizerData in [[stage_in]], - texture2d samples [[texture(0)]]) +sampleToColorShader(RasterizerData in [[stage_in]], + constant Parameters& parameters [[buffer(0)]], + constant Ball* balls [[buffer(1)]]) { - constexpr sampler textureSampler(mag_filter::linear, min_filter::linear); - const half4 sample = samples.sample(textureSampler, in.textureCoordinate); + const float sample = sampleAtPoint(in.textureCoordinate, balls, parameters.numberOfBalls); float4 out; - if (sample.r > 1.0) { + if (sample > 1.0) { out = float4(0.0, 1.0, 0.0, 0.0); - } - else { + } else { out = float4(0.0, 0.0, 0.0, 0.0); } return out; } + +float +sampleAtPoint(float2 point, + constant Ball* balls, + uint count) +{ + float sample = 0.0; + for (uint i = 0; i < count; i++) { + constant Ball& ball = balls[i]; + float r2 = ball.z * ball.z; // Radius stored in z coordinate. + float xDiff = point.x - ball.x; + float yDiff = point.y - ball.y; + sample += r2 / ((xDiff * xDiff) + (yDiff * yDiff)); + } + return sample; +}