Poisson fills
orx-poisson-fills offers tool for GPU-based Poisson operations.
Prerequisites
Assuming you are working on an openrndr-template based project, all you have to do is enable orx-poisson-fills in the orxFeatures set in build.gradle.kts and reimport the gradle project.
Filling
The PoissonFill filter can be used to fill in transparent parts of an image. In the following example we use orx-compose to simplify the code a bit. The same results can be achieved using render targets.
fun main() = application {
program {
val c = compose {
layer {
draw {
drawer.stroke = null
drawer.fill = ColorRGBa.RED
drawer.circle((cos(seconds) * 0.5 + 0.5) * width, (sin(seconds * 0.5) * 0.5 + 0.5) * height, 20.0)
drawer.fill = ColorRGBa.PINK
drawer.circle((sin(seconds * 2.0) * 0.5 + 0.5) * width, (cos(seconds) * 0.5 + 0.5) * height, 20.0)
drawer.fill = ColorRGBa.BLACK
drawer.circle((sin(seconds * 1.0) * 0.5 + 0.5) * width, (cos(seconds * 2.0) * 0.5 + 0.5) * height, 20.0)
}
post(PoissonFill())
}
layer {
// -- an extra layer just to demonstrate where the original data points are drawn
draw {
drawer.stroke = ColorRGBa.WHITE
drawer.strokeWeight = 5.0
drawer.fill = ColorRGBa.RED
drawer.circle((cos(seconds) * 0.5 + 0.5) * width, (sin(seconds * 0.5) * 0.5 + 0.5) * height, 20.0)
drawer.fill = ColorRGBa.PINK
drawer.circle((sin(seconds * 2.0) * 0.5 + 0.5) * width, (cos(seconds) * 0.5 + 0.5) * height, 20.0)
drawer.fill = ColorRGBa.BLACK
drawer.circle((sin(seconds * 1.0) * 0.5 + 0.5) * width, (cos(seconds * 2.0) * 0.5 + 0.5) * height, 20.0)
}
}
}
extend {
c.draw(drawer)
}
}
}
fun main() = application {
program {
val c = compose {
layer {
val image = loadImage("data/images/cheeta.jpg")
draw {
drawer.image(image, Rectangle((cos(seconds) * 0.5 + 0.5) * 100.0, (sin(seconds) * 0.5 + 0.5) * 100.0, 200.0, 200.0), Rectangle(width / 2 - 100.0, height / 2.0 - 100.0, 200.0, 200.0))
}
post(PoissonFill())
}
}
extend {
c.draw(drawer)
}
}
}
Blending
fun main() = application {
program {
val c = compose {
layer {
val image = loadImage("data/images/cheeta.jpg")
draw {
drawer.image(image)
}
}
layer {
draw {
drawer.stroke = null
drawer.fill = ColorRGBa.BLACK
drawer.circle((cos(seconds) * 0.5 + 0.5) * width, (sin(seconds * 0.5) * 0.5 + 0.5) * height, 120.0)
}
blend(PoissonBlend())
}
}
extend {
c.draw(drawer)
}
}
}
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val c = compose {
layer {
draw {
drawer.image(image)
}
}
layer {
draw {
drawer.stroke = ColorRGBa.GRAY
drawer.fill = null
drawer.strokeWeight = 40.0
drawer.circle((cos(seconds) * 0.5 + 0.5) * width, (sin(seconds * 0.5) * 0.5 + 0.5) * height, 120.0)
}
post(LumaOpacity()) {
this.backgroundLuma = 0.25
}
blend(PoissonBlend())
}
}
extend {
c.draw(drawer)
}
}
}