[orx-fx] Directional blur tweaks (#357)
This commit is contained in:
@@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
package org.openrndr.extra.fx.blur
|
package org.openrndr.extra.fx.blur
|
||||||
|
|
||||||
import org.openrndr.draw.*
|
|
||||||
|
import org.openrndr.draw.Filter2to1
|
||||||
import org.openrndr.extra.fx.fx_directional_blur
|
import org.openrndr.extra.fx.fx_directional_blur
|
||||||
import org.openrndr.extra.fx.mppFilterShader
|
import org.openrndr.extra.fx.mppFilterShader
|
||||||
import org.openrndr.extra.parameters.BooleanParameter
|
import org.openrndr.extra.parameters.BooleanParameter
|
||||||
import org.openrndr.extra.parameters.Description
|
import org.openrndr.extra.parameters.Description
|
||||||
import org.openrndr.extra.parameters.DoubleParameter
|
import org.openrndr.extra.parameters.DoubleParameter
|
||||||
import org.openrndr.extra.parameters.IntParameter
|
import org.openrndr.extra.parameters.IntParameter
|
||||||
import org.openrndr.shape.Rectangle
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Directional blur filter. Takes source image and direction buffer inputs
|
* Directional blur filter. Takes source image and direction buffer inputs
|
||||||
@@ -24,13 +24,13 @@ class DirectionalBlur : Filter2to1(mppFilterShader(fx_directional_blur, "directi
|
|||||||
var centerWindow: Boolean by parameters
|
var centerWindow: Boolean by parameters
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sample window, default is 5
|
* The sample window: how many samples to mix. The default is 5
|
||||||
*/
|
*/
|
||||||
@IntParameter("window size", 1, 25)
|
@IntParameter("window size", 1, 25)
|
||||||
var window: Int by parameters
|
var window: Int by parameters
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spread multiplier, default is 1.0
|
* Spread multiplier: the distance in pixels between sampled pixels. The default is 1.0
|
||||||
*/
|
*/
|
||||||
@DoubleParameter("kernel spread", 1.0, 4.0)
|
@DoubleParameter("kernel spread", 1.0, 4.0)
|
||||||
var spread: Double by parameters
|
var spread: Double by parameters
|
||||||
@@ -42,12 +42,22 @@ class DirectionalBlur : Filter2to1(mppFilterShader(fx_directional_blur, "directi
|
|||||||
var gain: Double by parameters
|
var gain: Double by parameters
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should filter use directions perpendicular to those in the direction buffer?
|
* Should filter use directions perpendicular to those in the direction buffer? default is false
|
||||||
*/
|
*/
|
||||||
@BooleanParameter("perpendicular")
|
@BooleanParameter("perpendicular")
|
||||||
var perpendicular: Boolean by parameters
|
var perpendicular: Boolean by parameters
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap around left and right edges
|
||||||
|
*/
|
||||||
|
@BooleanParameter("wrapX")
|
||||||
|
var wrapX: Boolean by parameters
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap around top and bottom edges
|
||||||
|
*/
|
||||||
|
@BooleanParameter("wrapY")
|
||||||
|
var wrapY: Boolean by parameters
|
||||||
|
|
||||||
init {
|
init {
|
||||||
window = 5
|
window = 5
|
||||||
@@ -55,11 +65,7 @@ class DirectionalBlur : Filter2to1(mppFilterShader(fx_directional_blur, "directi
|
|||||||
gain = 1.0
|
gain = 1.0
|
||||||
perpendicular = false
|
perpendicular = false
|
||||||
centerWindow = false
|
centerWindow = false
|
||||||
}
|
wrapX = false
|
||||||
|
wrapY = false
|
||||||
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>, clip: Rectangle?) {
|
|
||||||
parameters["wrapX"] = false
|
|
||||||
parameters["wrapY"] = false
|
|
||||||
super.apply(source, target, clip)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
55
orx-fx/src/commonMain/kotlin/distort/DirectionalDisplace.kt
Normal file
55
orx-fx/src/commonMain/kotlin/distort/DirectionalDisplace.kt
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
@file:Suppress("RUNTIME_ANNOTATION_NOT_SUPPORTED")
|
||||||
|
|
||||||
|
package org.openrndr.extra.fx.distort
|
||||||
|
|
||||||
|
import org.openrndr.draw.Filter2to1
|
||||||
|
import org.openrndr.extra.fx.fx_directional_displace
|
||||||
|
import org.openrndr.extra.fx.mppFilterShader
|
||||||
|
import org.openrndr.extra.parameters.BooleanParameter
|
||||||
|
import org.openrndr.extra.parameters.Description
|
||||||
|
import org.openrndr.extra.parameters.DoubleParameter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Directional displace filter. Takes source image and direction buffer inputs
|
||||||
|
*/
|
||||||
|
@Description("Directional displace")
|
||||||
|
class DirectionalDisplace : Filter2to1(mppFilterShader(fx_directional_displace, "directional-displace")) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The distance of the sampled pixel. The default is 1.0
|
||||||
|
*/
|
||||||
|
@DoubleParameter("distance", 1.0, 1000.0)
|
||||||
|
var distance: Double by parameters
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post-displace 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? default is false
|
||||||
|
*/
|
||||||
|
@BooleanParameter("perpendicular")
|
||||||
|
var perpendicular: Boolean by parameters
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap around left and right edges
|
||||||
|
*/
|
||||||
|
@BooleanParameter("wrapX")
|
||||||
|
var wrapX: Boolean by parameters
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap around top and bottom edges
|
||||||
|
*/
|
||||||
|
@BooleanParameter("wrapY")
|
||||||
|
var wrapY: Boolean by parameters
|
||||||
|
|
||||||
|
init {
|
||||||
|
distance = 1.0
|
||||||
|
gain = 1.0
|
||||||
|
perpendicular = false
|
||||||
|
wrapX = false
|
||||||
|
wrapY = false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,19 @@ import org.openrndr.math.smoothstep
|
|||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to use [DirectionalBlur] by creating a `direction`
|
||||||
|
* ColorBuffer in which the red and green components of the pixels point
|
||||||
|
* in various directions where to sample pixels from. All the pixel colors
|
||||||
|
* of the ColorBuffer are set one by one using two for loops.
|
||||||
|
*
|
||||||
|
* Note the FLOAT32 color type of the buffer to allow for negative values,
|
||||||
|
* so sampling can happen from every direction.
|
||||||
|
*
|
||||||
|
* Every 60 animation frames the `centerWindow` property is toggled
|
||||||
|
* between true and false to demonstrate how the result changes.
|
||||||
|
*
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
program {
|
program {
|
||||||
val db = DirectionalBlur()
|
val db = DirectionalBlur()
|
||||||
@@ -31,6 +44,7 @@ fun main() = application {
|
|||||||
drawer.image(image)
|
drawer.image(image)
|
||||||
}
|
}
|
||||||
db.window = 10
|
db.window = 10
|
||||||
|
db.centerWindow = frameCount % 120 > 60
|
||||||
db.apply(arrayOf(rt.colorBuffer(0), direction), blurred)
|
db.apply(arrayOf(rt.colorBuffer(0), direction), blurred)
|
||||||
drawer.image(blurred)
|
drawer.image(blurred)
|
||||||
}
|
}
|
||||||
|
|||||||
50
orx-fx/src/jvmDemo/kotlin/DemoDirectionalDisplace01.kt
Normal file
50
orx-fx/src/jvmDemo/kotlin/DemoDirectionalDisplace01.kt
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.color.ColorRGBa
|
||||||
|
import org.openrndr.color.rgb
|
||||||
|
import org.openrndr.draw.ColorType
|
||||||
|
import org.openrndr.draw.colorBuffer
|
||||||
|
import org.openrndr.draw.loadImage
|
||||||
|
import org.openrndr.drawImage
|
||||||
|
import org.openrndr.extra.fx.distort.DirectionalDisplace
|
||||||
|
import org.openrndr.extra.noise.simplex
|
||||||
|
import org.openrndr.extra.shapes.primitives.grid
|
||||||
|
import kotlin.math.cos
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrate how to use [DirectionalDisplace].
|
||||||
|
*
|
||||||
|
* The direction map is populated using `drawImage` instead of
|
||||||
|
* pixel by pixel. A grid of circles is drawn, each circle with a
|
||||||
|
* color based on simplex noise. The R and G channels of the colors
|
||||||
|
* control the direction of the sampling. By animating the sampling
|
||||||
|
* distance the result oscillates between no-effect and a noticeable one.
|
||||||
|
*/
|
||||||
|
fun main() = application {
|
||||||
|
program {
|
||||||
|
val displace = DirectionalDisplace()
|
||||||
|
|
||||||
|
val displaced = colorBuffer(width, height)
|
||||||
|
val direction = drawImage(width, height, type = ColorType.FLOAT32) {
|
||||||
|
clear(ColorRGBa.BLACK)
|
||||||
|
bounds.grid(32, 24).flatten().forEach {
|
||||||
|
fill = rgb(
|
||||||
|
simplex(133, it.center * 0.004),
|
||||||
|
simplex(197, it.center * 0.004),
|
||||||
|
0.0
|
||||||
|
)
|
||||||
|
stroke = null
|
||||||
|
|
||||||
|
//rectangle(it)
|
||||||
|
circle(it.center, 8.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val image = loadImage("demo-data/images/image-001.png")
|
||||||
|
extend {
|
||||||
|
displace.distance = 100.0 + 100.0 * cos(seconds)
|
||||||
|
displace.wrapX = true
|
||||||
|
displace.wrapX = true
|
||||||
|
displace.apply(arrayOf(image, direction), displaced)
|
||||||
|
drawer.image(displaced)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
orx-fx/src/jvmDemo/kotlin/DemoDirectionalDisplace02.kt
Normal file
45
orx-fx/src/jvmDemo/kotlin/DemoDirectionalDisplace02.kt
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.color.ColorRGBa
|
||||||
|
import org.openrndr.color.rgb
|
||||||
|
import org.openrndr.draw.ColorType
|
||||||
|
import org.openrndr.draw.colorBuffer
|
||||||
|
import org.openrndr.draw.loadImage
|
||||||
|
import org.openrndr.drawImage
|
||||||
|
import org.openrndr.extra.fx.distort.DirectionalDisplace
|
||||||
|
import org.openrndr.math.Polar
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrate how to use [DirectionalDisplace].
|
||||||
|
*
|
||||||
|
* The program draws 12 overlapping translucent circles on the
|
||||||
|
* `direction` color buffer to produce new color combinations
|
||||||
|
* on the overlapping areas. Those colors specify where the
|
||||||
|
* `DirectionalDisplace` effect will sample pixels from.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun main() = application {
|
||||||
|
program {
|
||||||
|
val displace = DirectionalDisplace()
|
||||||
|
|
||||||
|
val displaced = colorBuffer(width, height)
|
||||||
|
val direction = drawImage(width, height, type = ColorType.FLOAT32) {
|
||||||
|
clear(ColorRGBa.BLACK)
|
||||||
|
for(x in 0 until 6) {
|
||||||
|
val offset = Polar(x * 60.0).cartesian
|
||||||
|
fill = rgb(offset.y, offset.x, 0.0, 0.3)
|
||||||
|
stroke = null
|
||||||
|
|
||||||
|
val pos = bounds.center - offset * 110.0
|
||||||
|
circle(pos, 120.0)
|
||||||
|
circle(pos, 80.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val image = loadImage("demo-data/images/image-001.png")
|
||||||
|
extend {
|
||||||
|
displace.distance = 250.0
|
||||||
|
displace.apply(arrayOf(image, direction), displaced)
|
||||||
|
drawer.image(displaced)
|
||||||
|
//drawer.image(direction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,15 +17,11 @@ out vec4 o_color;
|
|||||||
|
|
||||||
vec2 wrap(vec2 uv) {
|
vec2 wrap(vec2 uv) {
|
||||||
vec2 res = uv;
|
vec2 res = uv;
|
||||||
if (wrapX) {
|
if (wrapX) { res.x = fract(res.x); }
|
||||||
res.x = mod(res.x, 1.0);
|
if (wrapY) { res.y = fract(res.y); }
|
||||||
}
|
|
||||||
if (wrapY) {
|
|
||||||
res.y = mod(res.y, 1.0);
|
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec2 s = textureSize0;
|
vec2 s = textureSize0;
|
||||||
s = vec2(1.0 / s.x, 1.0 / s.y);
|
s = vec2(1.0 / s.x, 1.0 / s.y);
|
||||||
@@ -40,8 +36,7 @@ void main() {
|
|||||||
int start = centerWindow ? -window / 2 : 0;
|
int start = centerWindow ? -window / 2 : 0;
|
||||||
int end = centerWindow ? window / 2 + 1 : window;
|
int end = centerWindow ? window / 2 + 1 : window;
|
||||||
|
|
||||||
|
for (int x = start; x < end; ++x) {
|
||||||
for (int x = 0; x < window; ++x) {
|
|
||||||
sum += texture(tex0, wrap(v_texCoord0 + float(x) * blurDirection * s * spread));
|
sum += texture(tex0, wrap(v_texCoord0 + float(x) * blurDirection * s * spread));
|
||||||
weight += 1.0;
|
weight += 1.0;
|
||||||
}
|
}
|
||||||
|
|||||||
37
orx-fx/src/shaders/glsl/distort/directional-displace.frag
Normal file
37
orx-fx/src/shaders/glsl/distort/directional-displace.frag
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
in vec2 v_texCoord0;
|
||||||
|
|
||||||
|
uniform sampler2D tex0; // image
|
||||||
|
uniform sampler2D tex1; // displaceDirection
|
||||||
|
uniform vec2 textureSize0;
|
||||||
|
|
||||||
|
uniform float gain;
|
||||||
|
uniform float distance;
|
||||||
|
|
||||||
|
uniform bool wrapX;
|
||||||
|
uniform bool wrapY;
|
||||||
|
uniform bool perpendicular;
|
||||||
|
|
||||||
|
out vec4 o_color;
|
||||||
|
|
||||||
|
vec2 wrap(vec2 uv) {
|
||||||
|
vec2 res = uv;
|
||||||
|
if (wrapX) { res.x = fract(res.x); }
|
||||||
|
if (wrapY) { res.y = fract(res.y); }
|
||||||
|
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);
|
||||||
|
vec2 blurDirection = texture(tex1, v_texCoord0).xy;
|
||||||
|
if (perpendicular) {
|
||||||
|
blurDirection = vec2(-blurDirection.y, blurDirection.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 result = texture(tex0, wrap(v_texCoord0 + blurDirection * s * distance))
|
||||||
|
* gain;
|
||||||
|
|
||||||
|
o_color = result;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user