Add Post extension
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
108
orx-fx/src/commonMain/kotlin/Post.kt
Normal file
108
orx-fx/src/commonMain/kotlin/Post.kt
Normal 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!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
27
orx-fx/src/demo/kotlin/DemoPost01.kt
Normal file
27
orx-fx/src/demo/kotlin/DemoPost01.kt
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user