From fe7f5dfbb0b31671685861dd864315ee17fcde19 Mon Sep 17 00:00:00 2001 From: Edwin Jakobs Date: Sat, 14 Mar 2020 11:43:56 +0100 Subject: [PATCH] Add distance-transform based Inpaint --- orx-jumpflood/src/main/kotlin/fx/InnerGlow.kt | 2 +- orx-jumpflood/src/main/kotlin/fx/Inpaint.kt | 72 +++++++++++++++++++ .../shaders/gl3/encode-subpixel.frag | 4 +- .../resources/shaders/gl3/fx/inpaint.frag | 49 +++++++++++++ 4 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 orx-jumpflood/src/main/kotlin/fx/Inpaint.kt create mode 100644 orx-jumpflood/src/main/resources/shaders/gl3/fx/inpaint.frag diff --git a/orx-jumpflood/src/main/kotlin/fx/InnerGlow.kt b/orx-jumpflood/src/main/kotlin/fx/InnerGlow.kt index 7b39d1b2..5b381ea2 100644 --- a/orx-jumpflood/src/main/kotlin/fx/InnerGlow.kt +++ b/orx-jumpflood/src/main/kotlin/fx/InnerGlow.kt @@ -30,7 +30,7 @@ private class InnerGlowFilter : Filter(filterShaderFromUrl(resourceUrl("/shaders } } -@Description("Outer glow") +@Description("Inner glow") class InnerGlow : Filter() { @DoubleParameter("width", 0.0, 50.0) var width = 5.0 diff --git a/orx-jumpflood/src/main/kotlin/fx/Inpaint.kt b/orx-jumpflood/src/main/kotlin/fx/Inpaint.kt new file mode 100644 index 00000000..f8b1ea47 --- /dev/null +++ b/orx-jumpflood/src/main/kotlin/fx/Inpaint.kt @@ -0,0 +1,72 @@ +package org.openrndr.extra.jumpfill.fx + +import org.openrndr.draw.* +import org.openrndr.extra.jumpfill.EncodeSubpixel +import org.openrndr.extra.jumpfill.JumpFlooder +import org.openrndr.extra.jumpfill.PixelDirection +import org.openrndr.extra.parameters.Description +import org.openrndr.extra.parameters.DoubleParameter +import org.openrndr.math.Vector2 +import org.openrndr.resourceUrl + +private class InpaintFilter : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/fx/inpaint.frag"))) { + + var noise: Double by parameters + var imageOpacity: Double by parameters + var opacity : Double by parameters + var shape : Double by parameters + var width: Double by parameters + init { + noise = 0.0 + imageOpacity = 1.0 + opacity = 1.0 + shape = 0.0 + width = 0.5 + } +} + +@Description("Inpaint") +class Inpaint : Filter() { + @DoubleParameter("width", 0.0, 1.0) + var width = 0.5 + + @DoubleParameter("noise", 0.0, 1.0) + var noise = 0.1 + + + @DoubleParameter("opacity", 0.0, 1.0) + var opacity = 1.0 + + @DoubleParameter("image opacity", 0.0, 1.0) + var imageOpacity = 1.0 + + @DoubleParameter("shape", 0.0, 10.0) + var shape = 0.0 + + + private var jumpFlooder: JumpFlooder? = null + private val decodeFilter = PixelDirection() + private val inpaintFilter = InpaintFilter() + + private var distance: ColorBuffer? = null + + override fun apply(source: Array, target: Array) { + if (jumpFlooder == null) { + jumpFlooder = JumpFlooder(target[0].width, target[0].height, encodePoints = EncodeSubpixel()) + } + if (distance == null) { + distance = colorBuffer(target[0].width, target[0].height, type = ColorType.FLOAT32) + } + val result = jumpFlooder!!.jumpFlood(source[0]) + decodeFilter.originalSize = Vector2(target[0].width * 1.0, target[0].height * 1.0) + decodeFilter.distanceScale = 1.0 + decodeFilter.apply(result, result) + result.copyTo(distance!!) + inpaintFilter.noise = noise + inpaintFilter.imageOpacity = imageOpacity + inpaintFilter.opacity = opacity + inpaintFilter.shape = shape + inpaintFilter.width = width + inpaintFilter.apply(arrayOf(source[0], distance!!), target[0]) + } +} \ No newline at end of file diff --git a/orx-jumpflood/src/main/resources/shaders/gl3/encode-subpixel.frag b/orx-jumpflood/src/main/resources/shaders/gl3/encode-subpixel.frag index 6f439493..0a9c8079 100644 --- a/orx-jumpflood/src/main/resources/shaders/gl3/encode-subpixel.frag +++ b/orx-jumpflood/src/main/resources/shaders/gl3/encode-subpixel.frag @@ -19,7 +19,7 @@ void main() { float ref = step(threshold, texture(tex0, v_texCoord0).a); - vec2 o = stepSize/2.0; + vec2 o = vec2(0.0); //stepSize/2.0; float t00 = texture(tex0, v_texCoord0 + o + vec2(0.0, 0.0)).a; float t10 = texture(tex0, v_texCoord0 + o + vec2(stepSize.x, 0.0)).a; float t01 = texture(tex0, v_texCoord0 + o + vec2(0.0, stepSize.y)).a; @@ -117,7 +117,7 @@ void main() { //float contour = (mask == 14 || mask == 11 || mask == 7 || mask == 13) ? 1.0 : 0.0; if (contour > 0.0) { - o_color = vec4(v_texCoord0 + offset*stepSize , ref, 1.0); + o_color = vec4(v_texCoord0 /*+ offset*stepSize*/ , ref, 1.0); } else { o_color = vec4(-1.0, -1.0, 0.0, 1.0); } diff --git a/orx-jumpflood/src/main/resources/shaders/gl3/fx/inpaint.frag b/orx-jumpflood/src/main/resources/shaders/gl3/fx/inpaint.frag new file mode 100644 index 00000000..82c14ead --- /dev/null +++ b/orx-jumpflood/src/main/resources/shaders/gl3/fx/inpaint.frag @@ -0,0 +1,49 @@ +#version 330 core + +uniform sampler2D tex0;// image +uniform sampler2D tex1;// distance + +uniform float width; +uniform float noise; +uniform float shape; +uniform float imageOpacity; +uniform float opacity; +in vec2 v_texCoord0; + +out vec4 o_color; +#define HASHSCALE 443.8975 +vec2 hash22(vec2 p) { + vec3 p3 = fract(vec3(p.xyx) * HASHSCALE); + p3 += dot(p3, p3.yzx+19.19); + return fract(vec2((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y)); +} + +void main() { + vec4 original = texture(tex0, v_texCoord0); + vec2 ts = textureSize(tex0, 0); + vec2 step = 1.0 / ts; + vec2 distance = texture(tex1, v_texCoord0).rg; + + vec2 n = normalize(distance); + + vec2 uvOff = distance * step * vec2(1.0, -1.0); + + vec4 border = vec4(0.0); + + float w = 0.0; + for (int j = -1; j <= 1; ++j) { + for (int i = -1; i <= 1; ++i) { + vec4 smp = texture(tex0, v_texCoord0 + uvOff + step * vec2(i, j)); + border += smp; + } + } + + vec4 nborder = border.a>0.0?vec4(border.rgb/border.a, 1.0):vec4(0.0); + float d = length(distance); + + vec2 h = hash22(v_texCoord0)*10.0; + float rwidth = max(ts.x, ts.y) * width; + float e = shape > 0.0 ? exp(-( pow((d+h.x*noise)*1.0/rwidth, shape))) : 1.0; + o_color = original * imageOpacity + (1.0-original.a)* nborder * e * opacity; + +} \ No newline at end of file