Add README.md for TemporalBlur

This commit is contained in:
Edwin Jakobs
2019-11-28 10:54:27 +01:00
parent d41a997cd6
commit 3ce6a7d020
3 changed files with 61 additions and 4 deletions

View File

@@ -0,0 +1,44 @@
# orx-temporal-blur
`orx-temporal-blur` is a an extension intended for off-line production;
i.e. videos made using the `ScreenRecorder` extension. This extension uses multi-sampling
to accumulate and average the final image. Multi-sampling is performed by modifying `Program.clock`
while processing the tail-end of the extension chain. This multi-sampling strategy is slow and not
entirely suited in real-time and/or interactive settings.
`orx-temporal-blur` works well with programs that use `seconds` for their animation input.
This includes `Animatables`, but only after the `Animatable` clock is synchronized with the `Program` clock.
(Which you should already have done when using `ScreenRecorder`)
Synchronizing clocks in OPENRNDR 0.3.36 (current release):
```
Animatable.clock(object: Clock {
override val time: Long
get() = (clock() * 1E3).toLong()
})
```
Synchronizing high precision clocks in OPENRNDR 0.3.37 (future release)
```
Animatable.clock(object: Clock {
override val time: Long
get() = timeNanos / 1000
override val timeNanos: Long
get() = (clock() * 1E6).toLong()
})
```
Note that time-step-based simulations or integrations will likely break because your drawing code will be executed multiple times
per frame.
## Configuration
```kotlin
extend(TemporalBlur()) {
duration = 0.9
samples = 30
fps = 60.0
jitter = 1.0
}
```

View File

@@ -1,3 +1,5 @@
package org.openrndr.extra.temporalblur
import org.openrndr.Extension
import org.openrndr.Program
import org.openrndr.color.ColorRGBa
@@ -7,6 +9,7 @@ import org.openrndr.filter.blend.add
import org.openrndr.filter.color.delinearize
import org.openrndr.filter.color.linearize
import org.openrndr.math.Matrix44
import org.openrndr.math.Matrix55
import org.openrndr.math.Vector2
import org.openrndr.math.transforms.translate
@@ -27,6 +30,7 @@ class TemporalBlur : Extension {
* number of samples to take, more is slower
*/
var samples = 30
/**
* duration in frames, shouldn't be 1.0 or larger when using Animatables
*/
@@ -121,20 +125,22 @@ class TemporalBlur : Extension {
drawer.background(ColorRGBa.BLACK)
}
}
val oldClock = program.clock
val oldClockValue = oldClock()
for (i in samples - 1 downTo 1) {
image?.bind()
drawer.background(ColorRGBa.BLACK)
val oldClock = program.clock
program.clock = { oldClock() - (i * duration) / (fps * samples) }
program.clock = { oldClockValue - (i * duration) / (fps * samples) }
// I guess we need something better here.
val fsf = Program::class.java.getDeclaredField("frameSeconds")
fsf.isAccessible = true
fsf.setDouble(program, program.clock())
drawer.drawStyle.blendMode = BlendMode.OVER
drawer.drawStyle.colorMatrix = Matrix55.IDENTITY
drawer.isolated {
val offset = Vector2.uniformRing(0.0, jitter)
drawer.projection = Matrix44.translate(offset.x * (1.0 / program.width), offset.y * (1.0 / program.height), 0.0) * drawer.projection
@@ -181,6 +187,8 @@ class TemporalBlur : Extension {
drawer.view = Matrix44.IDENTITY
drawer.isolatedWithTarget(result!!) {
drawer.drawStyle.blendMode = BlendMode.OVER
drawer.background(ColorRGBa.BLACK)
drawer.drawStyle.colorMatrix = tint(ColorRGBa.WHITE.shade(1.0 / samples))
drawer.image(accumulator!!.colorBuffer(0))
@@ -188,6 +196,11 @@ class TemporalBlur : Extension {
if (delinearizeOutput) {
delinearize.apply(result!!.colorBuffer(0), result!!.colorBuffer(0))
}
drawer.drawStyle.blendMode = BlendMode.OVER
drawer.drawStyle.colorMatrix = Matrix55.IDENTITY
drawer.drawStyle.depthTestPass = DepthTestPass.ALWAYS
drawer.background(ColorRGBa.BLACK)
drawer.image(result!!.colorBuffer(0))
}
}