Add LaserBlur
This commit is contained in:
64
orx-fx/src/demo/kotlin/DemoLaserBlur01.kt
Normal file
64
orx-fx/src/demo/kotlin/DemoLaserBlur01.kt
Normal file
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
118
orx-fx/src/main/kotlin/blur/LaserBlur.kt
Normal file
118
orx-fx/src/main/kotlin/blur/LaserBlur.kt
Normal file
@@ -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<ColorBuffer>()
|
||||
|
||||
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
|
||||
|
||||
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])
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user