orx-fx Filters
The orx-fx library contains many filters that can be readily used. See the chapter Filters and post-processing for instructions on using them.
A (more-or-less) complete listing of the effects in orx-fx is maintained in the repository’s README.md
Prerequisites
If you are working on an openrndr-template based project, orx-fx should be ready to use because it is part of the basic orx bundle, as described in ORX.
Effect Index
In this index we demonstrate selected filters, this is in no way a complete overview of what orx-fx offers.
Blur effects
BoxBlur
fun main() = application {
program {
// -- load a source image
val image = loadImage("data/images/cheeta.jpg")
// -- create a filter
val blur = BoxBlur()
// -- create a colorBuffer where to store the result
val blurred = colorBuffer(image.width, image.height)
extend {
// -- configure the filter
blur.window = (cos(seconds * 2) * 4.0 + 5.0).toInt()
// -- filter.apply(source, target)
blur.apply(image, blurred)
// -- draw the result
drawer.image(blurred)
}
}
}
ApproximateGaussianBlur
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val blurred = colorBuffer(image.width, image.height)
val blur = ApproximateGaussianBlur()
extend {
blur.window = 25
blur.sigma = cos(seconds * 2) * 10.0 + 10.1
blur.apply(image, blurred)
drawer.image(blurred)
}
}
}
GaussianBloom
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val blurred = colorBuffer(image.width, image.height)
val bloom = GaussianBloom()
extend {
bloom.window = 5
bloom.sigma = 3.0
bloom.gain = cos(seconds * 2) * 2.0 + 2.0
bloom.apply(image, blurred)
drawer.image(blurred)
}
}
}
HashBlur
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val blurred = colorBuffer(image.width, image.height)
val blur = HashBlur()
extend {
blur.samples = 50
blur.radius = cos(seconds * 2) * 25.0 + 25.0
blur.apply(image, blurred)
drawer.image(blurred)
}
}
}
FrameBlur
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val blurred = colorBuffer(image.width, image.height)
val blur = FrameBlur()
val rt = renderTarget(width, height) {
colorBuffer()
}
extend {
drawer.isolatedWithTarget(rt) {
drawer.clear(ColorRGBa.BLACK)
drawer.image(image, cos(seconds * 2) * 40.0, sin(seconds * 2) * 40.0)
}
blur.blend = 0.01
blur.apply(rt.colorBuffer(0), blurred)
drawer.image(blurred)
}
}
}
ZoomBlur
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val blurred = colorBuffer(image.width, image.height)
val blur = ZoomBlur()
extend {
blur.center = Vector2(
cos(seconds) * 0.5 + 0.5,
sin(seconds * 2) * 0.5 + 0.5
)
blur.strength = cos(seconds * 2) * 0.5 + 0.5
blur.apply(image, blurred)
drawer.image(blurred)
}
}
}
Color filters
ChromaticAberration
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = ChromaticAberration()
val filtered = colorBuffer(image.width, image.height)
extend {
filter.aberrationFactor = cos(seconds * 2) * 10.0
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
ColorCorrection
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = ColorCorrection()
val filtered = colorBuffer(image.width, image.height)
extend {
filter.hueShift = cos(seconds * 1) * 180.0
filter.saturation = cos(seconds * 2)
filter.brightness = sin(seconds * 3) * 0.1
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
Sepia
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = Sepia()
val filtered = colorBuffer(image.width, image.height)
extend {
filter.amount = cos(seconds * 2) * 0.5 + 0.5
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
LumaOpacity
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = LumaOpacity()
val filtered = colorBuffer(image.width, image.height)
extend {
// -- a pink background to demonstrate the introduced transparencies
drawer.clear(ColorRGBa.PINK)
filter.backgroundOpacity = 0.0
filter.foregroundOpacity = 1.0
filter.backgroundLuma = cos(seconds) * 0.25 + 0.25
filter.foregroundLuma = 1.0 - (cos(seconds) * 0.25 + 0.25)
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
Edge-detection filters
LumaSobel
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = LumaSobel()
val filtered = colorBuffer(image.width, image.height)
extend {
filter.backgroundColor = ColorRGBa.PINK.toHSVa()
.shiftHue(cos(seconds) * 180).toRGBa()
.shade(0.25)
filter.edgeColor = ColorRGBa.PINK
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
Contour
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = Contour()
val filtered = colorBuffer(image.width, image.height)
extend {
filter.backgroundOpacity = 1.0
filter.contourColor = ColorRGBa.BLACK
filter.contourWidth = 0.4
filter.levels = cos(seconds) * 3.0 + 5.1
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
EdgesWork
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = EdgesWork()
val filtered = colorBuffer(image.width, image.height)
extend {
filter.radius = (cos(seconds) * 5 + 5).toInt()
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
Distortion filters
BlockRepeat
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = BlockRepeat()
val filtered = colorBuffer(image.width, image.height)
extend {
filter.sourceScale = seconds / 5.0
filter.blockWidth = cos(seconds) * 0.3 + 0.4
filter.blockHeight = sin(seconds) * 0.3 + 0.4
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
StackRepeat
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = StackRepeat()
val filtered = colorBuffer(image.width, image.height)
extend {
filter.repeats = 4
filter.zoom = (cos(seconds) * 0.1 + 0.11)
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
HorizontalWave
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = HorizontalWave()
val filtered = colorBuffer(image.width, image.height)
extend {
filter.amplitude = cos(seconds) * 0.1
filter.frequency = sin(seconds) * 4.0
if (seconds > 2.5) {
filter.segments = 10
}
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
VerticalWave
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = VerticalWave()
val filtered = colorBuffer(image.width, image.height)
extend {
filter.amplitude = cos(seconds) * 0.1
filter.frequency = sin(seconds) * 4.0
if (seconds > 2.5) {
filter.segments = 10
}
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
Perturb
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = Perturb()
val filtered = colorBuffer(image.width, image.height)
extend {
filter.phase = seconds * 0.1
filter.decay = 0.168
filter.gain = cos(seconds) * 0.5 + 0.5
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
Tiles
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = Tiles()
val filtered = colorBuffer(image.width, image.height)
extend {
filter.rotation = seconds * 60.0
filter.xSegments = (10 + cos(seconds * PI / 3) * 5.0).toInt()
filter.ySegments = 30
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
Fisheye
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = Fisheye()
val filtered = colorBuffer(image.width, image.height)
extend {
filter.strength = cos(seconds) * 0.125
filter.scale = 1.1
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
DisplaceBlend
fun main() = application {
program {
val composite = compose {
colorType = ColorType.FLOAT16
layer {
val image = loadImage("data/images/cheeta.jpg")
draw {
drawer.imageFit(image, 0.0, 0.0, width * 1.0, height * 1.0)
}
}
layer {
draw {
drawer.shadeStyle = linearGradient(ColorRGBa.BLACK, ColorRGBa.WHITE)
drawer.stroke = null
val size = cos(seconds * PI / 3) * 100.0 + 200.0
drawer.rectangle(width / 2.0 - size / 2, height / 2.0 - size / 2, size, size)
}
blend(DisplaceBlend()) {
gain = cos(seconds * PI / 3) * 0.5 + 0.5
rotation = seconds * 60.0
}
}
}
extend {
composite.draw(drawer)
}
}
}
StretchWaves
fun main() = application {
program {
val composite = compose {
colorType = ColorType.FLOAT16
layer {
val image = loadImage("data/images/cheeta.jpg")
draw {
drawer.imageFit(image, 0.0, 0.0, width * 1.0, height * 1.0)
}
post(StretchWaves()) {
distortion = 0.25
rotation = seconds * 60.0
phase = seconds * 0.25
frequency = 5.0
}
}
}
extend {
composite.draw(drawer)
}
}
}
PerspectivePlane
fun main() = application {
program {
val composite = compose {
layer {
post(Checkers())
}
layer {
val image = loadImage("data/images/cheeta.jpg")
draw {
drawer.imageFit(image, 0.0, 0.0, width * 1.0, height * 1.0)
}
post(PerspectivePlane()) {
planePitch = cos(seconds) * 22.5
planeYaw = sin(seconds) * 22.5
}
}
}
extend {
composite.draw(drawer)
}
}
}
Dithering filters
ADither
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = ADither()
val filtered = colorBuffer(image.width, image.height)
extend {
filter.pattern = ((seconds / 5.0) * 4).toInt().coerceAtMost(3)
filter.levels = ((seconds % 1.0) * 3).toInt() + 1
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
CMYKHalftone
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = CMYKHalftone()
val filtered = colorBuffer(image.width, image.height)
extend {
// -- need a white background because the filter introduces transparent areas
drawer.clear(ColorRGBa.WHITE)
filter.dotSize = 1.2
filter.scale = cos(seconds) * 2.0 + 6.0
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
Crosshatch
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = Crosshatch()
val filtered = colorBuffer(image.width, image.height)
extend {
// -- need a white background because the filter introduces transparent areas
drawer.clear(ColorRGBa.WHITE)
filter.t1 = cos(seconds * PI) * 0.25 + 0.25
filter.t2 = filter.t1 + cos(seconds * 3) * 0.25 + 0.25
filter.t3 = filter.t2 + cos(seconds * 2) * 0.25 + 0.25
filter.t4 = filter.t3 + cos(seconds * 1) * 0.25 + 0.25
filter.apply(image, filtered)
drawer.image(filtered)
}
}
}
Shadow filters
DropShadow
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val filter = DropShadow()
val filtered = colorBuffer(image.width, image.height)
val rt = renderTarget(width, height) {
colorBuffer()
}
extend {
drawer.isolatedWithTarget(rt) {
drawer.clear(ColorRGBa.TRANSPARENT)
drawer.image(image, (image.width - image.width * 0.8) / 2, (image.height - image.height * 0.8) / 2, image.width * 0.8, image.height * 0.8)
}
// -- need a pink background because the filter introduces transparent areas
drawer.clear(ColorRGBa.PINK)
filter.window = (cos(seconds) * 16 + 16).toInt()
filter.xShift = cos(seconds * 2) * 16.0
filter.yShift = sin(seconds * 2) * 16.0
filter.apply(rt.colorBuffer(0), filtered)
drawer.image(filtered)
}
}
}
Pattern filters
Checkers
Checkers is a simple checker generator filter.
fun main() = application {
program {
val composite = compose {
layer {
post(Checkers()) {
size = cos(seconds) * 0.6 + 0.4
}
}
}
extend {
composite.draw(drawer)
}
}
}