Add README.md for TemporalBlur
This commit is contained in:
@@ -23,7 +23,7 @@ A growing library of assorted data structures, algorithms and utilities.
|
|||||||
- [`orx-olive`](orx-olive/README.md), extensions that turns OPENRNDR in to a live coding environment
|
- [`orx-olive`](orx-olive/README.md), extensions that turns OPENRNDR in to a live coding environment
|
||||||
- [`orx-osc`](orx-osc/README.md), open sound control interface
|
- [`orx-osc`](orx-osc/README.md), open sound control interface
|
||||||
- [`orx-palette`](orx-palette/README.md), manage color palettes
|
- [`orx-palette`](orx-palette/README.md), manage color palettes
|
||||||
|
- [`orx-temporal-blur`](orx-temporal-blur/README.md), temporal (motion) blur for video production.
|
||||||
# Developer notes
|
# Developer notes
|
||||||
|
|
||||||
## Create and use local builds of the library
|
## Create and use local builds of the library
|
||||||
|
|||||||
44
orx-temporal-blur/README.md
Normal file
44
orx-temporal-blur/README.md
Normal 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
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
package org.openrndr.extra.temporalblur
|
||||||
|
|
||||||
import org.openrndr.Extension
|
import org.openrndr.Extension
|
||||||
import org.openrndr.Program
|
import org.openrndr.Program
|
||||||
import org.openrndr.color.ColorRGBa
|
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.delinearize
|
||||||
import org.openrndr.filter.color.linearize
|
import org.openrndr.filter.color.linearize
|
||||||
import org.openrndr.math.Matrix44
|
import org.openrndr.math.Matrix44
|
||||||
|
import org.openrndr.math.Matrix55
|
||||||
import org.openrndr.math.Vector2
|
import org.openrndr.math.Vector2
|
||||||
import org.openrndr.math.transforms.translate
|
import org.openrndr.math.transforms.translate
|
||||||
|
|
||||||
@@ -27,6 +30,7 @@ class TemporalBlur : Extension {
|
|||||||
* number of samples to take, more is slower
|
* number of samples to take, more is slower
|
||||||
*/
|
*/
|
||||||
var samples = 30
|
var samples = 30
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* duration in frames, shouldn't be 1.0 or larger when using Animatables
|
* duration in frames, shouldn't be 1.0 or larger when using Animatables
|
||||||
*/
|
*/
|
||||||
@@ -121,20 +125,22 @@ class TemporalBlur : Extension {
|
|||||||
drawer.background(ColorRGBa.BLACK)
|
drawer.background(ColorRGBa.BLACK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val oldClock = program.clock
|
||||||
|
val oldClockValue = oldClock()
|
||||||
|
|
||||||
for (i in samples - 1 downTo 1) {
|
for (i in samples - 1 downTo 1) {
|
||||||
image?.bind()
|
image?.bind()
|
||||||
|
|
||||||
drawer.background(ColorRGBa.BLACK)
|
drawer.background(ColorRGBa.BLACK)
|
||||||
|
program.clock = { oldClockValue - (i * duration) / (fps * samples) }
|
||||||
val oldClock = program.clock
|
|
||||||
program.clock = { oldClock() - (i * duration) / (fps * samples) }
|
|
||||||
|
|
||||||
// I guess we need something better here.
|
// I guess we need something better here.
|
||||||
val fsf = Program::class.java.getDeclaredField("frameSeconds")
|
val fsf = Program::class.java.getDeclaredField("frameSeconds")
|
||||||
fsf.isAccessible = true
|
fsf.isAccessible = true
|
||||||
fsf.setDouble(program, program.clock())
|
fsf.setDouble(program, program.clock())
|
||||||
|
|
||||||
|
drawer.drawStyle.blendMode = BlendMode.OVER
|
||||||
|
drawer.drawStyle.colorMatrix = Matrix55.IDENTITY
|
||||||
drawer.isolated {
|
drawer.isolated {
|
||||||
val offset = Vector2.uniformRing(0.0, jitter)
|
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
|
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.view = Matrix44.IDENTITY
|
||||||
|
|
||||||
drawer.isolatedWithTarget(result!!) {
|
drawer.isolatedWithTarget(result!!) {
|
||||||
|
drawer.drawStyle.blendMode = BlendMode.OVER
|
||||||
|
|
||||||
drawer.background(ColorRGBa.BLACK)
|
drawer.background(ColorRGBa.BLACK)
|
||||||
drawer.drawStyle.colorMatrix = tint(ColorRGBa.WHITE.shade(1.0 / samples))
|
drawer.drawStyle.colorMatrix = tint(ColorRGBa.WHITE.shade(1.0 / samples))
|
||||||
drawer.image(accumulator!!.colorBuffer(0))
|
drawer.image(accumulator!!.colorBuffer(0))
|
||||||
@@ -188,6 +196,11 @@ class TemporalBlur : Extension {
|
|||||||
if (delinearizeOutput) {
|
if (delinearizeOutput) {
|
||||||
delinearize.apply(result!!.colorBuffer(0), result!!.colorBuffer(0))
|
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))
|
drawer.image(result!!.colorBuffer(0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user