Add Post extension

This commit is contained in:
Edwin Jakobs
2022-08-22 22:22:06 +02:00
parent 7853a1a1b3
commit 7d7c26758f
4 changed files with 167 additions and 1 deletions

View File

@@ -108,7 +108,36 @@ All distortion effects are opacity preserving
### Transform
- `FlipVertically` - flips the source input vertically.
## `Post` extension
The `Post` extension provides an easy way to apply filters to your drawings. Allocating
and resizing color buffers is all taken care of by `Post`.
To get additional intermediate color buffers one can access `intermediate[x]`
```kotlin
fun main() = application {
configure {
windowResizable = true
}
program {
extend(Post()) {
val blur = ApproximateGaussianBlur()
val add = Add()
post { input, output ->
blur.window = 50
blur.sigma = 50.0
blur.apply(input, intermediate[0])
add.apply(arrayOf(input, intermediate[0]), output)
}
}
extend {
drawer.circle(width / 2.0, height / 2.0, 100.0)
}
}
}
```
<!-- __demos__ >
# Demos
[DemoFluidDistort01Kt](src/demo/kotlin/DemoFluidDistort01Kt.kt

View File

@@ -23,6 +23,8 @@ kotlin {
dependencies {
implementation(project(":orx-color"))
implementation(project(":orx-camera"))
implementation(project(":orx-fx"))
implementation(libs.openrndr.application)
implementation(libs.openrndr.extensions)
runtimeOnly(libs.openrndr.gl3.core)

View File

@@ -0,0 +1,108 @@
package org.openrndr.extra.fx
import org.openrndr.Extension
import org.openrndr.Program
import org.openrndr.draw.*
class Post : Extension {
override var enabled = true
private var inputTarget: RenderTarget? = null
private var resolved: ColorBuffer? = null
/**
* The color type to use for the intermediate color buffers
*/
var intermediateType = ColorType.UINT8
/**
* The color type to use for the output color buffer
*/
var outputType = ColorType.UINT8
/**
* The color type to use for the input buffer
*/
var inputType = ColorType.UINT8
private var output: ColorBuffer? = null
private var postFunction = { input: ColorBuffer, output: ColorBuffer -> input.copyTo(output) }
inner class IntermediateBuffers {
internal val buffers = mutableMapOf<Int, ColorBuffer>()
operator fun get(index: Int) : ColorBuffer {
return buffers.getOrPut(index) {
colorBuffer(output!!.width, output!!.height, output!!.contentScale, type = intermediateType)
}
}
}
/**
* Intermediate buffer pool, provides automatically allocated color buffers
*/
val intermediate = IntermediateBuffers()
/**
* Set the post function
* @param function the post function
*/
fun post(function: (input: ColorBuffer, output: ColorBuffer) -> Unit) {
postFunction = function
}
override fun beforeDraw(drawer: Drawer, program: Program) {
val art = RenderTarget.active
val lit = inputTarget
if (lit != null) {
// in case the attributes of the existing buffers no longer match those of the active render target
if (lit.width != art.width || lit.height != art.height || lit.contentScale != art.contentScale || lit.multisample != art.multisample) {
lit.colorBuffer(0).destroy()
lit.detachColorAttachments()
lit.destroy()
inputTarget = null
resolved?.destroy()
resolved = null
output?.destroy()
output = null
for (buffer in intermediate.buffers.values) {
buffer.destroy()
}
intermediate.buffers.clear()
}
}
if (inputTarget == null) {
// create new targets and buffers
inputTarget = renderTarget(art.width, art.height, art.contentScale, multisample = art.multisample) {
colorBuffer(type = inputType)
}
if (art.multisample != BufferMultisample.Disabled) {
resolved = colorBuffer(art.width, art.height, art.contentScale)
}
output = colorBuffer(art.width, art.height, art.contentScale, type = outputType)
}
// bind input target, the next extensions will draw into it
inputTarget!!.bind()
}
override fun afterDraw(drawer: Drawer, program: Program) {
inputTarget!!.unbind()
if (resolved != null) {
inputTarget!!.colorBuffer(0).copyTo(resolved!!)
}
val postInput = resolved ?: inputTarget!!.colorBuffer(0)
// invoke the user provided post-processing function
postFunction(postInput, output!!)
// visualize the results
drawer.isolated {
drawer.defaults()
drawer.image(output!!)
}
}
}

View File

@@ -0,0 +1,27 @@
import org.openrndr.WindowMultisample
import org.openrndr.application
import org.openrndr.extra.fx.Post
import org.openrndr.extra.fx.blend.Add
import org.openrndr.extra.fx.blur.ApproximateGaussianBlur
fun main() = application {
configure {
windowResizable = true
}
program {
extend(Post()) {
val blur = ApproximateGaussianBlur()
val add = Add()
post { input, output ->
blur.window = 50
blur.sigma = 50.0
blur.apply(input, intermediate[0])
add.apply(arrayOf(input, intermediate[0]), output)
}
}
extend {
drawer.circle(width / 2.0, height / 2.0, 100.0)
}
}
}