Distance fields using orx-jumpflood
Prerequisites
Assuming you are working on an
openrndr-template based
project, all you have to do is to add implementation(orx.jumpflood)
to the dependencies block in build.gradle.kts and reload Gradle,
as described in ORX.
Distance field visualization
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.ColorType
import org.openrndr.draw.loadImage
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.jumpfill.DistanceField
import org.openrndr.extra.jumpfill.fx.InnerGlow
import org.openrndr.extra.jumpfill.fx.OuterGlow
import kotlin.math.cos
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val c = compose {
layer {
colorType = ColorType.FLOAT32
draw {
drawer.image(image)
}
post(DistanceField()) {
threshold = cos(seconds) * 0.5 + 0.5
distanceScale = 0.008
}
}
}
extend {
// FIXME
//c.draw(drawer)
}
}
}
Outer glow
orx-jumpflood comes with a filter that creates Photoshop-style outer glow effect.
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.ColorType
import org.openrndr.draw.loadImage
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.jumpfill.DistanceField
import org.openrndr.extra.jumpfill.fx.InnerGlow
import org.openrndr.extra.jumpfill.fx.OuterGlow
import kotlin.math.cos
fun main() = application {
program {
val c = compose {
layer {
draw {
drawer.fill = ColorRGBa.PINK
drawer.circle(width / 2.0, height / 2.0, 200.0)
}
post(OuterGlow()) {
this.width = (cos(seconds) * 0.5 + 0.5) * 100.0
}
}
}
extend {
// FIXME
//c.draw(drawer)
}
}
}
Inner glow
Similar to the outer glow effect, but the glow is placed in the inside of the shape.
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.ColorType
import org.openrndr.draw.loadImage
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.jumpfill.DistanceField
import org.openrndr.extra.jumpfill.fx.InnerGlow
import org.openrndr.extra.jumpfill.fx.OuterGlow
import kotlin.math.cos
fun main() = application {
program {
val c = compose {
layer {
draw {
drawer.fill = ColorRGBa.PINK
drawer.circle(width / 2.0, height / 2.0, 200.0)
}
post(InnerGlow()) {
this.width = (cos(seconds) * 0.5 + 0.5) * 100.0
}
}
}
extend {
// FIXME
//c.draw(drawer)
}
}
}
Sampling distance
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.ColorType
import org.openrndr.draw.loadImage
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.jumpfill.DistanceField
import org.openrndr.extra.jumpfill.fx.InnerGlow
import org.openrndr.extra.jumpfill.fx.OuterGlow
import kotlin.math.cos
fun main() = application {
program {
val image = loadImage("data/images/cheeta.jpg")
val c = compose {
// -- make sure accumulation is done in float32
colorType = ColorType.FLOAT32
layer {
colorType = ColorType.FLOAT32
draw {
drawer.image(image)
}
post(DistanceField()) {
threshold = cos(seconds) * 0.5 + 0.5
distanceScale = 1.0
}
}
layer {
draw {
// -- use the accumulation buffer to get the distance field
accumulation?.let {
val s = it.shadow
s.download()
drawer.fill = ColorRGBa.PINK
drawer.stroke = null
for (y in 0 until height step 10) {
for (x in 0 until width step 10) {
val distance = s[x, y].r
drawer.circle(x * 1.0, y * 1.0, distance * 0.05)
}
}
// -- clear the accumulated contents
it.fill(ColorRGBa.TRANSPARENT)
}
}
}
}
extend {
// FIXME
//c.draw(drawer)
}
}
}