# 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: ```kotlin 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. ```kotlin 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: ```kotlin 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. ```kotlin 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 ```kotlin 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. ```kotlin fun main() = application { program { val composite = compose { val directionField = aside { draw { // [...] } } layer { draw { // [...] } post(DirectionalBlur(), directionField) } } extend { // draw the composite composite.draw(drawer) } } } ``` ##### Example ```kotlin 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](src/jvmDemo/kotlin/DemoAside01.kt) ![DemoAside01Kt](https://raw.githubusercontent.com/openrndr/orx/media/orx-compositor/images/DemoAside01Kt.png) ### DemoCompositor01 [source code](src/jvmDemo/kotlin/DemoCompositor01.kt) ![DemoCompositor01Kt](https://raw.githubusercontent.com/openrndr/orx/media/orx-compositor/images/DemoCompositor01Kt.png) ### DemoCompositor02 [source code](src/jvmDemo/kotlin/DemoCompositor02.kt) ![DemoCompositor02Kt](https://raw.githubusercontent.com/openrndr/orx/media/orx-compositor/images/DemoCompositor02Kt.png)