From 9cb7ac6644d1d5f7f70ffe82d2c9c2b9bf183778 Mon Sep 17 00:00:00 2001 From: Edwin Jakobs Date: Thu, 27 Feb 2020 16:45:50 +0100 Subject: [PATCH] Add Filter interfaces for PoissonBlend and PoissonFill --- .../src/main/kotlin/PoissonBlender.kt | 66 +++++++++++++++++-- .../src/main/kotlin/PoissonFiller.kt | 5 +- .../shaders/gl3/poisson/alpha-to-bitmap.frag | 2 +- .../shaders/gl3/poisson/blend-combine.frag | 1 + .../shaders/gl3/poisson/fill-combine.frag | 4 +- 5 files changed, 68 insertions(+), 10 deletions(-) diff --git a/orx-poisson-fill/src/main/kotlin/PoissonBlender.kt b/orx-poisson-fill/src/main/kotlin/PoissonBlender.kt index 09777749..78a89b81 100644 --- a/orx-poisson-fill/src/main/kotlin/PoissonBlender.kt +++ b/orx-poisson-fill/src/main/kotlin/PoissonBlender.kt @@ -3,6 +3,8 @@ package org.openrndr.poissonfill import org.openrndr.draw.* import org.openrndr.extra.fx.blend.Passthrough import org.openrndr.extra.fx.blend.Subtract +import org.openrndr.filter.color.delinearize +import org.openrndr.filter.color.linearize import org.openrndr.resourceUrl internal class BlendBoundary : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/poisson/blend-boundary.frag"))) @@ -23,7 +25,7 @@ internal class Clamp : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/pois private val passthrough by lazy { Passthrough() } private val subtract by lazy { Subtract() } -class PoissonBlender(width: Int, height: Int, type: ColorType = ColorType.FLOAT32) { +class PoissonBlender(val width: Int, val height: Int, type: ColorType = ColorType.FLOAT32) { private val pyramid = ConvolutionPyramid(width, height, 0, type = type) private val preprocess = colorBuffer(width, height, type = type) private val combined = colorBuffer(width, height, type = type) @@ -37,7 +39,6 @@ class PoissonBlender(width: Int, height: Int, type: ColorType = ColorType.FLOAT3 private val h2 = 0.0269546f private val g = floatArrayOf(0.0311849f, 0.7752854f, 0.0311849f) - private val clamp = Clamp() init { pyramid.h1 = h1 @@ -48,12 +49,69 @@ class PoissonBlender(width: Int, height: Int, type: ColorType = ColorType.FLOAT3 fun process(target: ColorBuffer, source: ColorBuffer, mask: ColorBuffer, softMask: ColorBuffer = mask, softMaskGain: Double = 1.0): ColorBuffer { subtract.apply(arrayOf(target, source), difference) - clamp.minValue = -0.50 - clamp.maxValue = 0.50 fillBoundary.apply(arrayOf(difference, mask), preprocess) val result = pyramid.process(preprocess) fillCombine.softMaskGain = softMaskGain fillCombine.apply(arrayOf(result, target, source, mask, softMask), arrayOf(combined)) return combined } + + fun destroy() { + pyramid.destroy() + preprocess.destroy() + combined.destroy() + difference.destroy() + } + +} + +class PoissonBlend: Filter() { + private var blender: PoissonBlender? = null + + val alphaToBitmap = AlphaToBitmap() + var mask: ColorBuffer? = null + + override fun apply(source: Array, target: Array) { + if (target.isNotEmpty()) { + + mask?.let { + if (it.width != target[0].width || it.height != target[0].height) { + it.destroy() + mask = null + } + } + + if (mask == null) { + mask = colorBuffer(target[0].width, target[0].height) + } + + blender?.let { + if (it.width != target[0].width || it.height != target[0].height) { + it.destroy() + blender = null + } + } + + if (blender == null) { + blender = PoissonBlender(target[0].width, target[0].height) + } + + mask?.let { + alphaToBitmap.apply(source[1], it) + } + + + blender?.let { + + linearize.apply(source[0], source[0]) + linearize.apply(source[1], source[1]) + + val result = it.process(source[0], source[1], mask ?: error("no mask")) + result.copyTo(target[0]) + + delinearize.apply(target[0], target[0]) + } + + } + } } \ No newline at end of file diff --git a/orx-poisson-fill/src/main/kotlin/PoissonFiller.kt b/orx-poisson-fill/src/main/kotlin/PoissonFiller.kt index 3bbe0589..89764352 100644 --- a/orx-poisson-fill/src/main/kotlin/PoissonFiller.kt +++ b/orx-poisson-fill/src/main/kotlin/PoissonFiller.kt @@ -33,11 +33,12 @@ class PoissonFiller(val width: Int, val height: Int, type: ColorType = ColorType fun destroy() { preproc.destroy() combined.destroy() - } - } +/** + * Poison filling as a filter + */ class PoissonFill : Filter() { private var filler: PoissonFiller? = null override fun apply(source: Array, target: Array) { diff --git a/orx-poisson-fill/src/main/resources/shaders/gl3/poisson/alpha-to-bitmap.frag b/orx-poisson-fill/src/main/resources/shaders/gl3/poisson/alpha-to-bitmap.frag index afc1fa1b..07d85216 100644 --- a/orx-poisson-fill/src/main/resources/shaders/gl3/poisson/alpha-to-bitmap.frag +++ b/orx-poisson-fill/src/main/resources/shaders/gl3/poisson/alpha-to-bitmap.frag @@ -6,6 +6,6 @@ out vec4 o_output; void main(){ vec4 c = texture(tex0, v_texCoord0); - o_output.rgb = vec3(step(1.0, c.a)); + o_output.rgb = vec3(step(0.01, c.a)); o_output.a = 1.0; } \ No newline at end of file diff --git a/orx-poisson-fill/src/main/resources/shaders/gl3/poisson/blend-combine.frag b/orx-poisson-fill/src/main/resources/shaders/gl3/poisson/blend-combine.frag index 3ccfef85..a8b7d5b6 100644 --- a/orx-poisson-fill/src/main/resources/shaders/gl3/poisson/blend-combine.frag +++ b/orx-poisson-fill/src/main/resources/shaders/gl3/poisson/blend-combine.frag @@ -41,5 +41,6 @@ void main(){ o_output.rgb = mix(targetColor.rgb, blend, mask*max(0.0,min(1.0, softMask * softMaskGain))); o_output.a = 1.0; + } } \ No newline at end of file diff --git a/orx-poisson-fill/src/main/resources/shaders/gl3/poisson/fill-combine.frag b/orx-poisson-fill/src/main/resources/shaders/gl3/poisson/fill-combine.frag index 9436db54..ca5069f6 100644 --- a/orx-poisson-fill/src/main/resources/shaders/gl3/poisson/fill-combine.frag +++ b/orx-poisson-fill/src/main/resources/shaders/gl3/poisson/fill-combine.frag @@ -12,9 +12,7 @@ out vec4 o_output; /** Composite the initial image and the filled image in the regions where the initial image is black. */ void main(){ - vec4 inputColor = textureLod(tex1, v_texCoord0, 0.0).rgba; - //float mask = float(all(equal(inputColor, vec3(0.0)))); - //float mask = inputColor.a == 1.0? 0.0 : 1.0; + vec4 inputColor = textureLod(tex1, v_texCoord0, 0.0); float mask = 1.0 - inputColor.a; vec4 fillColor = textureLod(tex0, v_texCoord0, 0.0);