diff --git a/orx-compositor/README.md b/orx-compositor/README.md new file mode 100644 index 00000000..8c469978 --- /dev/null +++ b/orx-compositor/README.md @@ -0,0 +1,44 @@ +# orx-compositor + +A simple toolkit to make composite images. + +##### Usage + +```kotlin +import org.openrndr.Configuration +import org.openrndr.Program +import org.openrndr.application +import org.openrndr.color.ColorRGBa +import org.openrndr.extra.compositor.* +import org.openrndr.filter.blend.add +import org.openrndr.filter.blur.ApproximateGaussianBlur + +class Compositor001 : Program() { + + override fun setup() { + val drawing = compose { + draw { + drawer.fill = ColorRGBa.PINK + drawer.circle(width / 2.0, height / 2.0, 10.0) + } + + layer { + 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 + } + blend(add) + } + } + + extend { + drawing.draw(drawer) + } + } +} + +fun main(args: Array) = application(Compositor001(), Configuration()) +``` diff --git a/orx-compositor/src/main/kotlin/Compositor.kt b/orx-compositor/src/main/kotlin/Compositor.kt new file mode 100644 index 00000000..f12c6e35 --- /dev/null +++ b/orx-compositor/src/main/kotlin/Compositor.kt @@ -0,0 +1,94 @@ +package org.openrndr.extra.compositor + +import org.openrndr.color.ColorRGBa +import org.openrndr.draw.* + +/** + * Layer representation + */ +class Layer internal constructor() { + + var drawFunc: () -> Unit = {} + val children: MutableList = mutableListOf() + var blendFilter: Pair Unit>? = null + val postFilters: MutableList Unit>> = mutableListOf() + + fun draw(drawer: Drawer) { + val rt = RenderTarget.active + val layerTarget = renderTarget(rt.width, rt.height) { + colorBuffer() + depthBuffer() + } + + drawer.isolatedWithTarget(layerTarget) { + drawer.background(ColorRGBa.TRANSPARENT) + children.reversed().forEach { + it.draw(drawer) + } + drawFunc() + } + + val (tmpTargets, layerPost) = postFilters.let { filters -> + val targets = List(Math.min(filters.size, 2)) { + colorBuffer(rt.width, rt.height) + } + val result = filters.foldIndexed(layerTarget.colorBuffer(0)) { i, source, filter -> + val target = targets[i % targets.size] + filter.first.apply(filter.second) + filter.first.apply(source, target) + target + } + Pair(targets, result) + } + + val lblend = blendFilter + if (lblend == null) { + drawer.isolatedWithTarget(rt) { + drawer.image(layerPost, layerPost.bounds, drawer.bounds) + } + } else { + lblend.first.apply(lblend.second) + lblend.first.apply(arrayOf(rt.colorBuffer(0), layerPost), rt.colorBuffer(0)) + } + + tmpTargets.forEach { + it.destroy() + } + + layerTarget.colorBuffer(0).destroy() + layerTarget.depthBuffer?.destroy() + layerTarget.detachColorBuffers() + layerTarget.detachDepthBuffer() + layerTarget.destroy() + } +} + +/** + * create a layer within the composition + */ +fun Layer.layer(function: Layer.() -> Unit) { + children.add(Layer().apply { function() }) +} + +fun Layer.draw(function: () -> Unit) { + drawFunc = function +} + +fun Layer.post(filter: F, configure: F.() -> Unit = {}) { + postFilters.add(Pair(filter as Filter, configure as Filter.() -> Unit)) +} + +fun Layer.blend(filter: F, configure: F.() -> Unit = {}) { + blendFilter = Pair(filter as Filter, configure as Filter.() -> Unit) +} + +/** + * create a layered composition + */ +fun compose(function: Layer.() -> Unit): Layer { + val root = Layer() + root.function() + return root +} + + diff --git a/orx-no-clear/src/main/kotlin/NoClear.kt b/orx-no-clear/src/main/kotlin/NoClear.kt index 45f848a7..857fb6b8 100644 --- a/orx-no-clear/src/main/kotlin/NoClear.kt +++ b/orx-no-clear/src/main/kotlin/NoClear.kt @@ -1,3 +1,5 @@ +package org.openrndr.extra.noclear + import org.openrndr.Extension import org.openrndr.Program import org.openrndr.color.ColorRGBa diff --git a/settings.gradle b/settings.gradle index bab4cb72..f30c382e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,7 +1,8 @@ rootProject.name = 'orx' -include 'orx-integral-image', - 'orx-jumpflood', - 'orx-kdtree', - 'orx-no-clear' +include 'orx-compositor', + 'orx-integral-image', + 'orx-jumpflood', + 'orx-kdtree', + 'orx-no-clear'