[orx-fx] convert to MPP

This commit is contained in:
Edwin Jakobs
2021-06-27 21:07:44 +02:00
parent 7d524df2de
commit 4dfc5c31c8
144 changed files with 1197 additions and 847 deletions

View File

@@ -0,0 +1,65 @@
package org.openrndr.extra.fx.blur
import org.openrndr.draw.*
import org.openrndr.extra.fx.ColorBufferDescription
import org.openrndr.extra.fx.fx_approximate_gaussian_blur
import org.openrndr.extra.fx.mppFilterShader
import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter
import org.openrndr.extra.parameters.IntParameter
import org.openrndr.math.Vector2
/**
* Approximate separated Gaussian blur
*/
@Description("Approximate Gaussian blur")
class ApproximateGaussianBlur : Filter(mppFilterShader(fx_approximate_gaussian_blur, "approximate gaussian blur")) {
/**
* blur sample window, default value is 5
*/
@IntParameter("window size", 1, 25)
var window: Int by parameters
/**
* spread multiplier, default value is 1.0
*/
@DoubleParameter("kernel spread", 1.0, 4.0)
var spread: Double by parameters
/**
* blur sigma, default value is 1.0
*/
@DoubleParameter("kernel sigma", 0.0, 25.0)
var sigma: Double by parameters
/**
* post blur gain, default value is 1.0
*/
@DoubleParameter("gain", 0.0, 4.0)
var gain: Double by parameters
private var intermediateCache = mutableMapOf<ColorBufferDescription, ColorBuffer>()
init {
window = 5
spread = 1.0
gain = 1.0
sigma = 1.0
}
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
val intermediateDescription = ColorBufferDescription(target[0].width, target[0].height, target[0].contentScale, target[0].format, target[0].type)
val intermediate = intermediateCache.getOrPut(intermediateDescription) {
colorBuffer(target[0].width, target[0].height, target[0].contentScale, target[0].format, target[0].type)
}
intermediate.let {
parameters["blurDirection"] = Vector2(1.0, 0.0)
super.apply(source, arrayOf(it))
parameters["blurDirection"] = Vector2(0.0, 1.0)
super.apply(arrayOf(it), target)
}
}
}

View File

@@ -0,0 +1,86 @@
package org.openrndr.extra.fx.blur
import org.openrndr.draw.*
import org.openrndr.extra.fx.blend.Add
import org.openrndr.extra.fx.fx_bloom
import org.openrndr.extra.fx.mppFilterShader
import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter
import org.openrndr.extra.parameters.IntParameter
@Description("Bloom")
class Bloom(blur: Filter = ApproximateGaussianBlur()) : Filter(mppFilterShader(fx_bloom, "bloom")) {
/**
* the blur filter to use for the bloom, default is Approximate Gaussian Blur
*/
var blur: Filter = blur
/**
* number of downsampled textures to use, default value is 2
*/
@IntParameter("blur iterations", 1, 8)
var downsamples: Int = 2
/**
* rate of downsampling, f.ex: 4 -> 4x, 8x, 16x.., default value is 2
*/
@IntParameter("downsamping rate", 1, 4)
var downsampleRate: Int = 2
/**
* blending amount between original image and blurred, default value is 0.5
*/
@DoubleParameter("blend factor", 0.0, 1.0)
var blendFactor: Double by parameters
/**
* brightness of the resulting image, default value is 0.5
*/
@DoubleParameter("brightness", 0.0, 1.0)
var brightness: Double by parameters
init {
blendFactor = 0.5
brightness = 0.5
}
private val samplers: MutableList<Pair<ColorBuffer, ColorBuffer>> = mutableListOf()
private var lastDownsampleRate = 0
private val blendAdd = Add()
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
val src = source[0]
val dest = target[0]
if (samplers.isEmpty() || samplers.size != downsamples || lastDownsampleRate != downsampleRate) {
samplers.clear()
lastDownsampleRate = downsampleRate
for (downsample in 0 until downsamples) {
val div = 1 shl downsample
val bufferA = colorBuffer(dest.width / div, dest.height / div, 1.0, target[0].format, ColorType.FLOAT16)
val bufferB = colorBuffer(dest.width / div, dest.height / div, 1.0, target[0].format, ColorType.FLOAT16)
samplers.add(Pair(bufferA, bufferB))
}
}
for ((bufferA, _) in samplers) {
blur.apply(src, bufferA)
}
for ((index, buffers) in samplers.asReversed().withIndex()) {
val (bufferCurrA) = buffers
if (index + 1 <= samplers.lastIndex) {
val (bufferNextA, bufferNextB) = samplers.asReversed()[index + 1]
blur.apply(bufferCurrA, bufferNextB)
blendAdd.apply(arrayOf(bufferNextA, bufferNextB), bufferNextA)
} else {
super.apply(arrayOf(src, bufferCurrA), target)
}
}
}
}

View File

@@ -0,0 +1,60 @@
package org.openrndr.extra.fx.blur
import org.openrndr.draw.*
import org.openrndr.extra.fx.fx_box_blur
import org.openrndr.extra.fx.mppFilterShader
import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter
import org.openrndr.extra.parameters.IntParameter
import org.openrndr.math.Vector2
/**
* BoxBlur implemented as a separable filter
*/
@Description("Box-blur")
class BoxBlur : Filter(mppFilterShader(fx_box_blur,"box-blur")) {
data class ColorBufferDescription(val width: Int, val height: Int, val contentScale: Double, val format: ColorFormat, val type: ColorType)
/**
* The sample window, default is 5
*/
@IntParameter("window size", 1, 25)
var window: Int by parameters
/**
* Spread multiplier, default is 1.0
*/
@DoubleParameter("kernel spread", 1.0, 4.0)
var spread: Double by parameters
/**
* Post-blur gain, default is 1.0
*/
@DoubleParameter("gain", 0.0, 4.0)
var gain: Double by parameters
private var intermediateCache = mutableMapOf<ColorBufferDescription, ColorBuffer>()
init {
window = 5
spread = 1.0
gain = 1.0
}
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
val intermediateDescription = ColorBufferDescription(target[0].width, target[0].height, target[0].contentScale, target[0].format, target[0].type)
val intermediate = intermediateCache.getOrPut(intermediateDescription) {
colorBuffer(target[0].width, target[0].height, target[0].contentScale, target[0].format, target[0].type)
}
intermediate.let {
parameters["blurDirection"] = Vector2(1.0, 0.0)
super.apply(source, arrayOf(it))
parameters["blurDirection"] = Vector2(0.0, 1.0)
super.apply(arrayOf(it), target)
}
}
}

View File

@@ -0,0 +1,41 @@
package org.openrndr.extra.fx.blur
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.*
import org.openrndr.extra.fx.fx_frame_blur
import org.openrndr.extra.fx.mppFilterShader
import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter
@Description("Frame blur")
class FrameBlur : Filter(mppFilterShader(fx_frame_blur, "frame-blur")) {
@DoubleParameter("blend", 0.0, 1.0)
var blend: Double by parameters
private var intermediate: ColorBuffer? = null
init {
blend = 0.5
}
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
if (target.isNotEmpty()) {
intermediate?.let {
if (it.width != target[0].width || it.height != target[0].height) {
it.destroy()
intermediate = null
}
}
if (intermediate == null) {
intermediate = colorBuffer(target[0].width, target[0].height, type = ColorType.FLOAT16)
//intermediate?.fill(ColorRGBa.TRANSPARENT)
TODO("no mpp colorbuffer.fill")
}
super.apply(arrayOf(source[0], intermediate!!), arrayOf(intermediate!!))
intermediate!!.copyTo(target[0])
}
}
}

View File

@@ -0,0 +1,47 @@
package org.openrndr.extra.fx.blur
import org.openrndr.draw.Filter
import org.openrndr.extra.fx.fx_gaussian_blur
import org.openrndr.extra.fx.mppFilterShader
import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter
import org.openrndr.extra.parameters.IntParameter
/**
* Exact Gaussian blur, implemented as a single pass filter
*/
@Description("Gaussian blur")
class GaussianBlur : Filter(mppFilterShader(fx_gaussian_blur,"gaussian-blur")) {
/**
* The sample window, default value is 5
*/
@IntParameter("window size", 1, 25)
var window: Int by parameters
/**
* Spread multiplier, default value is 1.0
*/
@DoubleParameter("kernel spread", 1.0, 4.0)
var spread: Double by parameters
/**
* Blur kernel sigma, default value is 1.0
*/
@DoubleParameter("kernel sigma", 0.0, 25.0)
var sigma: Double by parameters
/**
* Post-blur gain, default value is 1.0
*/
@DoubleParameter("gain", 0.0, 4.0)
var gain: Double by parameters
init {
window = 5
spread = 1.0
sigma = 1.0
gain = 1.0
}
}

View File

@@ -0,0 +1,41 @@
package org.openrndr.extra.fx.blur
import org.openrndr.draw.Filter
import org.openrndr.extra.fx.fx_hash_blur
import org.openrndr.extra.fx.mppFilterShader
import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter
import org.openrndr.extra.parameters.IntParameter
@Description("Hash blur")
class HashBlur : Filter(mppFilterShader(fx_hash_blur, "hash-blur")) {
/**
* Blur radius in pixels, default is 5.0
*/
@DoubleParameter("blur radius", 1.0, 25.0)
var radius: Double by parameters
/**
* Time/seed, this should be fed with seconds, default is 0.0
*/
var time: Double by parameters
/**
* Number of samples, default is 30
*/
@IntParameter("number of samples", 1, 100)
var samples: Int by parameters
/**
* Post-blur gain, default is 1.0
*/
@DoubleParameter("image gain", 0.0, 2.0)
var gain: Double by parameters
init {
radius = 5.0
time = 0.0
samples = 30
gain = 1.0
}
}

View File

@@ -0,0 +1,119 @@
package org.openrndr.extra.fx.blur
import org.openrndr.draw.*
import org.openrndr.extra.fx.fx_laser_blur
import org.openrndr.extra.fx.mppFilterShader
import org.openrndr.extra.parameters.*
import org.openrndr.math.Vector2
import kotlin.math.pow
private class LaserBlurPass : Filter(mppFilterShader(fx_laser_blur, "laser-blur")) {
var radius: Double by parameters
var amp0: Double by parameters
var amp1: Double by parameters
var center: Vector2 by parameters
var vignette: Double by parameters
var vignetteSize: Double by parameters
var aberration: Double by parameters
var linearInput: Boolean by parameters
var linearOutput: Boolean by parameters
init {
radius = 0.0
amp0 = 1.0
amp1 = 1.0
center = Vector2.ZERO
vignette = 0.0
vignetteSize = 1.0
aberration = 0.0
linearInput = false
linearOutput = false
}
}
@Description("Laser blur")
class LaserBlur : Filter() {
@Vector2Parameter("center", order = 0)
var center = Vector2.ZERO
@DoubleParameter("radius", -2.0, 2.0, order = 1)
var radius = -0.18
@DoubleParameter("amp0", 0.0, 1.0, order = 2)
var amp0 = 0.5
@DoubleParameter("amp1", 0.0, 1.0, order = 3)
var amp1 = 0.5
@DoubleParameter("vignette", 0.0, 1.0, order = 4)
var vignette = 0.0
@DoubleParameter("vignette size", 0.0, 1.0, order = 5)
var vignetteSize = 0.0
@DoubleParameter("aberration", -1.0, 1.0, order = 6)
var aberration = 0.006
@DoubleParameter("exp", -1.0, 1.0, order = 7)
var exp = 0.739
@BooleanParameter("linear input", order = 8)
var linearInput = false
@BooleanParameter("linear output", order = 9)
var linearOutput = false
@DoubleParameter("phase", -1.0, 1.0, order = 7)
var phase = 0.0
private val pass = LaserBlurPass()
@IntParameter("passes", 2, 32, order = 4)
var passes = 15
val intermediates = mutableListOf<ColorBuffer>()
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
pass.center = center
pass.radius = radius
pass.amp0 = amp0
pass.amp1 = amp1
pass.vignette = vignette
pass.vignetteSize = vignetteSize
pass.aberration = aberration
if ((!intermediates.all { it.isEquivalentTo(source[0], ignoreFormat = true, ignoreType = true) })) {
intermediates.forEach {
it.destroy()
}
intermediates.clear()
}
if (intermediates.size == 0) {
intermediates.add(source[0].createEquivalent(type = ColorType.FLOAT16))
intermediates.add(source[0].createEquivalent(type = ColorType.FLOAT16))
}
pass.radius = 1.0 + pow(exp, 0.0) * radius
pass.linearInput = linearInput
pass.linearOutput = true
pass.apply(source[0], intermediates[0])
for (i in 0 until passes - 1) {
pass.linearInput = true
pass.linearOutput = true
pass.radius = 1.0 + pow(exp, i + 1.0) * radius //(1.0 + simplex(0, phase + i)) / 2.0
pass.apply(intermediates[i % 2], intermediates[(i + 1) % 2])
}
pass.radius = 1.0 + pow(exp, (passes) * 1.0) * radius
pass.linearInput = true
pass.linearOutput = linearOutput
pass.apply(intermediates[(passes + 1) % 2], target[0])
}
}
private fun pow(a: Double, x: Double): Double {
return a.pow(x)
}

View File

@@ -0,0 +1,165 @@
package org.openrndr.extra.fx.blur
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.*
import org.openrndr.extra.fx.fx_bloom_combine
import org.openrndr.extra.fx.fx_bloom_downscale
import org.openrndr.extra.fx.fx_bloom_upscale
import org.openrndr.extra.fx.mppFilterShader
import org.openrndr.extra.parameters.BooleanParameter
import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter
import org.openrndr.extra.parameters.IntParameter
import org.openrndr.filter.color.delinearize
import org.openrndr.filter.color.linearize
class BloomDownscale : Filter(mppFilterShader(fx_bloom_downscale,"bloom-downscale"))
class BloomUpscale : Filter(mppFilterShader(fx_bloom_upscale, "bloom-upscale")) {
var gain: Double by parameters
var shape: Double by parameters
var noiseSeed: Double by parameters
var noiseGain: Double by parameters
init {
gain = 1.0
shape = 1.0
noiseSeed = 1.0
noiseGain = 0.25
}
}
class BloomCombine : Filter(mppFilterShader(fx_bloom_combine, "bloom-combine")) {
var gain: Double by parameters
var bias: ColorRGBa by parameters
init {
bias = ColorRGBa.BLACK
gain = 1.0
}
}
@Description("MipBloom")
open class MipBloom<T : Filter>(val blur: T) : Filter(mppFilterShader(fx_bloom_combine, "bloom-combine")) {
var passes = 6
@DoubleParameter("shape", 0.0, 4.0)
var shape: Double = 1.0
@DoubleParameter("gain", 0.0, 4.0)
var gain: Double = 1.0
/**
* noise gain. low noise gains will result in visible banding of the image. default value is 0.25
*/
@DoubleParameter("noise gain", 0.0, 1.0)
var noiseGain: Double = 0.25
@DoubleParameter("noise seed", 0.0, 1000.0)
var noiseSeed: Double = 0.0
@BooleanParameter("sRGB")
var sRGB = true
var intermediates = mutableListOf<ColorBuffer>()
var sourceCopy: ColorBuffer? = null
val upscale = BloomUpscale()
val downScale = BloomDownscale()
val combine = BloomCombine()
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
sourceCopy?.let {
if (!it.isEquivalentTo(source[0], ignoreType = true)) {
it.destroy()
sourceCopy = null
}
}
if (sourceCopy == null) {
sourceCopy = source[0].createEquivalent(type = ColorType.FLOAT16)
}
source[0].copyTo(sourceCopy!!)
upscale.shape = shape
if (intermediates.size != passes
|| (intermediates.isNotEmpty() && (!intermediates[0].isEquivalentTo(target[0], ignoreType = true, ignoreFormat = true)))) {
intermediates.forEach {
it.destroy()
}
intermediates.clear()
for (pass in 0 until passes) {
val tdiv = 1 shl (pass + 1)
val cb = colorBuffer(target[0].width / tdiv, target[0].height / tdiv, type = ColorType.FLOAT16)
intermediates.add(cb)
}
}
if (sRGB) {
linearize.apply(sourceCopy!!, sourceCopy!!)
}
upscale.noiseGain = noiseGain
upscale.noiseSeed = noiseSeed
downScale.apply(sourceCopy!!, intermediates[0])
blur.apply(intermediates[0], intermediates[0])
for (pass in 1 until passes) {
downScale.apply(intermediates[pass - 1], intermediates[pass])
blur.apply(intermediates[pass], intermediates[pass])
}
upscale.apply(intermediates.toTypedArray(), arrayOf(target[0]))
combine.gain = gain
combine.apply(arrayOf(sourceCopy!!, target[0]), target)
if (sRGB) {
delinearize.apply(target[0], target[0])
}
}
}
@Description("Hash bloom")
class HashBloom : MipBloom<HashBlur>(blur = HashBlur()) {
/**
* Blur radius in pixels, default is 5.0
*/
@DoubleParameter("blur radius", 1.0, 25.0)
var radius: Double = 5.0
/**
* Number of samples, default is 30
*/
@IntParameter("number of samples", 1, 100)
var samples: Int = 30
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
blur.radius = radius
blur.samples = samples
super.apply(source, target)
}
}
@Description("Gaussian bloom")
class GaussianBloom : MipBloom<GaussianBlur>(blur = GaussianBlur()) {
/**
* blur sample window, default value is 5
*/
@IntParameter("window size", 1, 25)
var window: Int = 5
/**
* blur sigma, default value is 1.0
*/
@DoubleParameter("kernel sigma", 0.0, 25.0)
var sigma: Double = 1.0
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
blur.window = window
blur.sigma = sigma
super.apply(source, target)
}
}

View File

@@ -0,0 +1,44 @@
package org.openrndr.extra.fx.blur
import org.openrndr.draw.*
import org.openrndr.extra.fx.fx_zoom_blur
import org.openrndr.extra.fx.mppFilterShader
import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter
import org.openrndr.math.Vector2
@Description("Zoom Blur")
class ZoomBlur : Filter(mppFilterShader(fx_zoom_blur, "zoom-blur")) {
var center: Vector2 by parameters
@DoubleParameter("strength", 0.0, 1.0)
var strength: Double by parameters
init {
center = Vector2.ONE / 2.0
strength = 0.2
}
private var intermediate: ColorBuffer? = null
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
intermediate?.let {
if (it.width != target[0].width || it.height != target[0].height) {
intermediate = null
}
}
if (intermediate == null) {
intermediate =
colorBuffer(target[0].width, target[0].height, target[0].contentScale, target[0].format, target[0].type)
}
intermediate?.let {
parameters["dimensions"] = Vector2(it.effectiveWidth.toDouble(), it.effectiveHeight.toDouble())
super.apply(source, arrayOf(it))
it.copyTo(target[0])
}
}
}