[orx-fx] Directional blur tweaks (#357)
This commit is contained in:
@@ -2,14 +2,14 @@
|
||||
|
||||
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.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
|
||||
import org.openrndr.shape.Rectangle
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
/**
|
||||
* The sample window, default is 5
|
||||
* The sample window: how many samples to mix. The default is 5
|
||||
*/
|
||||
@IntParameter("window size", 1, 25)
|
||||
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)
|
||||
var spread: Double by parameters
|
||||
@@ -42,12 +42,22 @@ class DirectionalBlur : Filter2to1(mppFilterShader(fx_directional_blur, "directi
|
||||
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")
|
||||
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 {
|
||||
window = 5
|
||||
@@ -55,11 +65,7 @@ class DirectionalBlur : Filter2to1(mppFilterShader(fx_directional_blur, "directi
|
||||
gain = 1.0
|
||||
perpendicular = false
|
||||
centerWindow = false
|
||||
}
|
||||
|
||||
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>, clip: Rectangle?) {
|
||||
parameters["wrapX"] = false
|
||||
parameters["wrapY"] = false
|
||||
super.apply(source, target, clip)
|
||||
wrapX = false
|
||||
wrapY = false
|
||||
}
|
||||
}
|
||||
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.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 {
|
||||
program {
|
||||
val db = DirectionalBlur()
|
||||
@@ -31,6 +44,7 @@ fun main() = application {
|
||||
drawer.image(image)
|
||||
}
|
||||
db.window = 10
|
||||
db.centerWindow = frameCount % 120 > 60
|
||||
db.apply(arrayOf(rt.colorBuffer(0), direction), 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
in vec2 v_texCoord0;
|
||||
|
||||
uniform bool centerWindow;
|
||||
uniform sampler2D tex0;// image
|
||||
uniform sampler2D tex1;// blurDirection
|
||||
uniform sampler2D tex0; // image
|
||||
uniform sampler2D tex1; // blurDirection
|
||||
uniform vec2 textureSize0;
|
||||
|
||||
uniform int window;
|
||||
@@ -17,15 +17,11 @@ out vec4 o_color;
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
@@ -37,15 +33,14 @@ void main() {
|
||||
}
|
||||
float weight = 0.0;
|
||||
|
||||
int start = centerWindow? -window/2 : 0;
|
||||
int end = centerWindow? window/2 + 1 : window;
|
||||
int start = centerWindow ? -window / 2 : 0;
|
||||
int end = centerWindow ? window / 2 + 1 : window;
|
||||
|
||||
|
||||
for (int x = 0; x < window; ++x) {
|
||||
for (int x = start; x < end; ++x) {
|
||||
sum += texture(tex0, wrap(v_texCoord0 + float(x) * blurDirection * s * spread));
|
||||
weight += 1.0;
|
||||
}
|
||||
|
||||
vec4 result = (sum/weight) * gain;
|
||||
vec4 result = (sum / weight) * gain;
|
||||
o_color = result;
|
||||
}
|
||||
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