From 85f3519b1481497c672c246d59117f1e22cce782 Mon Sep 17 00:00:00 2001 From: dscyrescotti Date: Tue, 18 Jun 2024 23:49:50 +0700 Subject: [PATCH] feat: generate quad texture programmatically --- Memola/Canvas/Core/PipelineStates.swift | 2 +- .../Geometries/Stroke/Core/Stroke.swift | 8 ++++++-- .../PhotoBackgroundRenderPass.swift | 1 + .../Canvas/RenderPasses/PhotoRenderPass.swift | 1 + .../RenderPasses/ViewPortRenderPass.swift | 2 +- Memola/Canvas/Shaders/Stroke.metal | 18 ++++++++++++++++++ Memola/Canvas/Tool/Pen/Core/PenStyle.swift | 5 +++-- .../Tool/Pen/PenStyles/EraserPenStyle.swift | 4 ++-- .../Tool/Pen/PenStyles/MarkerPenStyle.swift | 2 +- 9 files changed, 34 insertions(+), 9 deletions(-) diff --git a/Memola/Canvas/Core/PipelineStates.swift b/Memola/Canvas/Core/PipelineStates.swift index 7d68936..01af9dd 100644 --- a/Memola/Canvas/Core/PipelineStates.swift +++ b/Memola/Canvas/Core/PipelineStates.swift @@ -77,7 +77,7 @@ struct PipelineStates { let library = renderer.library let pipelineDescriptor = MTLRenderPipelineDescriptor() pipelineDescriptor.vertexFunction = library.makeFunction(name: "vertex_stroke") - pipelineDescriptor.fragmentFunction = library.makeFunction(name: "fragment_stroke") + pipelineDescriptor.fragmentFunction = library.makeFunction(name: "fragment_stroke_eraser") pipelineDescriptor.colorAttachments[0].pixelFormat = pixelFormat ?? renderer.pixelFormat pipelineDescriptor.label = "Eraser Pipeline State" diff --git a/Memola/Canvas/Elements/Geometries/Stroke/Core/Stroke.swift b/Memola/Canvas/Elements/Geometries/Stroke/Core/Stroke.swift index f00857c..d6682d0 100644 --- a/Memola/Canvas/Elements/Geometries/Stroke/Core/Stroke.swift +++ b/Memola/Canvas/Elements/Geometries/Stroke/Core/Stroke.swift @@ -83,13 +83,17 @@ extension Stroke { extension Stroke { func prepare(device: MTLDevice) { guard texture == nil else { return } - texture = penStyle.loadTexture(on: device) + if penStyle.textureName != nil { + texture = penStyle.loadTexture(on: device) + } } func draw(device: MTLDevice, renderEncoder: MTLRenderCommandEncoder) { guard !isEmpty, let indexBuffer else { return } prepare(device: device) - renderEncoder.setFragmentTexture(texture, index: 0) + if penStyle.textureName != nil { + renderEncoder.setFragmentTexture(texture, index: 0) + } renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0) renderEncoder.drawIndexedPrimitives( type: .triangle, diff --git a/Memola/Canvas/RenderPasses/PhotoBackgroundRenderPass.swift b/Memola/Canvas/RenderPasses/PhotoBackgroundRenderPass.swift index c3427c9..33a5a1b 100644 --- a/Memola/Canvas/RenderPasses/PhotoBackgroundRenderPass.swift +++ b/Memola/Canvas/RenderPasses/PhotoBackgroundRenderPass.swift @@ -52,5 +52,6 @@ class PhotoBackgroundRenderPass: RenderPass { renderEncoder.endEncoding() commandBuffer.commit() + commandBuffer.waitUntilCompleted() } } diff --git a/Memola/Canvas/RenderPasses/PhotoRenderPass.swift b/Memola/Canvas/RenderPasses/PhotoRenderPass.swift index 49b9f6f..30c03d4 100644 --- a/Memola/Canvas/RenderPasses/PhotoRenderPass.swift +++ b/Memola/Canvas/RenderPasses/PhotoRenderPass.swift @@ -41,5 +41,6 @@ class PhotoRenderPass: RenderPass { renderEncoder.endEncoding() commandBuffer.commit() + commandBuffer.waitUntilCompleted() } } diff --git a/Memola/Canvas/RenderPasses/ViewPortRenderPass.swift b/Memola/Canvas/RenderPasses/ViewPortRenderPass.swift index 8f56ae9..0fda41b 100644 --- a/Memola/Canvas/RenderPasses/ViewPortRenderPass.swift +++ b/Memola/Canvas/RenderPasses/ViewPortRenderPass.swift @@ -54,7 +54,7 @@ class ViewPortRenderPass: RenderPass { renderEncoder.setRenderPipelineState(viewPortUpdatePipelineState) renderEncoder.setFragmentTexture(photoBackgroundTexture, index: 0) - canvas.renderViewPort(device: renderer.device, renderEncoder: renderEncoder) + canvas.renderViewPortUpdate(device: renderer.device, renderEncoder: renderEncoder) renderEncoder.setFragmentTexture(cacheTexture, index: 0) canvas.renderViewPortUpdate(device: renderer.device, renderEncoder: renderEncoder) diff --git a/Memola/Canvas/Shaders/Stroke.metal b/Memola/Canvas/Shaders/Stroke.metal index 99ec764..046ec36 100644 --- a/Memola/Canvas/Shaders/Stroke.metal +++ b/Memola/Canvas/Shaders/Stroke.metal @@ -53,3 +53,21 @@ fragment float4 fragment_stroke( float4 color = float4(texture.sample(textureSampler, out.textCoord)); return float4(1, 1, 1, color.a); } + +fragment float4 fragment_stroke_eraser( + VertexOut out [[stage_in]], + texture2d texture [[texture(0)]] +) { + float2 circleCenter = float2(0.5, 0.5); + float radius = 0.4; + float4 circleColor = float4(1.0, 0.0, 0.0, 1.0); + + float2 fragCoord = out.textCoord; + float distance = length(fragCoord - circleCenter); + + if (distance < radius) { + return circleColor; + } else { + return float4(0.0); + } +} diff --git a/Memola/Canvas/Tool/Pen/Core/PenStyle.swift b/Memola/Canvas/Tool/Pen/Core/PenStyle.swift index 51f717d..8bf961a 100644 --- a/Memola/Canvas/Tool/Pen/Core/PenStyle.swift +++ b/Memola/Canvas/Tool/Pen/Core/PenStyle.swift @@ -10,7 +10,7 @@ import Foundation protocol PenStyle { var icon: (base: String, tip: String?) { get } - var textureName: String { get } + var textureName: String? { get } var thickness: (min: CGFloat, max: CGFloat) { get } var thicknessSteps: [CGFloat] { get } var color: [CGFloat] { get } @@ -22,6 +22,7 @@ protocol PenStyle { extension PenStyle { @discardableResult func loadTexture(on device: MTLDevice) -> MTLTexture? { - Textures.createPenTexture(with: textureName, on: device) + guard let textureName else { return nil } + return Textures.createPenTexture(with: textureName, on: device) } } diff --git a/Memola/Canvas/Tool/Pen/PenStyles/EraserPenStyle.swift b/Memola/Canvas/Tool/Pen/PenStyles/EraserPenStyle.swift index 4b567e8..f4e96b6 100644 --- a/Memola/Canvas/Tool/Pen/PenStyles/EraserPenStyle.swift +++ b/Memola/Canvas/Tool/Pen/PenStyles/EraserPenStyle.swift @@ -10,8 +10,8 @@ import Foundation struct EraserPenStyle: PenStyle { var icon: (base: String, tip: String?) = ("eraser", nil) - var textureName: String = "point-texture" - + var textureName: String? = nil + var thickness: (min: CGFloat, max: CGFloat) = (0.5, 30) var thicknessSteps: [CGFloat] = [0.5, 1, 2, 5, 7.5, 10, 12.5, 15, 17.5, 20, 25, 30] diff --git a/Memola/Canvas/Tool/Pen/PenStyles/MarkerPenStyle.swift b/Memola/Canvas/Tool/Pen/PenStyles/MarkerPenStyle.swift index 404d62c..2e608a4 100644 --- a/Memola/Canvas/Tool/Pen/PenStyles/MarkerPenStyle.swift +++ b/Memola/Canvas/Tool/Pen/PenStyles/MarkerPenStyle.swift @@ -10,7 +10,7 @@ import Foundation struct MarkerPenStyle: PenStyle { var icon: (base: String, tip: String?) = ("marker-base", "marker-tip") - var textureName: String = "point-texture" + var textureName: String? = "point-texture" var thickness: (min: CGFloat, max: CGFloat) = (0.5, 30)