diff --git a/build.gradle b/build.gradle index 0517d4f7..920df5a8 100644 --- a/build.gradle +++ b/build.gradle @@ -14,7 +14,7 @@ buildscript { apply plugin: 'org.jetbrains.dokka' project.ext { - openrndrVersion = "0.3.42-rc.3" + openrndrVersion = "0.3.42-rc.4" kotlinVersion = "1.3.72" spekVersion = "2.0.10" libfreenectVersion = "0.5.7-1.5.3" diff --git a/orx-fx/build.gradle b/orx-fx/build.gradle index d6a74909..103d1690 100644 --- a/orx-fx/build.gradle +++ b/orx-fx/build.gradle @@ -10,9 +10,11 @@ sourceSets { dependencies { api project(":orx-parameters") - + implementation project(":orx-noise") demoImplementation("org.openrndr:openrndr-core:$openrndrVersion") demoImplementation("org.openrndr:openrndr-extensions:$openrndrVersion") + demoImplementation(project(":orx-gui")) + demoImplementation(project(":orx-compositor")) demoRuntimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion") demoRuntimeOnly("org.openrndr:openrndr-gl3-natives-$openrndrOS:$openrndrVersion") demoImplementation(sourceSets.getByName("main").output) diff --git a/orx-fx/src/demo/kotlin/DemoLaserBlur01.kt b/orx-fx/src/demo/kotlin/DemoLaserBlur01.kt new file mode 100644 index 00000000..b14325e1 --- /dev/null +++ b/orx-fx/src/demo/kotlin/DemoLaserBlur01.kt @@ -0,0 +1,64 @@ +import org.openrndr.application +import org.openrndr.color.ColorRGBa +import org.openrndr.extensions.SingleScreenshot +import org.openrndr.extra.compositor.compose +import org.openrndr.extra.compositor.draw +import org.openrndr.extra.compositor.layer +import org.openrndr.extra.compositor.post +import org.openrndr.extra.fx.blur.GaussianBloom +import org.openrndr.extra.fx.blur.LaserBlur +import org.openrndr.extra.gui.GUI +import org.openrndr.extra.gui.addTo +import org.openrndr.extra.noise.simplex +import org.openrndr.math.Vector2 +import kotlin.math.absoluteValue + +fun main() = application { + configure { + width = 1280 + height = 720 + } + + program { + if (System.getProperty("takeScreenshot") == "true") { + extend(SingleScreenshot()) { + this.outputFile = System.getProperty("screenshotPath") + } + } + + val gui = GUI() + val c = compose { + layer { + draw { + drawer.fill = null + drawer.strokeWeight = 4.0 + drawer.translate(width/2.0, height/2.0) + drawer.rotate(seconds*45.0 + simplex(0, seconds)*45.0) + drawer.translate(-width/2.0, -height/2.0) + for (y in -1..1) { + for (x in -1..1) { + drawer.stroke = ColorRGBa.RED.toHSVa() + .shiftHue(0.0 + simplex(500+x+y,seconds)*5.0) + .scaleValue(0.5 + 0.5 * simplex(300+x+y,seconds*4.0).absoluteValue) + .toRGBa() + val r = simplex(400+x+y, seconds) * 150.0 + 150.0 + drawer.circle(width / 2.0 + x * 100.0, height / 2.0 + y * 100.0, r) + } + } + } + post(LaserBlur()) { + center = Vector2(simplex(2, seconds*0.1), simplex(100, seconds*0.1)) + aberration = simplex(5, seconds) * 0.01 + radius = simplex(7, seconds) + }.addTo(gui) + post(GaussianBloom()).addTo(gui) + } + } + extend(gui) { + doubleBind = true + } + extend { + c.draw(drawer) + } + } +} \ No newline at end of file diff --git a/orx-fx/src/main/kotlin/blur/LaserBlur.kt b/orx-fx/src/main/kotlin/blur/LaserBlur.kt new file mode 100644 index 00000000..b22a049d --- /dev/null +++ b/orx-fx/src/main/kotlin/blur/LaserBlur.kt @@ -0,0 +1,118 @@ +package org.openrndr.extra.fx.blur + +import org.openrndr.draw.ColorBuffer +import org.openrndr.draw.ColorType +import org.openrndr.draw.Filter +import org.openrndr.draw.filterShaderFromUrl +import org.openrndr.extra.fx.filterFragmentUrl +import org.openrndr.extra.noise.simplex +import org.openrndr.extra.parameters.* +import org.openrndr.math.Vector2 +import java.lang.Math.pow + +private class LaserBlurPass : Filter(filterShaderFromUrl(filterFragmentUrl("blur/laser-blur.frag"))) { + var radius: Double by parameters + var amp0: Double by parameters + var amp1: Double by parameters + var center: Vector2 by parameters + var vignette: Double by parameters + var vignetteSize: Double by parameters + var aberration: Double by parameters + var linearInput: Boolean by parameters + var linearOutput: Boolean by parameters + + init { + radius = 0.0 + amp0 = 1.0 + amp1 = 1.0 + center = Vector2.ZERO + vignette = 0.0 + vignetteSize = 1.0 + aberration = 0.0 + linearInput = false + linearOutput = false + } +} + +@Description("Laser blur") +class LaserBlur : Filter() { + @Vector2Parameter("center", order = 0) + var center = Vector2.ZERO + + @DoubleParameter("radius", -2.0, 2.0, order = 1) + var radius = -0.18 + + @DoubleParameter("amp0", 0.0, 1.0, order = 2) + var amp0 = 0.5 + + @DoubleParameter("amp1", 0.0, 1.0, order = 3) + var amp1 = 0.5 + + @DoubleParameter("vignette", 0.0, 1.0, order = 4) + var vignette = 0.0 + + @DoubleParameter("vignette size", 0.0, 1.0, order = 5) + var vignetteSize = 0.0 + + @DoubleParameter("aberration", -1.0, 1.0, order = 6) + var aberration = 0.006 + + @DoubleParameter("exp", -1.0, 1.0, order = 7) + var exp = 0.739 + + @BooleanParameter("linear input", order = 8) + var linearInput = false + + @BooleanParameter("linear output", order = 9) + var linearOutput = false + + @DoubleParameter("phase", -1.0, 1.0, order = 7) + var phase = 0.0 + + + private val pass = LaserBlurPass() + + @IntParameter("passes", 2, 32, order = 4) + var passes = 15 + + val intermediates = mutableListOf() + + override fun apply(source: Array, target: Array) { + + pass.center = center + pass.radius = radius + pass.amp0 = amp0 + pass.amp1 = amp1 + pass.vignette = vignette + pass.vignetteSize = vignetteSize + pass.aberration = aberration + + if ((!intermediates.all { it.isEquivalentTo(source[0], ignoreFormat = true, ignoreType = true) })) { + intermediates.forEach { + it.destroy() + } + intermediates.clear() + } + if (intermediates.size == 0) { + intermediates.add(source[0].createEquivalent(type = ColorType.FLOAT16)) + intermediates.add(source[0].createEquivalent(type = ColorType.FLOAT16)) + } + + pass.radius = 1.0 + Math.pow(exp, 0.0) * radius + + pass.linearInput = linearInput + pass.linearOutput = true + pass.apply(source[0], intermediates[0]) + for (i in 0 until passes - 1) { + pass.linearInput = true + pass.linearOutput = true + + pass.radius = 1.0 + Math.pow(exp, i + 1.0) * radius //(1.0 + simplex(0, phase + i)) / 2.0 + pass.apply(intermediates[i % 2], intermediates[(i + 1) % 2]) + } + pass.radius = 1.0 + Math.pow(exp, (passes) * 1.0) * radius + pass.linearInput = true + pass.linearOutput = linearOutput + pass.apply(intermediates[(passes + 1) % 2], target[0]) + } +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/laser-blur.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/laser-blur.frag new file mode 100644 index 00000000..9089cd10 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/laser-blur.frag @@ -0,0 +1,50 @@ +#version 330 core +out vec4 o_output; +uniform sampler2D tex0; +in vec2 v_texCoord0; +uniform float radius; +uniform float amp0; +uniform float amp1; +uniform vec2 center; +uniform float vignette; +uniform float vignetteSize; +uniform float aberration; +uniform bool linearInput; +uniform bool linearOutput; + +void main() { + vec4 i0 = texture(tex0, v_texCoord0); + if (!linearInput) { + i0.rgb = pow(i0.rgb, vec3(2.2)); + } + vec2 vt = (v_texCoord0 - vec2(0.5, 0.5) + center) * radius + vec2(0.5, 0.5) - center; + + vec2 size = textureSize(tex0, 0); + vec2 l = (v_texCoord0 - vec2(0.5, 0.5) + center) * vec2(1.0, size.y/size.x); + float d = length(l); + + if (vt.x >= 0.0 && vt.y >= 0.0 && vt.x <= 1.0 && vt.y <= 1.0) { + vec4 i1r = texture(tex0, (v_texCoord0 - vec2(0.5, 0.5) + center) * (radius*(1.0 + aberration)) + vec2(0.5, 0.5) - center); + vec4 i1g = texture(tex0, (v_texCoord0 - vec2(0.5, 0.5) + center) * (radius*(1.0)) + vec2(0.5, 0.5) - center); + vec4 i1b = texture(tex0, (v_texCoord0 - vec2(0.5, 0.5) + center) * (radius*(1.0 - aberration)) + vec2(0.5, 0.5) - center); + + i1r.rgb = i1r.a > 0.0 ? i1r.rgb / i1r.a : vec3(0.0); + i1g.rgb = i1g.a > 0.0 ? i1g.rgb / i1g.a : vec3(0.0); + i1b.rgb = i1b.a > 0.0 ? i1b.rgb / i1b.a : vec3(0.0); + + vec4 i1 = vec4(i1r.r, i1g.g, i1b.b, 1.0) * (i1r.a + i1g.a + i1b.a)/3.0; + if (!linearInput) { + i1.rgb = pow(i1.rgb, vec3(2.2)); + } + o_output = i0 * amp0 + i1 * amp1; + } else { + o_output = i0 * 0.5; + } + + o_output.rgb *= mix(1.0, smoothstep(vignetteSize, 0.0, d), vignette); + if (!linearOutput) { + o_output.rgb = pow(o_output.rgb, vec3(1.0 / 2.2)); + } + + +} \ No newline at end of file