From c3419336fa5438363e3eae39ba9abd7b68a16346 Mon Sep 17 00:00:00 2001 From: Marius Horga Date: Fri, 30 Dec 2016 15:51:16 +0200 Subject: [PATCH 1/2] added raymarching --- README.md | 39 +++++++------ .../raymarching.playground/Contents.swift | 9 +++ .../Resources/Shaders.metal | 54 ++++++++++++++++++ .../Sources/MetalView.swift | 52 +++++++++++++++++ .../contents.xcplayground | 4 ++ .../contents.xcworkspacedata | 7 +++ .../UserInterfaceState.xcuserstate | Bin 0 -> 19416 bytes .../timeline.xctimeline | 6 ++ 8 files changed, 152 insertions(+), 19 deletions(-) create mode 100644 raymarching/raymarching.playground/Contents.swift create mode 100755 raymarching/raymarching.playground/Resources/Shaders.metal create mode 100755 raymarching/raymarching.playground/Sources/MetalView.swift create mode 100644 raymarching/raymarching.playground/contents.xcplayground create mode 100755 raymarching/raymarching.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100755 raymarching/raymarching.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 raymarching/raymarching.playground/timeline.xctimeline diff --git a/README.md b/README.md index e021d1a..d0aa377 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,23 @@ # Metal Repository to accompany the following blog posts: -- [Introducing the Metal framework](http://mhorga.org/2016/01/04/introducing-the-metal-framework.html) -- [Using MetalKit part 1](http://mhorga.org/2016/01/11/using-metalkit-part-1.html) -- [Using MetalKit part 2](http://mhorga.org/2016/01/18/using-metalkit-part-2.html) -- [Using MetalKit part 3](http://mhorga.org/2016/01/25/using-metalkit-part-3.html) -- [Using MetalKit part 4](http://mhorga.org/2016/02/01/using-metalkit-part-4.html) -- [Using MetalKit part 5](http://mhorga.org/2016/02/08/using-metalkit-part-5.html) -- [Using MetalKit part 6](http://mhorga.org/2016/02/15/using-metalkit-part-6.html) -- [Using MetalKit part 7](http://mhorga.org/2016/02/29/using-metalkit-part-7.html) -- [Using MetalKit part 8](http://mhorga.org/2016/03/07/using-metalkit-part-8.html) -- [Using MetalKit part 9](http://mhorga.org/2016/04/18/using-metalkit-part-9.html) -- [Using MetalKit part 10](http://mhorga.org/2016/05/02/using-metalkit-part-10.html) -- [Using MetalKit part 11](http://mhorga.org/2016/05/10/using-metalkit-part-11.html) -- [Using MetalKit part 12](http://mhorga.org/2016/05/18/using-metalkit-part-12.html) -- [Using MetalKit part 13](http://mhorga.org/2016/05/25/using-metalkit-part-13.html) -- [Using MetalKit part 14](http://mhorga.org/2016/06/01/using-metalkit-part-14.html) -- [Using MetalKit part 15](http://mhorga.org/2016/06/23/using-metalkit-part-15.html) -- [Using MetalKit part 16](http://mhorga.org/2016/07/06/using-metalkit-part-16.html) -- [Using MetalKit part 17](http://mhorga.org/2016/09/24/using-metalkit-part-17.html) -- [Using MetalKit part 18](http://mhorga.org/2016/09/30/using-metalkit-part-2-3-2.html) +- [Introducing the Metal framework](http://metalkit.org/2016/01/04/introducing-the-metal-framework.html) +- [Using MetalKit part 1](http://metalkit.org/2016/01/11/using-metalkit-part-1.html) +- [Using MetalKit part 2](http://metalkit.org/2016/01/18/using-metalkit-part-2.html) +- [Using MetalKit part 3](http://metalkit.org/2016/01/25/using-metalkit-part-3.html) +- [Using MetalKit part 4](http://metalkit.org/2016/02/01/using-metalkit-part-4.html) +- [Using MetalKit part 5](http://metalkit.org/2016/02/08/using-metalkit-part-5.html) +- [Using MetalKit part 6](http://metalkit.org/2016/02/15/using-metalkit-part-6.html) +- [Using MetalKit part 7](http://metalkit.org/2016/02/29/using-metalkit-part-7.html) +- [Using MetalKit part 8](http://metalkit.org/2016/03/07/using-metalkit-part-8.html) +- [Using MetalKit part 9](http://metalkit.org/2016/04/18/using-metalkit-part-9.html) +- [Using MetalKit part 10](http://metalkit.org/2016/05/02/using-metalkit-part-10.html) +- [Using MetalKit part 11](http://metalkit.org/2016/05/10/using-metalkit-part-11.html) +- [Using MetalKit part 12](http://metalkit.org/2016/05/18/using-metalkit-part-12.html) +- [Using MetalKit part 13](http://metalkit.org/2016/05/25/using-metalkit-part-13.html) +- [Using MetalKit part 14](http://metalkit.org/2016/06/01/using-metalkit-part-14.html) +- [Using MetalKit part 15](http://metalkit.org/2016/06/23/using-metalkit-part-15.html) +- [Using MetalKit part 16](http://metalkit.org/2016/07/06/using-metalkit-part-16.html) +- [Using MetalKit part 17](http://metalkit.org/2016/09/24/using-metalkit-part-17.html) +- [Using MetalKit part 18](http://metalkit.org/2016/10/01/using-metalkit-part-2-3-2.html) +- [Raymarching in Metal](http://metalkit.org/2016/12/29/raymarching-in-metal.html) \ No newline at end of file diff --git a/raymarching/raymarching.playground/Contents.swift b/raymarching/raymarching.playground/Contents.swift new file mode 100644 index 0000000..d12f060 --- /dev/null +++ b/raymarching/raymarching.playground/Contents.swift @@ -0,0 +1,9 @@ + +import MetalKit +import PlaygroundSupport + +let frame = NSRect(x: 0, y: 0, width: 300, height: 300) +let delegate = MetalView() +let view = MTKView(frame: frame, device: delegate.device) +view.delegate = delegate +PlaygroundPage.current.liveView = view diff --git a/raymarching/raymarching.playground/Resources/Shaders.metal b/raymarching/raymarching.playground/Resources/Shaders.metal new file mode 100755 index 0000000..e5e2ff3 --- /dev/null +++ b/raymarching/raymarching.playground/Resources/Shaders.metal @@ -0,0 +1,54 @@ + +#include +using namespace metal; + +struct Ray { + float3 origin; + float3 direction; + Ray(float3 o, float3 d) { + origin = o; + direction = d; + } +}; + +struct Sphere { + float3 center; + float radius; + Sphere(float3 c, float r) { + center = c; + radius = r; + } +}; + +float distToSphere(Ray ray, Sphere s) { + return length(ray.origin - s.center) - s.radius; +} + +float distToScene(Ray r) { + Sphere s = Sphere(float3(1.), 0.5); + Ray repeatRay = r; + repeatRay.origin = fmod(r.origin, 2.0); + return distToSphere(repeatRay, s); +} + +kernel void compute(texture2d output [[texture(0)]], + constant float &time [[buffer(0)]], + uint2 gid [[thread_position_in_grid]]) { + int width = output.get_width(); + int height = output.get_height(); + float2 uv = float2(gid) / float2(width, height); + uv = uv * 2.0 - 1.0; + float3 camPos = float3(1000. + sin(time) + 1., 1000. + cos(time) + 1., time); + Ray ray = Ray(camPos, normalize(float3(uv, 1.))); + float3 col = float3(0.); + for (int i=0.; i<100.; i++) { + float dist = distToScene(ray); + if (dist < 0.001) { + col = float3(1.); + break; + } + ray.origin += ray.direction * dist; + } + float3 posRelativeToCamera = ray.origin - camPos; + output.write(float4(col * abs((posRelativeToCamera) / 10.0), 1.), gid); +} diff --git a/raymarching/raymarching.playground/Sources/MetalView.swift b/raymarching/raymarching.playground/Sources/MetalView.swift new file mode 100755 index 0000000..19203f9 --- /dev/null +++ b/raymarching/raymarching.playground/Sources/MetalView.swift @@ -0,0 +1,52 @@ + +import MetalKit + +public class MetalView: NSObject, MTKViewDelegate { + + public var device: MTLDevice! + var queue: MTLCommandQueue! + var cps: MTLComputePipelineState! + var time: Float = 0 + var timeBuffer: MTLBuffer! + + override public init() { + super.init() + registerShaders() + } + + func registerShaders() { + device = MTLCreateSystemDefaultDevice()! + queue = device.makeCommandQueue() + let path = Bundle.main.path(forResource: "Shaders", ofType: "metal") + do { + let input = try String(contentsOfFile: path!, encoding: String.Encoding.utf8) + let library = try device.makeLibrary(source: input, options: nil) + let kernel = library.makeFunction(name: "compute")! + cps = try device.makeComputePipelineState(function: kernel) + } catch let e { + Swift.print("\(e)") + } + timeBuffer = device!.makeBuffer(length: MemoryLayout.size, options: []) + } + + public func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {} + + public func draw(in view: MTKView) { + if let drawable = view.currentDrawable { + let commandBuffer = queue.makeCommandBuffer() + let commandEncoder = commandBuffer.makeComputeCommandEncoder() + commandEncoder.setComputePipelineState(cps) + commandEncoder.setTexture(drawable.texture, at: 0) + commandEncoder.setBuffer(timeBuffer, offset: 0, at: 0) + time += 0.01 + let bufferPointer = timeBuffer.contents() + memcpy(bufferPointer, &time, MemoryLayout.size) + let threadGroupCount = MTLSizeMake(8, 8, 1) + let threadGroups = MTLSizeMake(drawable.texture.width / threadGroupCount.width, drawable.texture.height / threadGroupCount.height, 1) + commandEncoder.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount) + commandEncoder.endEncoding() + commandBuffer.present(drawable) + commandBuffer.commit() + } + } +} diff --git a/raymarching/raymarching.playground/contents.xcplayground b/raymarching/raymarching.playground/contents.xcplayground new file mode 100644 index 0000000..9f9eecc --- /dev/null +++ b/raymarching/raymarching.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/raymarching/raymarching.playground/playground.xcworkspace/contents.xcworkspacedata b/raymarching/raymarching.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..919434a --- /dev/null +++ b/raymarching/raymarching.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/raymarching/raymarching.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/raymarching/raymarching.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100755 index 0000000000000000000000000000000000000000..94f3cc32c6326f80bd2c9348b08d5674a0bcb025 GIT binary patch literal 19416 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 q!M@Y}nthjjkNpk%+xB + + + + From 8192c344e7811de5f81707e45b0a7ed64397d289 Mon Sep 17 00:00:00 2001 From: Marius Horga Date: Fri, 30 Dec 2016 15:52:51 +0200 Subject: [PATCH 2/2] added raymarching --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d0aa377..b7abaae 100644 --- a/README.md +++ b/README.md @@ -20,4 +20,4 @@ Repository to accompany the following blog posts: - [Using MetalKit part 16](http://metalkit.org/2016/07/06/using-metalkit-part-16.html) - [Using MetalKit part 17](http://metalkit.org/2016/09/24/using-metalkit-part-17.html) - [Using MetalKit part 18](http://metalkit.org/2016/10/01/using-metalkit-part-2-3-2.html) -- [Raymarching in Metal](http://metalkit.org/2016/12/29/raymarching-in-metal.html) \ No newline at end of file +- [Raymarching in Metal](http://metalkit.org/2016/12/30/raymarching-in-metal.html) \ No newline at end of file