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)
        }
    }
}

Link to the full example

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)
        }
    }
}

Link to the full example

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)
        }
    }
}

Link to the full example

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)
        }
    }
}

Link to the full example

edit on GitHub