Skip to content

Latest commit

 

History

History

orx-compositor

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

orx-compositor

Toolkit to make composite (layered) images using blend modes and filters.

Usage

A Composite is made using the compose {} builder. We start with a very simple example:

fun main() = application {
    program {
        val composite = compose {
            // this is only executed once
            val position = Vector2(100.0, 100.0)
            
            draw {
                // code inside draw blocks is executed whenever the composite is drawn
                drawer.circle(position, 100.0)
            }
        }
        extend {
            // draw the composite
            composite.draw(drawer)
        }
    }
}

Layers

A Composite with two layers looks like this.

fun main() = application {
    program {
        val composite = compose {
            // this layer is drawn first
            layer {
                val position = Vector2(100.0, 100.0)
                draw {
                    drawer.circle(position, 100.0)
                }
            }
            
            // this layer is drawn second
            layer {
                val position = Vector2(150.0, 150.0)
                draw {
                    drawer.circle(position, 100.0)
                }
                blend(Multiply())
            }
        }
        extend {
            // draw the composite
            composite.draw(drawer)
        }
    }
}

Layers can be nested:

fun main() = application {
    program {
        val composite = compose {
            layer {
                layer {
                    // this draw is processed first
                    draw { }
                }
                layer {
                    // this draw is processed second
                    draw { }
                }
                val position = Vector2(100.0, 100.0)
                draw {
                    // this draw is processed third
                    drawer.circle(position, 100.0)
                }
            }
            
            // this layer is drawn second
            layer {
                val position = Vector2(150.0, 150.0)
                draw {
                    drawer.circle(position, 100.0)
                }
                blend(Multiply())
            }
        }
        extend {
            // draw the composite
            composite.draw(drawer)
        }
    }
}

Asides

An aside is a layer which output is not directly included in the composite drawing. The contents of an aside can be used in layers and post-processing.

fun main() = application {
    program {
        val composite = compose {
            
            val a = aside {
                val position = Vector2(250.0, 250.0)
                draw {
                    drawer.circle(position, 100.0)
                }
            }
            
            // this layer is drawn second
            layer {
                val position = Vector2(150.0, 150.0)
                draw {
                    drawer.image(a)
                    drawer.circle(position, 100.0)
                }
                blend(Multiply())
            }
        }
        extend {
            // draw the composite
            composite.draw(drawer)
        }
    }
}

Post-processing

fun main() = application {
    program {
        val composite = compose {
            layer {
                draw {
                    
                }
                // the first Filter1to1 to apply
                post(ApproximateGaussianBlur()) {
                    // here is code that is executed everytime the layer is drawn
                }
                
                // the second Filter1to1 to apply
                post(ColorCorrection()) {
                    // here is code that is executed everytime the layer is drawn
                }
            }
        }
        extend {
            // draw the composite
            composite.draw(drawer)
        }
    }
}

Using filters with multiple inputs

Some filters use more than a single input in producing their output, these filters inherit from Filter2to1, Filter3to1, Filter4to1 etc. One such filter is DirectionalBlur which has image and direction field inputs. In the following example we use an aside to draw a direction field which is fed into the blur filter.

fun main() = application {
    program {
        val composite = compose {
            val directionField = aside {
                draw {
                    // [...]
                }
            }
            layer {
                draw {
                    // [...]
                }
                post(DirectionalBlur(), directionField)
            }
        }
        extend {
            // draw the composite
            composite.draw(drawer)
        }
    }
}
Example
import org.openrndr.application
import org.openrndr.draw.loadImage
import org.openrndr.extra.compositor.*
import org.openrndr.extra.fx.blend.Add
import org.openrndr.extra.fx.edges.EdgesWork
import org.openrndr.extra.gui.GUI
import org.openrndr.math.Vector2

fun main() {
    application {
        configure {
            width = 768
            height = 768
        }
        program {
            val w2 = width / 2.0
            val h2 = height / 2.0

            val c = compose {
                draw {
                    drawer.fill = ColorRGBa.PINK
                    drawer.circle(width / 2.0, height / 2.0, 10.0)
                }
    
                layer {
                    blend(Add())

                    draw {
                        drawer.circle(width / 2.0, height / 2.0, 100.0)
                    }
                    post(ApproximateGaussianBlur()) {
                        window = 10
                        sigma = Math.cos(seconds * 10.0) * 10.0 + 10.0
                    }
                }
            }
            extend(gui)
            extend {
                c.draw(drawer)
            }
        }
    }
}

Demos

DemoAside01

source code

DemoAside01Kt

DemoCompositor01

source code

DemoCompositor01Kt

DemoCompositor02

source code

DemoCompositor02Kt