diff --git a/orx-fx/src/main/kotlin/blend/BlendFilters.kt b/orx-fx/src/main/kotlin/blend/BlendFilters.kt index e0f09536..d4071f55 100644 --- a/orx-fx/src/main/kotlin/blend/BlendFilters.kt +++ b/orx-fx/src/main/kotlin/blend/BlendFilters.kt @@ -3,16 +3,89 @@ package org.openrndr.extra.fx.blend import org.openrndr.draw.Filter import org.openrndr.draw.Shader import org.openrndr.extra.fx.filterFragmentCode +import org.openrndr.extra.parameters.BooleanParameter + +class ColorBurn : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/color-burn.frag"))) { + @BooleanParameter("source clip") + var clip: Boolean by parameters + + init { + clip = false + } +} + +class ColorDodge : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/color-dodge.frag"))) { + @BooleanParameter("source clip") + var clip: Boolean by parameters + + init { + clip = false + } +} + +class Darken : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/darken.frag"))) { + @BooleanParameter("source clip") + var clip: Boolean by parameters + + init { + clip = false + } +} + +class HardLight : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/hard-light.frag"))) { + @BooleanParameter("source clip") + var clip: Boolean by parameters + + init { + clip = false + } +} + +class Lighten : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/lighten.frag"))) { + @BooleanParameter("source clip") + var clip: Boolean by parameters + + init { + clip = false + } +} + +class Multiply : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/multiply.frag"))) { + @BooleanParameter("source clip") + var clip: Boolean by parameters + + init { + clip = false + } +} + +class Normal : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/normal.frag"))) { + @BooleanParameter("source clip") + var clip: Boolean by parameters + + init { + clip = false + } +} + +class Overlay : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/overlay.frag"))) { + @BooleanParameter("source clip") + var clip: Boolean by parameters + + init { + clip = false + } +} + +class Screen : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/screen.frag"))) { + @BooleanParameter("source clip") + var clip: Boolean by parameters + + init { + clip = false + } +} -class ColorBurn : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/color-burn.frag"))) -class ColorDodge : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/color-dodge.frag"))) -class Darken : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/darken.frag"))) -class HardLight : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/hard-light.frag"))) -class Lighten : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/lighten.frag"))) -class Multiply : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/multiply.frag"))) -class Normal : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/normal.frag"))) -class Overlay : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/overlay.frag"))) -class Screen : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/screen.frag"))) class SourceIn : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/source-in.frag"))) class SourceOut : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/source-out.frag"))) @@ -23,5 +96,19 @@ class Xor : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragment class MultiplyContrast : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/multiply-contrast.frag"))) class Passthrough : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/passthrough.frag"))) -class Add : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/add.frag"))) -class Subtract : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/subtract.frag"))) +class Add : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/add.frag"))) { + @BooleanParameter("source clip") + var clip: Boolean by parameters + + init { + clip = false + } +} +class Subtract : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/subtract.frag"))) { + @BooleanParameter("source clip") + var clip: Boolean by parameters + + init { + clip = false + } +} diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/add.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/add.frag index e7b50217..a408eda7 100644 --- a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/add.frag +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/add.frag @@ -3,12 +3,21 @@ in vec2 v_texCoord0; uniform sampler2D tex0; uniform sampler2D tex1; - +uniform bool clip; out vec4 o_color; + + void main() { vec4 a = texture(tex0, v_texCoord0); vec4 b = texture(tex1, v_texCoord0); vec3 na = a.a > 0 ? a.rgb/a.a : vec3(0.0); + vec3 nb = b.a > 0 ? b.rgb/b.a : vec3(0.0); + vec3 addColor = b.rgb; //mix(vec3(0.0), nb, b.a); - o_color = vec4((na + addColor), 1) * a.a; + + if (clip) { + o_color = vec4((na + addColor), 1) * a.a; + } else { + o_color = (1.0-a.a) * b + a.a * b.a * vec4(min(na + nb, vec3(1.0)), 1.0) + (1.0-b.a) * a; + } } \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/color-burn.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/color-burn.frag index 506b18ae..7223d94c 100644 --- a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/color-burn.frag +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/color-burn.frag @@ -3,11 +3,13 @@ in vec2 v_texCoord0; uniform sampler2D tex0; uniform sampler2D tex1; +uniform bool clip; float blendColorBurn(float base, float blend) { return (blend==0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0); } + out vec4 o_color; void main() { vec4 a = texture(tex0, v_texCoord0); @@ -22,5 +24,9 @@ void main() { blendColorBurn(na.b, nb.b) ); - o_color = vec4(na * (1.0 - b.a) + b.a * m, 1.0) * a.a; + if (clip) { + o_color = vec4(na * (1.0 - b.a) + b.a * m, 1.0) * a.a; + } else { + o_color = (1.0-a.a) * b + a.a * b.a * vec4(m, 1.0) + (1.0-b.a) * a; + } } \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/color-dodge.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/color-dodge.frag index 17c9edf0..45f43dba 100644 --- a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/color-dodge.frag +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/color-dodge.frag @@ -3,6 +3,7 @@ in vec2 v_texCoord0; uniform sampler2D tex0; uniform sampler2D tex1; +uniform bool clip; float dodge(float base, float blend) { return (blend==1.0)?blend:min(base/(1.0-blend),1.0); @@ -22,5 +23,9 @@ void main() { dodge(na.b, nb.b) ); - o_color = vec4(na * (1.0 - b.a) + b.a * m, 1.0) * a.a; + if (clip) { + o_color = vec4(na * (1.0 - b.a) + b.a * m, 1.0) * a.a; + } else { + o_color = (1.0-a.a) * b + a.a * b.a * vec4(m, 1.0) + (1.0-b.a) * a; + } } \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/darken.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/darken.frag index 39e0d942..5e756edd 100644 --- a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/darken.frag +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/darken.frag @@ -3,6 +3,7 @@ in vec2 v_texCoord0; uniform sampler2D tex0; uniform sampler2D tex1; +uniform bool clip; out vec4 o_color; void main() { @@ -17,5 +18,9 @@ void main() { nb.g <= na.g? nb.g : na.g, nb.b <= na.b? nb.b : na.b); - o_color = vec4(na * (1.0 - b.a) + b.a * m, 1.0) * a.a; + if (clip) { + o_color = vec4(na * (1.0 - b.a) + b.a * m, 1.0) * a.a; + } else { + o_color = (1.0-a.a) * b + a.a * b.a * vec4(m, 1.0) + (1.0-b.a) * a; + } } \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/hard-light.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/hard-light.frag index ad05e06d..bc5fdb65 100644 --- a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/hard-light.frag +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/hard-light.frag @@ -3,7 +3,7 @@ in vec2 v_texCoord0; uniform sampler2D tex0; uniform sampler2D tex1; - +uniform bool clip; out vec4 o_color; void main() { vec4 a = texture(tex0, v_texCoord0); @@ -17,6 +17,10 @@ void main() { nb.g <= 0.5? 2*na.g * nb.g : 1.0 - 2.0*(1.0 - na.g)*(1.0 - nb.g), nb.b <= 0.5? 2*na.b * nb.b : 1.0 - 2.0*(1.0 - na.b)*(1.0 - nb.b) ); - o_color = vec4(na * (1.0 - b.a) + b.a * m, 1.0) * a.a; + if (clip) { + o_color = vec4(na * (1.0 - b.a) + b.a * m, 1.0) * a.a; + } else { + o_color = (1.0-a.a) * b + a.a * b.a * vec4(m, 1.0) + (1.0-b.a) * a; + } } \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/lighten.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/lighten.frag index e5f91610..fe29a7f3 100644 --- a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/lighten.frag +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/lighten.frag @@ -3,6 +3,7 @@ in vec2 v_texCoord0; uniform sampler2D tex0; uniform sampler2D tex1; +uniform bool clip; out vec4 o_color; void main() { @@ -17,5 +18,9 @@ void main() { nb.g >= na.g? nb.g : na.g, nb.b >= na.b? nb.b : na.b); - o_color = vec4(na * (1.0 - b.a) + b.a * m, 1.0) * a.a; + if (clip) { + o_color = vec4(na * (1.0 - b.a) + b.a * m, 1.0) * a.a; + } else { + o_color = (1.0-a.a) * b + a.a * b.a * vec4(m, 1.0) + (1.0-b.a) * a; + } } \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/multiply.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/multiply.frag index d4c3e43e..d161a3cb 100644 --- a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/multiply.frag +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/multiply.frag @@ -4,12 +4,25 @@ in vec2 v_texCoord0; uniform sampler2D tex0; uniform sampler2D tex1; +uniform bool clip; + out vec4 o_color; + +vec3 u(vec4 x) { + return x.a == 0.0? vec3(0.0) : x.rgb / x.a; +} + void main() { vec4 a = texture(tex0, v_texCoord0); vec4 b = texture(tex1, v_texCoord0); - vec3 nb = b.a > 0 ? b.rgb/b.a : vec3(0.0); + vec3 na = u(a); + vec3 nb = u(b); vec3 mulColor = mix(vec3(1.0), nb, b.a); - o_color = vec4(a.rgb * mulColor, a.a); + + if (clip) { + o_color = vec4(a.rgb * mulColor, a.a); + } else { + o_color = (1.0-a.a) * b + a.a * b.a * vec4(na * nb, 1.0) + (1.0-b.a) * a; + } } diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/normal.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/normal.frag index 5a7403a4..869ef901 100644 --- a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/normal.frag +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/normal.frag @@ -3,6 +3,7 @@ in vec2 v_texCoord0; uniform sampler2D tex0; uniform sampler2D tex1; +uniform bool clip; out vec4 o_color; void main() { @@ -10,6 +11,10 @@ void main() { vec4 b = texture(tex1, v_texCoord0); float alpha = min(1,max(0, b.a)); - o_color = a * (1.0-alpha) + b; - o_color.a = clamp(o_color.a, 0.0, 1.0); + if (!clip) { + o_color = a * (1.0-alpha) + b; + o_color.a = clamp(o_color.a, 0.0, 1.0); + } else { + o_color = a * (1.0-alpha) + b * a.a; + } } \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/overlay.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/overlay.frag index 9690ce2d..27cac3c5 100644 --- a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/overlay.frag +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/overlay.frag @@ -4,6 +4,7 @@ in vec2 v_texCoord0; uniform sampler2D tex0; uniform sampler2D tex1; +uniform bool clip; out vec4 o_color; @@ -22,13 +23,16 @@ void main() { vec3 na = demul(a); vec3 nb = demul(b); - vec4 c = vec4( + vec3 m = vec3( na.r <= 0.5? 2.0 * na.r * nb.r : (1.0 - 2.0 * (1.0 - na.r) * (1.0 - nb.r)), na.g <= 0.5? 2.0 * na.g * nb.g : (1.0 - 2.0 * (1.0 - na.g) * (1.0 - nb.g)), - na.b <= 0.5? 2.0 * na.b * nb.b : (1.0 - 2.0 * (1.0 - na.b) * (1.0 - nb.b)), - 1.0 + na.b <= 0.5? 2.0 * na.b * nb.b : (1.0 - 2.0 * (1.0 - na.b) * (1.0 - nb.b)) ); - vec3 fc = na * (1.0 - b.a) + c.rgb * b.a; - o_color = vec4(fc, 1.0) * a.a; + if (clip) { + vec3 fc = na * (1.0 - b.a) + m * b.a; + o_color = vec4(fc, 1.0) * a.a; + } else { + o_color = (1.0-a.a) * b + a.a * b.a * vec4(m, 1.0) + (1.0-b.a) * a; + } } \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/screen.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/screen.frag index ecb3c187..0480c015 100644 --- a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/screen.frag +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/screen.frag @@ -3,6 +3,7 @@ in vec2 v_texCoord0; uniform sampler2D tex0; uniform sampler2D tex1; +uniform bool clip; out vec4 o_color; void main() { @@ -17,5 +18,9 @@ void main() { 1.0-((1.0-na.g)*(1.0-nb.g)), 1.0-((1.0-na.b)*(1.0-nb.b))); - o_color = vec4(na * (1.0 - b.a) + b.a * m, 1.0) * a.a; + if (clip) { + o_color = vec4(na * (1.0 - b.a) + b.a * m, 1.0) * a.a; + } else { + o_color = (1.0-a.a) * b + a.a * b.a * vec4(m, 1.0) + (1.0-b.a) * a; + } } \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/subtract.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/subtract.frag index f19a5c69..2c9c3ce6 100644 --- a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/subtract.frag +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/subtract.frag @@ -3,12 +3,18 @@ in vec2 v_texCoord0; uniform sampler2D tex0; uniform sampler2D tex1; +uniform bool clip; out vec4 o_color; void main() { vec4 a = texture(tex0, v_texCoord0); vec4 b = texture(tex1, v_texCoord0); vec3 na = a.a > 0 ? a.rgb/a.a : vec3(0.0); + vec3 nb = b.a > 0 ? b.rgb/b.a : vec3(0.0); vec3 subColor = b.rgb; - o_color = vec4(max(na - subColor, vec3(0.0)), 1) * a.a; + if (clip) { + o_color = vec4(max(na - subColor, vec3(0.0)), 1) * a.a; + } else { + o_color = (1.0-a.a) * b + a.a * b.a * vec4(max(na - nb, vec3(0.0)), 1.0) + (1.0-b.a) * a; + } } \ No newline at end of file