feat: generate quad texture programmatically

This commit is contained in:
dscyrescotti
2024-06-18 23:49:50 +07:00
parent e5f7bec775
commit 85f3519b14
9 changed files with 34 additions and 9 deletions

View File

@@ -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"

View File

@@ -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,

View File

@@ -52,5 +52,6 @@ class PhotoBackgroundRenderPass: RenderPass {
renderEncoder.endEncoding()
commandBuffer.commit()
commandBuffer.waitUntilCompleted()
}
}

View File

@@ -41,5 +41,6 @@ class PhotoRenderPass: RenderPass {
renderEncoder.endEncoding()
commandBuffer.commit()
commandBuffer.waitUntilCompleted()
}
}

View File

@@ -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)

View File

@@ -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<float> 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);
}
}

View File

@@ -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)
}
}

View File

@@ -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]

View File

@@ -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)