From ff12413f1f46a2c30155004102e7de5c7a608acb Mon Sep 17 00:00:00 2001 From: Edwin Jakobs Date: Sat, 3 Sep 2022 13:08:02 +0200 Subject: [PATCH] [orx-fx] Add DirectionalBlur --- .../commonMain/kotlin/blur/DirectionalBlur.kt | 53 +++++++++++++++ .../src/demo/kotlin/DemoDirectionalBlur01.kt | 38 +++++++++++ .../shaders/glsl/blur/directional-blur.frag | 67 +++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 orx-fx/src/commonMain/kotlin/blur/DirectionalBlur.kt create mode 100644 orx-fx/src/demo/kotlin/DemoDirectionalBlur01.kt create mode 100644 orx-fx/src/shaders/glsl/blur/directional-blur.frag diff --git a/orx-fx/src/commonMain/kotlin/blur/DirectionalBlur.kt b/orx-fx/src/commonMain/kotlin/blur/DirectionalBlur.kt new file mode 100644 index 00000000..591a6330 --- /dev/null +++ b/orx-fx/src/commonMain/kotlin/blur/DirectionalBlur.kt @@ -0,0 +1,53 @@ +package org.openrndr.extra.fx.blur + +import org.openrndr.draw.* +import org.openrndr.extra.fx.fx_directional_blur +import org.openrndr.extra.fx.mppFilterShader +import org.openrndr.extra.parameters.BooleanParameter +import org.openrndr.extra.parameters.Description +import org.openrndr.extra.parameters.DoubleParameter +import org.openrndr.extra.parameters.IntParameter + +/** + * Directional blur filter. Takes source image and direction buffer inputs + */ +@Description("Directional blur") +class DirectionalBlur : Filter(mppFilterShader(fx_directional_blur, "directional-blur")) { + + /** + * The sample window, default is 5 + */ + @IntParameter("window size", 1, 25) + var window: Int by parameters + + /** + * Spread multiplier, default is 1.0 + */ + @DoubleParameter("kernel spread", 1.0, 4.0) + var spread: Double by parameters + + /** + * Post-blur gain, default is 1.0 + */ + @DoubleParameter("gain", 0.0, 4.0) + var gain: Double by parameters + + /** + * Should filter use directions perpendicular to those in the direction buffer? + */ + @BooleanParameter("perpendicular") + var perpendicular: Boolean by parameters + + init { + window = 5 + spread = 1.0 + gain = 1.0 + perpendicular = false + } + + override fun apply(source: Array, target: Array) { + parameters["wrapX"] = false + parameters["wrapY"] = false + super.apply(source, target) + } +} \ No newline at end of file diff --git a/orx-fx/src/demo/kotlin/DemoDirectionalBlur01.kt b/orx-fx/src/demo/kotlin/DemoDirectionalBlur01.kt new file mode 100644 index 00000000..1ff50916 --- /dev/null +++ b/orx-fx/src/demo/kotlin/DemoDirectionalBlur01.kt @@ -0,0 +1,38 @@ +import org.openrndr.application +import org.openrndr.color.ColorRGBa +import org.openrndr.draw.* +import org.openrndr.extra.fx.blur.DirectionalBlur +import org.openrndr.math.smoothstep +import kotlin.math.cos +import kotlin.math.sin + +fun main() = application { + program { + val db = DirectionalBlur() + val rt = renderTarget(width, height) { + colorBuffer() + } + + val blurred = colorBuffer(width, height) + val direction = colorBuffer(width, height, type = ColorType.FLOAT32) + val s = direction.shadow + for (y in 0 until height) { + for (x in 0 until width) { + val a = smoothstep(0.45, 0.55, cos((x + y) * 0.01) * 0.5 + 0.5) + s[x, y] = ColorRGBa(cos(y * .1) * a, sin(x * 0.1) * a, 0.0, 1.0) + } + } + + s.upload() + val image = loadImage("demo-data/images/image-001.png") + extend { + drawer.isolatedWithTarget(rt) { + clear(ColorRGBa.BLACK) + drawer.image(image) + } + db.window = 10 + db.apply(arrayOf(rt.colorBuffer(0), direction), blurred) + drawer.image(blurred) + } + } +} \ No newline at end of file diff --git a/orx-fx/src/shaders/glsl/blur/directional-blur.frag b/orx-fx/src/shaders/glsl/blur/directional-blur.frag new file mode 100644 index 00000000..3e0803e4 --- /dev/null +++ b/orx-fx/src/shaders/glsl/blur/directional-blur.frag @@ -0,0 +1,67 @@ +#ifdef OR_IN_OUT +in vec2 v_texCoord0; +#else +varying vec2 v_texCoord0; +#endif + +uniform sampler2D tex0; // image +uniform sampler2D tex1; // blurDirection +uniform vec2 textureSize0; + +uniform int window; +uniform float sigma; +uniform float gain; +uniform vec4 subtract; +uniform float spread; + +uniform bool wrapX; +uniform bool wrapY; +uniform bool perpendicular; + + +#ifndef OR_GL_FRAGCOLOR +out vec4 o_color; +#endif + +vec2 wrap(vec2 uv) { + vec2 res = uv; + if (wrapX) { + res.x = mod(res.x, 1.0); + } + if (wrapY) { + res.y = mod(res.y, 1.0); + } + return res; + +} +void main() { + vec2 s = textureSize0; + s = vec2(1.0 / s.x, 1.0 / s.y); + + + vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); + #ifndef OR_GL_TEXTURE2D + vec2 blurDirection = texture(tex1, v_texCoord0).xy; + if (perpendicular) { + blurDirection = vec2(-blurDirection.y, blurDirection.x); + } + float weight = 0.0; + for (int x = 0; x < window; ++x) { + sum += texture(tex0, wrap(v_texCoord0 + float(x) * blurDirection * s * spread)); + weight += 1.0; + } + #else + vec2 blurDirection = texture2D(tex1, v_texCoord0); + float weight = 0.0; + sum += texture2D(tex0, wrap(v_texCoord0 * blurDirection * s * spread)); + + #endif + + + vec4 result = (sum/weight) * gain; + #ifdef OR_GL_FRAGCOLOR + gl_FragColor = result; + #else + o_color = result; + #endif +} \ No newline at end of file