Add Filter interfaces for PoissonBlend and PoissonFill
This commit is contained in:
@@ -3,6 +3,8 @@ package org.openrndr.poissonfill
|
|||||||
import org.openrndr.draw.*
|
import org.openrndr.draw.*
|
||||||
import org.openrndr.extra.fx.blend.Passthrough
|
import org.openrndr.extra.fx.blend.Passthrough
|
||||||
import org.openrndr.extra.fx.blend.Subtract
|
import org.openrndr.extra.fx.blend.Subtract
|
||||||
|
import org.openrndr.filter.color.delinearize
|
||||||
|
import org.openrndr.filter.color.linearize
|
||||||
import org.openrndr.resourceUrl
|
import org.openrndr.resourceUrl
|
||||||
|
|
||||||
internal class BlendBoundary : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/poisson/blend-boundary.frag")))
|
internal class BlendBoundary : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/poisson/blend-boundary.frag")))
|
||||||
@@ -23,7 +25,7 @@ internal class Clamp : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/pois
|
|||||||
private val passthrough by lazy { Passthrough() }
|
private val passthrough by lazy { Passthrough() }
|
||||||
private val subtract by lazy { Subtract() }
|
private val subtract by lazy { Subtract() }
|
||||||
|
|
||||||
class PoissonBlender(width: Int, height: Int, type: ColorType = ColorType.FLOAT32) {
|
class PoissonBlender(val width: Int, val height: Int, type: ColorType = ColorType.FLOAT32) {
|
||||||
private val pyramid = ConvolutionPyramid(width, height, 0, type = type)
|
private val pyramid = ConvolutionPyramid(width, height, 0, type = type)
|
||||||
private val preprocess = colorBuffer(width, height, type = type)
|
private val preprocess = colorBuffer(width, height, type = type)
|
||||||
private val combined = colorBuffer(width, height, type = type)
|
private val combined = colorBuffer(width, height, type = type)
|
||||||
@@ -37,7 +39,6 @@ class PoissonBlender(width: Int, height: Int, type: ColorType = ColorType.FLOAT3
|
|||||||
private val h2 = 0.0269546f
|
private val h2 = 0.0269546f
|
||||||
private val g = floatArrayOf(0.0311849f, 0.7752854f, 0.0311849f)
|
private val g = floatArrayOf(0.0311849f, 0.7752854f, 0.0311849f)
|
||||||
|
|
||||||
private val clamp = Clamp()
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
pyramid.h1 = h1
|
pyramid.h1 = h1
|
||||||
@@ -48,12 +49,69 @@ class PoissonBlender(width: Int, height: Int, type: ColorType = ColorType.FLOAT3
|
|||||||
fun process(target: ColorBuffer, source: ColorBuffer, mask: ColorBuffer,
|
fun process(target: ColorBuffer, source: ColorBuffer, mask: ColorBuffer,
|
||||||
softMask: ColorBuffer = mask, softMaskGain: Double = 1.0): ColorBuffer {
|
softMask: ColorBuffer = mask, softMaskGain: Double = 1.0): ColorBuffer {
|
||||||
subtract.apply(arrayOf(target, source), difference)
|
subtract.apply(arrayOf(target, source), difference)
|
||||||
clamp.minValue = -0.50
|
|
||||||
clamp.maxValue = 0.50
|
|
||||||
fillBoundary.apply(arrayOf(difference, mask), preprocess)
|
fillBoundary.apply(arrayOf(difference, mask), preprocess)
|
||||||
val result = pyramid.process(preprocess)
|
val result = pyramid.process(preprocess)
|
||||||
fillCombine.softMaskGain = softMaskGain
|
fillCombine.softMaskGain = softMaskGain
|
||||||
fillCombine.apply(arrayOf(result, target, source, mask, softMask), arrayOf(combined))
|
fillCombine.apply(arrayOf(result, target, source, mask, softMask), arrayOf(combined))
|
||||||
return combined
|
return combined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun destroy() {
|
||||||
|
pyramid.destroy()
|
||||||
|
preprocess.destroy()
|
||||||
|
combined.destroy()
|
||||||
|
difference.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class PoissonBlend: Filter() {
|
||||||
|
private var blender: PoissonBlender? = null
|
||||||
|
|
||||||
|
val alphaToBitmap = AlphaToBitmap()
|
||||||
|
var mask: ColorBuffer? = null
|
||||||
|
|
||||||
|
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
|
||||||
|
if (target.isNotEmpty()) {
|
||||||
|
|
||||||
|
mask?.let {
|
||||||
|
if (it.width != target[0].width || it.height != target[0].height) {
|
||||||
|
it.destroy()
|
||||||
|
mask = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask == null) {
|
||||||
|
mask = colorBuffer(target[0].width, target[0].height)
|
||||||
|
}
|
||||||
|
|
||||||
|
blender?.let {
|
||||||
|
if (it.width != target[0].width || it.height != target[0].height) {
|
||||||
|
it.destroy()
|
||||||
|
blender = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blender == null) {
|
||||||
|
blender = PoissonBlender(target[0].width, target[0].height)
|
||||||
|
}
|
||||||
|
|
||||||
|
mask?.let {
|
||||||
|
alphaToBitmap.apply(source[1], it)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
blender?.let {
|
||||||
|
|
||||||
|
linearize.apply(source[0], source[0])
|
||||||
|
linearize.apply(source[1], source[1])
|
||||||
|
|
||||||
|
val result = it.process(source[0], source[1], mask ?: error("no mask"))
|
||||||
|
result.copyTo(target[0])
|
||||||
|
|
||||||
|
delinearize.apply(target[0], target[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -33,11 +33,12 @@ class PoissonFiller(val width: Int, val height: Int, type: ColorType = ColorType
|
|||||||
fun destroy() {
|
fun destroy() {
|
||||||
preproc.destroy()
|
preproc.destroy()
|
||||||
combined.destroy()
|
combined.destroy()
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Poison filling as a filter
|
||||||
|
*/
|
||||||
class PoissonFill : Filter() {
|
class PoissonFill : Filter() {
|
||||||
private var filler: PoissonFiller? = null
|
private var filler: PoissonFiller? = null
|
||||||
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
|
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ out vec4 o_output;
|
|||||||
|
|
||||||
void main(){
|
void main(){
|
||||||
vec4 c = texture(tex0, v_texCoord0);
|
vec4 c = texture(tex0, v_texCoord0);
|
||||||
o_output.rgb = vec3(step(1.0, c.a));
|
o_output.rgb = vec3(step(0.01, c.a));
|
||||||
o_output.a = 1.0;
|
o_output.a = 1.0;
|
||||||
}
|
}
|
||||||
@@ -41,5 +41,6 @@ void main(){
|
|||||||
|
|
||||||
o_output.rgb = mix(targetColor.rgb, blend, mask*max(0.0,min(1.0, softMask * softMaskGain)));
|
o_output.rgb = mix(targetColor.rgb, blend, mask*max(0.0,min(1.0, softMask * softMaskGain)));
|
||||||
o_output.a = 1.0;
|
o_output.a = 1.0;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,9 +12,7 @@ out vec4 o_output;
|
|||||||
/** Composite the initial image and the filled image in the regions where the initial image is black. */
|
/** Composite the initial image and the filled image in the regions where the initial image is black. */
|
||||||
void main(){
|
void main(){
|
||||||
|
|
||||||
vec4 inputColor = textureLod(tex1, v_texCoord0, 0.0).rgba;
|
vec4 inputColor = textureLod(tex1, v_texCoord0, 0.0);
|
||||||
//float mask = float(all(equal(inputColor, vec3(0.0))));
|
|
||||||
//float mask = inputColor.a == 1.0? 0.0 : 1.0;
|
|
||||||
float mask = 1.0 - inputColor.a;
|
float mask = 1.0 - inputColor.a;
|
||||||
|
|
||||||
vec4 fillColor = textureLod(tex0, v_texCoord0, 0.0);
|
vec4 fillColor = textureLod(tex0, v_texCoord0, 0.0);
|
||||||
|
|||||||
Reference in New Issue
Block a user