diff --git a/orx-fx/src/main/kotlin/FilterTools.kt b/orx-fx/src/main/kotlin/FilterTools.kt new file mode 100644 index 00000000..6e33a93d --- /dev/null +++ b/orx-fx/src/main/kotlin/FilterTools.kt @@ -0,0 +1,11 @@ +package org.openrndr.extra.fx + +import org.openrndr.resourceUrl +import java.net.URL + +internal class FilterTools + +internal fun filterFragmentCode(resourceId: String): String { + val urlString = resourceUrl("gl3/$resourceId", FilterTools::class.java) + return URL(urlString).readText() +} \ No newline at end of file diff --git a/orx-fx/src/main/kotlin/antialias/FXAA.kt b/orx-fx/src/main/kotlin/antialias/FXAA.kt new file mode 100644 index 00000000..07d81482 --- /dev/null +++ b/orx-fx/src/main/kotlin/antialias/FXAA.kt @@ -0,0 +1,37 @@ +package org.openrndr.extra.fx.antialias + +import org.openrndr.draw.Filter +import org.openrndr.draw.Shader +import org.openrndr.extra.fx.filterFragmentCode + +/** + * FXAA approximate antialiasing filter. Only works on LDR inputs + */ +class FXAA : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("antialias/fxaa.frag"))) { + /** + * luma threshold, default value is 0.5 + */ + var lumaThreshold: Double by parameters + + /** + * max search span, default value is 8.0 + */ + var maxSpan: Double by parameters + + /** + * direction reduce multiplier, default value is 0.0 + */ + var directionReduceMultiplier: Double by parameters + + /** + * direction reduce minimum, default value is 0.0 + */ + var directionReduceMinimum: Double by parameters + + init { + lumaThreshold = 0.5 + maxSpan = 8.0 + directionReduceMinimum = 0.0 + directionReduceMultiplier = 0.0 + } +} \ No newline at end of file diff --git a/orx-fx/src/main/kotlin/blend/BlendFilters.kt b/orx-fx/src/main/kotlin/blend/BlendFilters.kt new file mode 100644 index 00000000..e0f09536 --- /dev/null +++ b/orx-fx/src/main/kotlin/blend/BlendFilters.kt @@ -0,0 +1,27 @@ +package org.openrndr.extra.fx.blend + +import org.openrndr.draw.Filter +import org.openrndr.draw.Shader +import org.openrndr.extra.fx.filterFragmentCode + +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"))) +class DestinationIn : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/destination-in.frag"))) +class DestinationOut : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/destination-out.frag"))) +class Xor : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("blend/xor.frag"))) + +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"))) diff --git a/orx-fx/src/main/kotlin/blur/ApproximateGaussianBlur.kt b/orx-fx/src/main/kotlin/blur/ApproximateGaussianBlur.kt new file mode 100644 index 00000000..8631dc6d --- /dev/null +++ b/orx-fx/src/main/kotlin/blur/ApproximateGaussianBlur.kt @@ -0,0 +1,66 @@ +package org.openrndr.extra.fx.blur + +import org.openrndr.draw.ColorBuffer +import org.openrndr.draw.Filter +import org.openrndr.draw.Shader +import org.openrndr.draw.colorBuffer +import org.openrndr.extra.fx.filterFragmentCode + +import org.openrndr.math.Vector2 + +/** + * Approximate separated Gaussian blur + */ +class ApproximateGaussianBlur : Filter(Shader.createFromCode(Filter.filterVertexCode, + filterFragmentCode("blur/approximate-gaussian-blur.frag"))) { + + /** + * blur sample window, default value is 5 + */ + var window: Int by parameters + + /** + * spread multiplier, default value is 1.0 + */ + var spread: Double by parameters + + /** + * blur sigma, default value is 1.0 + */ + var sigma: Double by parameters + + /** + * post blur gain, default value is 1.0 + */ + var gain: Double by parameters + + + private var intermediate: ColorBuffer? = null + + init { + window = 5 + spread = 1.0 + gain = 1.0 + sigma = 1.0 + } + + override fun apply(source: Array, target: Array) { + 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["blurDirection"] = Vector2(1.0, 0.0) + super.apply(source, arrayOf(it)) + + parameters["blurDirection"] = Vector2(0.0, 1.0) + super.apply(arrayOf(it), target) + } + } +} \ No newline at end of file diff --git a/orx-fx/src/main/kotlin/blur/BoxBlur.kt b/orx-fx/src/main/kotlin/blur/BoxBlur.kt new file mode 100644 index 00000000..74c1bf6e --- /dev/null +++ b/orx-fx/src/main/kotlin/blur/BoxBlur.kt @@ -0,0 +1,59 @@ +package org.openrndr.extra.fx.blur + +import org.openrndr.draw.ColorBuffer +import org.openrndr.draw.Filter +import org.openrndr.draw.Shader +import org.openrndr.draw.colorBuffer +import org.openrndr.extra.fx.filterFragmentCode + +import org.openrndr.math.Vector2 + +/** + * BoxBlur implemented as a separable filter + */ +class BoxBlur : Filter(Shader.createFromCode(Filter.filterVertexCode, + filterFragmentCode("blur/box-blur.frag"))) { + + /** + * The sample window, default is 5 + */ + var window: Int by parameters + + /** + * Spread multiplier, default is 1.0 + */ + var spread: Double by parameters + + /** + * Post-blur gain, default is 1.0 + */ + var gain: Double by parameters + + private var intermediate: ColorBuffer? = null + + init { + window = 5 + spread = 1.0 + gain = 1.0 + } + + override fun apply(source: Array, target: Array) { + 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["blurDirection"] = Vector2(1.0, 0.0) + super.apply(source, arrayOf(it)) + + parameters["blurDirection"] = Vector2(0.0, 1.0) + super.apply(arrayOf(it), target) + } + } +} \ No newline at end of file diff --git a/orx-fx/src/main/kotlin/blur/GaussianBlur.kt b/orx-fx/src/main/kotlin/blur/GaussianBlur.kt new file mode 100644 index 00000000..78ab7e8b --- /dev/null +++ b/orx-fx/src/main/kotlin/blur/GaussianBlur.kt @@ -0,0 +1,39 @@ +package org.openrndr.extra.fx.blur + +import org.openrndr.draw.Filter +import org.openrndr.draw.Shader +import org.openrndr.extra.fx.filterFragmentCode + +/** + * Exact Gaussian blur, implemented as a single pass filter + */ +class GaussianBlur : Filter(Shader.createFromCode(Filter.filterVertexCode, + filterFragmentCode("blur/gaussian-blur.frag"))) { + + /** + * The sample window, default value is 5 + */ + var window: Int by parameters + + /** + * Spread multiplier, default value is 1.0 + */ + var spread: Double by parameters + + /** + * Blur kernel sigma, default value is 1.0 + */ + var sigma: Double by parameters + + /** + * Post-blur gain, default value is 1.0 + */ + var gain: Double by parameters + + init { + window = 5 + spread = 1.0 + sigma = 1.0 + gain = 1.0 + } +} \ No newline at end of file diff --git a/orx-fx/src/main/kotlin/blur/HashBlur.kt b/orx-fx/src/main/kotlin/blur/HashBlur.kt new file mode 100644 index 00000000..7aa48d1d --- /dev/null +++ b/orx-fx/src/main/kotlin/blur/HashBlur.kt @@ -0,0 +1,35 @@ +package org.openrndr.extra.fx.blur + +import org.openrndr.draw.Filter +import org.openrndr.draw.Shader +import org.openrndr.extra.fx.filterFragmentCode + +class HashBlur : Filter(Shader.createFromCode(Filter.filterVertexCode, + filterFragmentCode("blur/hash-blur.frag"))) { + /** + * Blur radius in pixels, default is 5.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 + */ + var samples: Int by parameters + + /** + * Post-blur gain, default is 1.0 + */ + var gain: Double by parameters + + init { + radius = 5.0 + time = 0.0 + samples = 30 + gain = 1.0 + } +} \ No newline at end of file diff --git a/orx-fx/src/main/kotlin/color/ColorLookup.kt b/orx-fx/src/main/kotlin/color/ColorLookup.kt new file mode 100644 index 00000000..3274d82e --- /dev/null +++ b/orx-fx/src/main/kotlin/color/ColorLookup.kt @@ -0,0 +1,30 @@ +package org.openrndr.extra.fx.color + +import org.openrndr.draw.* +import org.openrndr.extra.fx.filterFragmentCode + +class ColorLookup(lookup: ColorBuffer) : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("color/color-lookup.frag"))) { + /** a color look-up texture */ + var lookup: ColorBuffer by parameters + + /** + * noise gain in look-up, default value is 0.0 + */ + var noiseGain: Double by parameters + + /** + * noise seed, default value is 0.0 + */ + var seed: Double by parameters + + init { + this.lookup = lookup + this.noiseGain = 0.0 + this.seed = 0.0 + } + + override fun apply(source: Array, target: Array) { + lookup.filter(MinifyingFilter.LINEAR, MagnifyingFilter.LINEAR) + super.apply(source, target) + } +} \ No newline at end of file diff --git a/orx-fx/src/main/kotlin/color/ColorMix.kt b/orx-fx/src/main/kotlin/color/ColorMix.kt new file mode 100644 index 00000000..2e2cf451 --- /dev/null +++ b/orx-fx/src/main/kotlin/color/ColorMix.kt @@ -0,0 +1,9 @@ +package org.openrndr.extra.fx.color + +import org.openrndr.draw.Filter +import org.openrndr.draw.Shader +import org.openrndr.extra.fx.filterFragmentCode + +class ColorMix : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("color/color-mix.frag"))) { + +} \ No newline at end of file diff --git a/orx-fx/src/main/kotlin/color/SubtractConstant.kt b/orx-fx/src/main/kotlin/color/SubtractConstant.kt new file mode 100644 index 00000000..7650592e --- /dev/null +++ b/orx-fx/src/main/kotlin/color/SubtractConstant.kt @@ -0,0 +1,14 @@ +package org.openrndr.extra.fx.color + +import org.openrndr.color.ColorRGBa +import org.openrndr.draw.Filter +import org.openrndr.draw.Shader +import org.openrndr.extra.fx.filterFragmentCode + +class SubtractConstant : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("color/subtract-constant.frag"))) { + var constant: ColorRGBa by parameters + + init { + constant = ColorRGBa(1.0, 1.0, 1.0, 0.0) + } +} diff --git a/orx-fx/src/main/kotlin/dither/ADither.kt b/orx-fx/src/main/kotlin/dither/ADither.kt new file mode 100644 index 00000000..4a211104 --- /dev/null +++ b/orx-fx/src/main/kotlin/dither/ADither.kt @@ -0,0 +1,25 @@ +package org.openrndr.extra.fx.dither + +import org.openrndr.draw.Filter +import org.openrndr.draw.Shader +import org.openrndr.extra.fx.filterFragmentCode + + +class ADither: Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("dither/a-dither.frag"))) { + var pattern: Int + set(value) { + parameters["pattern"] = value + } + get() = parameters["pattern"] as Int + + var levels: Int + set(value) { + parameters["levels"] = value; + } + get() = parameters["levels"] as Int + + init { + levels = 4 + pattern = 3 + } +} \ No newline at end of file diff --git a/orx-fx/src/main/kotlin/transform/FlipVertically.kt b/orx-fx/src/main/kotlin/transform/FlipVertically.kt new file mode 100644 index 00000000..48d24e41 --- /dev/null +++ b/orx-fx/src/main/kotlin/transform/FlipVertically.kt @@ -0,0 +1,10 @@ +package org.openrndr.extra.fx.transform + +import org.openrndr.draw.Filter +import org.openrndr.draw.Shader +import org.openrndr.extra.fx.filterFragmentCode + +/** + * Vertically flips in the input image + */ +class FlipVertically : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("transform/flip-vertically.frag"))) \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/antialias/fxaa.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/antialias/fxaa.frag new file mode 100644 index 00000000..7b58931f --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/antialias/fxaa.frag @@ -0,0 +1,121 @@ +#version 330 core + + + +//uniform vec2 u_texelStep; + + +uniform float lumaThreshold; +uniform float maxSpan; +uniform float directionReduceMultiplier; +uniform float directionReduceMinimum; + +uniform sampler2D tex0; +in vec2 v_texCoord0; + +out vec4 fragColor; + +// see FXAA +// http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf +// http://iryoku.com/aacourse/downloads/09-FXAA-3.11-in-15-Slides.pdf +// http://horde3d.org/wiki/index.php5?title=Shading_Technique_-_FXAA + +void main(void) +{ + const int u_showEdges = 0; + const int u_fxaaOn = 1; + + + + + vec2 u_texelStep = 1.0 / textureSize(tex0, 0); + vec3 rgbM = min(vec3(1), texture(tex0, v_texCoord0).rgb); + + // Possibility to toggle FXAA on and off. + if (u_fxaaOn == 0) + { + fragColor = vec4(rgbM, 1.0); + + return; + } + + // Sampling neighbour texels. Offsets are adapted to OpenGL texture coordinates. + vec3 rgbNW = min(vec3(1),textureOffset(tex0, v_texCoord0, ivec2(-1, 1)).rgb); + vec3 rgbNE = min(vec3(1),textureOffset(tex0, v_texCoord0, ivec2(1, 1)).rgb); + vec3 rgbSW = min(vec3(1),textureOffset(tex0, v_texCoord0, ivec2(-1, -1)).rgb); + vec3 rgbSE = min(vec3(1),textureOffset(tex0, v_texCoord0, ivec2(1, -1)).rgb); + + // see http://en.wikipedia.org/wiki/Grayscale + const vec3 toLuma = vec3(0.299, 0.587, 0.114); + + // Convert from RGB to luma. + float lumaNW = dot(rgbNW, toLuma); + float lumaNE = dot(rgbNE, toLuma); + float lumaSW = dot(rgbSW, toLuma); + float lumaSE = dot(rgbSE, toLuma); + float lumaM = dot(rgbM, toLuma); + + // Gather minimum and maximum luma. + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + // If contrast is lower than a maximum threshold ... + if (lumaMax - lumaMin < lumaMax * lumaThreshold) + { + // ... do no AA and return. + fragColor = vec4(rgbM, 1.0); + + return; + } + + // Sampling is done along the gradient. + vec2 samplingDirection; + samplingDirection.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + samplingDirection.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + // Sampling step distance depends on the luma: The brighter the sampled texels, the smaller the final sampling step direction. + // This results, that brighter areas are less blurred/more sharper than dark areas. + float samplingDirectionReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * 0.25 * directionReduceMultiplier, directionReduceMinimum); + + // Factor for norming the sampling direction plus adding the brightness influence. + float minSamplingDirectionFactor = 1.0 / (min(abs(samplingDirection.x), abs(samplingDirection.y)) + samplingDirectionReduce); + + // Calculate final sampling direction vector by reducing, clamping to a range and finally adapting to the texture size. + samplingDirection = clamp(samplingDirection * minSamplingDirectionFactor, vec2(-maxSpan, -maxSpan), vec2(maxSpan, maxSpan)) * u_texelStep; + + // Inner samples on the tab. + vec3 rgbSampleNeg = min(vec3(1),texture(tex0, v_texCoord0 + samplingDirection * (1.0/3.0 - 0.5)).rgb); + vec3 rgbSamplePos = min(vec3(1),texture(tex0, v_texCoord0 + samplingDirection * (2.0/3.0 - 0.5)).rgb); + + vec3 rgbTwoTab = (rgbSamplePos + rgbSampleNeg) * 0.5; + + // Outer samples on the tab. + vec3 rgbSampleNegOuter = min(vec3(1),texture(tex0, v_texCoord0 + samplingDirection * (0.0/3.0 - 0.5)).rgb); + vec3 rgbSamplePosOuter = min(vec3(1),texture(tex0, v_texCoord0 + samplingDirection * (3.0/3.0 - 0.5)).rgb); + + vec3 rgbFourTab = (rgbSamplePosOuter + rgbSampleNegOuter) * 0.25 + rgbTwoTab * 0.5; + + // Calculate luma for checking against the minimum and maximum value. + float lumaFourTab = dot(rgbFourTab, toLuma); + + // Are outer samples of the tab beyond the edge ... + if (lumaFourTab < lumaMin || lumaFourTab > lumaMax) + { + // ... yes, so use only two samples. + fragColor = vec4(rgbTwoTab, 1.0); +// fragColor.r = 1.0; + } + else + { + // ... no, so use four samples. + fragColor = vec4(rgbFourTab, 1.0); +// fragColor.g = 1.0; + } + + // Show edges for debug purposes. + if (u_showEdges != 0) + { + fragColor.r = 1.0; + } + //fragColor.rgb = vec3(fragColor.rgb-rgbM)*40.0; +} \ No newline at end of file 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 new file mode 100644 index 00000000..fbafb892 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/add.frag @@ -0,0 +1,29 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +out vec4 o_color; +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + + vec3 na = a.a == 0.0 ? a.rgb: a.rgb / a.a; + vec3 nb = b.a == 0.0 ? b.rgb: b.rgb / b.a; + + float minAlpha = min(a.a, b.a); + float maxAlpha = max(a.a, b.a); + + vec3 ka = mix(vec3(0.0), na.rgb, a.a); + vec3 kb = mix(vec3(0.0), nb.rgb, b.a); + + vec4 m = vec4(ka+kb, 1.0) * maxAlpha; + + vec4 l = a; + l = l * (1.0 - b.a) + b; + l = l * (1.0 - m.a) + m; + o_color = l; + o_color.a = maxAlpha; + +} \ 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 new file mode 100644 index 00000000..e6835d00 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/color-burn.frag @@ -0,0 +1,39 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +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); + vec4 b = texture(tex1, v_texCoord0); + + vec3 na = a.a == 0.0 ? vec3(0.0): a.rgb / a.a; + vec3 nb = b.a == 0.0 ? b.rgb: b.rgb / b.a; + + float minAlpha = min(a.a, b.a); + float maxAlpha = max(a.a, b.a); + + vec3 ka = mix(vec3(0.0), na.rgb, a.a); + vec3 kb = mix(vec3(1.0), nb.rgb, b.a); + + vec4 m = vec4( + blendColorBurn(ka.r, kb.r), + blendColorBurn(ka.g, kb.g), + blendColorBurn(ka.b, kb.b), + + 1.0 + ) * maxAlpha; + + vec4 l = a; + l = l * (1.0 - b.a) + b; + l = l * (1.0 - m.a) + m; + o_color = l; + o_color.a = maxAlpha; +} \ 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 new file mode 100644 index 00000000..492ec947 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/color-dodge.frag @@ -0,0 +1,37 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +float dodge(float base, float blend) { + return (blend==1.0)?blend:min(base/(1.0-blend),1.0); +} + +out vec4 o_color; +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + + vec3 na = a.a == 0.0 ? vec3(0.0): a.rgb / a.a; + vec3 nb = b.a == 0.0 ? vec3(0.0): b.rgb / b.a; + + float minAlpha = min(a.a, b.a); + float maxAlpha = max(a.a, b.a); + + vec3 ka = mix(vec3(0.0), na.rgb, a.a); + vec3 kb = mix(vec3(0.0), nb.rgb, b.a); + + vec4 m = vec4( + dodge(ka.r, kb.r), + dodge(ka.g, kb.g), + dodge(ka.b, kb.b), + 1.0 + ) * maxAlpha; + + vec4 l = a; + l = l * (1.0 - b.a) + b; + l = l * (1.0 - m.a) + m; + o_color = l; + o_color.a = maxAlpha; +} \ 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 new file mode 100644 index 00000000..d9d70cc1 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/darken.frag @@ -0,0 +1,34 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +out vec4 o_color; +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + + vec3 na = a.a == 0.0 ? vec3(0.0): a.rgb / a.a; + vec3 nb = b.a == 0.0 ? vec3(0.0): b.rgb / b.a; + + float minAlpha = min(a.a, b.a); + float maxAlpha = max(a.a, b.a); + + vec3 ka = mix(vec3(0.0), na.rgb, a.a); + vec3 kb = mix(na.rgb, nb.rgb, b.a); + + + vec4 m = vec4( + kb.r <= ka.r? kb.r : ka.r, + kb.g <= ka.g? kb.g : ka.g, + kb.b <= ka.b? kb.b : ka.b, + 1.0 + ) * maxAlpha; + + vec4 l = a; + l = l * (1.0 - b.a) + b; + l = l * (1.0 - m.a) + m; + o_color = l; + o_color.a = maxAlpha; +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/destination-in.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/destination-in.frag new file mode 100644 index 00000000..77f80163 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/destination-in.frag @@ -0,0 +1,15 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +out vec4 o_color; + +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + + o_color.rgb = a.rgb; + o_color.a = b.a; +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/destination-out.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/destination-out.frag new file mode 100644 index 00000000..0284d9d7 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/destination-out.frag @@ -0,0 +1,14 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +out vec4 o_color; +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + + o_color.rgb = a.rgb; + o_color.a = max(a.a - b.a, 0.0); +} \ 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 new file mode 100644 index 00000000..247bafe9 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/hard-light.frag @@ -0,0 +1,33 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +out vec4 o_color; +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + + vec3 na = a.a == 0.0 ? vec3(0.0): a.rgb / a.a; + vec3 nb = b.a == 0.0 ? vec3(0.0): b.rgb / b.a; + + float minAlpha = min(a.a, b.a); + float maxAlpha = max(a.a, b.a); + + vec3 ka = mix(vec3(0.0), na.rgb, a.a); + vec3 kb = mix(vec3(0.5), nb.rgb, b.a); + + vec4 m = vec4( + kb.r <= 0.5? 2*ka.r * kb.r : 1.0 - 2.0*(1.0 - ka.r)*(1.0 - kb.r), + kb.g <= 0.5? 2*ka.g * kb.g : 1.0 - 2.0*(1.0 - ka.g)*(1.0 - kb.g), + kb.b <= 0.5? 2*ka.b * kb.b : 1.0 - 2.0*(1.0 - ka.b)*(1.0 - kb.b), + 1.0 + ) * maxAlpha; + + vec4 l = a; + l = l * (1.0 - b.a) + b; + l = l * (1.0 - m.a) + m; + o_color = l; + o_color.a = maxAlpha; +} \ 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 new file mode 100644 index 00000000..b1cad6cb --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/lighten.frag @@ -0,0 +1,34 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +out vec4 o_color; +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + + vec3 na = a.a == 0.0 ? vec3(0.0): a.rgb / a.a; + vec3 nb = b.a == 0.0 ? vec3(0.0): b.rgb / b.a; + + float minAlpha = min(a.a, b.a); + float maxAlpha = max(a.a, b.a); + + vec3 ka = mix(vec3(0.0), na.rgb, a.a); + vec3 kb = mix(na.rgb, nb.rgb, b.a); + + vec4 m = vec4( + kb.r >= ka.r? kb.r : ka.r, + kb.g >= ka.g? kb.g : ka.g, + kb.b >= ka.b? kb.b : ka.b, + 1.0 + ) * maxAlpha; + + + vec4 l = a; + l = l * (1.0 - b.a) + b; + l = l * (1.0 - m.a) + m; + o_color = l; + o_color.a = maxAlpha; +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/multiply-contrast.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/multiply-contrast.frag new file mode 100644 index 00000000..070b1b19 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/multiply-contrast.frag @@ -0,0 +1,32 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + + + +out vec4 o_color; +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + + + + //float ai = dot(vec3(1.0), a.rgb)/3.0; + //float bi = dot(vec3(1.0), b.rgb)/3.0; + + + float ai = max(a.z, max(a.x, a.y)); + float bi = max(b.z, max(b.x, b.y)); + + //vec3 f = bi < 0.5? vec3(0.0) : a.rgb; + +// vec3 f = smoothstep(0.5, 0.9, bi) * a.rgb; + + vec3 f = a.rgb - (1.0-b.rgb)*2.0*b.a; + + o_color.rgb = max(vec3(0.0), f) * (1.0) + b.rgb * (1.0-a.a);; + + o_color.a = 1.0; //min(1.0, a.a + b.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 new file mode 100644 index 00000000..39f61573 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/multiply.frag @@ -0,0 +1,30 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +out vec4 o_color; +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + + vec3 na = a.a == 0.0 ? a.rgb: a.rgb / a.a; + vec3 nb = b.a == 0.0 ? b.rgb: b.rgb / b.a; + + float minAlpha = min(a.a, b.a); + float maxAlpha = max(a.a, b.a); + + vec3 ka = mix(vec3(1.0), na.rgb, a.a); + vec3 kb = mix(vec3(1.0), nb.rgb, b.a); + + vec4 m = vec4(ka*kb, 1.0) * maxAlpha; + + vec4 l = a; + l = l * (1.0 - b.a) + b; + l = l * (1.0 - m.a) + m; + + o_color = l; + o_color.a = maxAlpha; +} + 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 new file mode 100644 index 00000000..29e075b9 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/normal.frag @@ -0,0 +1,15 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +out vec4 o_color; +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + float alpha = min(1,max(0, b.a)); + + o_color = a * (1.0-alpha) + b; + o_color.a = 1.0; +} \ 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 new file mode 100644 index 00000000..c7cb3e65 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/overlay.frag @@ -0,0 +1,23 @@ + +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +out vec4 o_color; +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + + vec4 c = vec4( + a.r <= 0.5? 2.0*a.r * b.r : 1.0 - 2.0*(1.0-a.r)*(1.0-b.r), + a.g <= 0.5? 2.0*a.g * b.g : 1.0 - 2.0*(1.0-a.g)*(1.0-b.g), + a.b <= 0.5? 2.0*a.b * b.b : 1.0 - 2.0*(1.0-a.b)*(1.0-b.b), + 1.0 + ); + + vec4 d = a * (1.0 - b.a) + c * b.a; + o_color = max(vec4(0), min(vec4(1), d)); + o_color.a = 1.0; +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/passthrough.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/passthrough.frag new file mode 100644 index 00000000..45867b2e --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/passthrough.frag @@ -0,0 +1,9 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; + +out vec4 o_color; +void main() { + o_color = texture(tex0, v_texCoord0); +} \ 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 new file mode 100644 index 00000000..1d3e7976 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/screen.frag @@ -0,0 +1,33 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +out vec4 o_color; +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + + vec3 na = a.a == 0.0 ? vec3(0.0): a.rgb / a.a; + vec3 nb = b.a == 0.0 ? vec3(0.0): b.rgb / b.a; + + float minAlpha = min(a.a, b.a); + float maxAlpha = max(a.a, b.a); + + vec3 ka = mix(vec3(0.0), na.rgb, a.a); + vec3 kb = mix(na.rgb, nb.rgb, b.a); + + vec4 m = vec4( + 1.0-((1.0-ka.r)*(1.0-kb.r)), + 1.0-((1.0-ka.g)*(1.0-kb.g)), + 1.0-((1.0-ka.b)*(1.0-kb.b)), + 1.0 + ) * maxAlpha; + + vec4 l = a; + l = l * (1.0 - b.a) + b; + l = l * (1.0 - m.a) + m; + o_color = l; + o_color.a = maxAlpha; +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/source-in.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/source-in.frag new file mode 100644 index 00000000..a9e92c5f --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/source-in.frag @@ -0,0 +1,14 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +out vec4 o_color; +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + + o_color.rgb = b.rgb; + o_color.a = a.a; +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/source-out.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/source-out.frag new file mode 100644 index 00000000..96a8a077 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/source-out.frag @@ -0,0 +1,14 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +out vec4 o_color; +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + + o_color.rgb = b.rgb; + o_color.a = max(b.a - a.a, 0.0); +} \ 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 new file mode 100644 index 00000000..e9a9ef06 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/subtract.frag @@ -0,0 +1,29 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +out vec4 o_color; +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + + vec3 na = a.a == 0.0 ? a.rgb: a.rgb / a.a; + vec3 nb = b.a == 0.0 ? b.rgb: b.rgb / b.a; + + float minAlpha = min(a.a, b.a); + float maxAlpha = max(a.a, b.a); + + vec3 ka = mix(vec3(0.0), na.rgb, a.a); + vec3 kb = mix(vec3(0.0), nb.rgb, b.a); + + vec4 m = vec4(na-kb, 1.0) * maxAlpha; + + vec4 l = a; + l = l * (1.0 - b.a) + b; + l = l * (1.0 - m.a) + m; + o_color = l; + o_color.a = maxAlpha; + +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/xor.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/xor.frag new file mode 100644 index 00000000..7419da5d --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blend/xor.frag @@ -0,0 +1,22 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D tex1; + +out vec4 o_color; +void main() { + vec4 a = texture(tex0, v_texCoord0); + vec4 b = texture(tex1, v_texCoord0); + vec4 color = vec4(0.0); + + if (a.a > b.a) { + color = a; + } + + if (b.a > a.a) { + color = b; + } + + o_color = color; +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/approximate-gaussian-blur.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/approximate-gaussian-blur.frag new file mode 100644 index 00000000..549f2132 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/approximate-gaussian-blur.frag @@ -0,0 +1,29 @@ +// openrndr - gl3 - approximate-gaussian-blur + +#version 330 core + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform vec2 blurDirection; + +uniform int window; +uniform float sigma; +uniform float spread; +uniform float gain; + +out vec4 o_color; +void main() { + vec2 s = textureSize(tex0, 0).xy; + s = vec2(1.0/s.x, 1.0/s.y); + int w = window; + + vec4 sum = vec4(0.0); + float weight = 0; + for (int x = -w; x <= w; ++x) { + float lw = exp( -(x*x) / (2 * sigma * sigma) ) ; + vec2 tc = v_texCoord0 + x * blurDirection * s;// * spread; + sum += texture(tex0, tc) * lw; + weight += lw; + } + o_color = (sum / weight) * gain; +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/box-blur.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/box-blur.frag new file mode 100644 index 00000000..49625f92 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/box-blur.frag @@ -0,0 +1,31 @@ +// openrndr - gl3 - box-blur + +#version 330 core + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform vec2 blurDirection; + +uniform int window; +uniform float sigma; +uniform float gain; +uniform vec4 subtract; +uniform float spread; +out vec4 o_color; +void main() { + vec2 s = textureSize(tex0, 0).xy; + s = vec2(1.0/s.x, 1.0/s.y); + + int w = window; + + vec4 sum = vec4(0, 0, 0, 0); + float weight = 0; + for (int x = -w; x<= w; ++x) { + float lw = 1.0; + sum += texture(tex0, v_texCoord0 + x * blurDirection * s * spread); + weight += lw; + } + + o_color = (sum / weight) * gain; +// o_color.a = 1.0; +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/gaussian-blur.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/gaussian-blur.frag new file mode 100644 index 00000000..b4b49126 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/gaussian-blur.frag @@ -0,0 +1,31 @@ +#version 330 core + +in vec2 v_texCoord0; +uniform sampler2D tex0; + +uniform int window; +uniform float sigma; +uniform float spread; +uniform float gain; + + +out vec4 o_color; +void main() { + + vec2 s = textureSize(tex0, 0).xy; + s = vec2(1.0/s.x, 1.0/s.y); + + int w = window; + + vec4 sum = vec4(0,0,0,0); + float weight = 0; + for (int y = -w; y<= w; ++y) { + for (int x = -w; x<= w; ++x) { + float lw = exp(-(x*x+y*y) / (2 * sigma * sigma)); + sum+=texture(tex0, v_texCoord0 + vec2(x,y) * s * spread) * lw; + weight+=lw; + } + } + + o_color = (sum / weight) * gain; +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/hash-blur.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/hash-blur.frag new file mode 100644 index 00000000..62dfddab --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/hash-blur.frag @@ -0,0 +1,49 @@ +#version 330 core + +// based on Hashed blur by David Hoskins. +// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. + +uniform float radius; +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform float time; +uniform int samples; +uniform float gain; +out vec4 o_color; + +#define TAU 6.28318530718 + +//------------------------------------------------------------------------------------------- +#define HASHSCALE 443.8975 +vec2 hash22(vec2 p) { + vec3 p3 = fract(vec3(p.xyx) * HASHSCALE); + p3 += dot(p3, p3.yzx+19.19); + return fract(vec2((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y)); +} + +vec2 sampleTexture(inout vec2 r) { + r = fract(r * vec2(33.3983, 43.4427)); + //return r-.5; + return sqrt(r.x+.001) * vec2(sin(r.y * TAU), cos(r.y * TAU))*.5; // <<=== circular sampling. +} + + +//------------------------------------------------------------------------------------------- +vec4 blur(vec2 uv, float radius) { + vec2 circle = vec2(radius) * (vec2(1.0) / textureSize(tex0, 0)); + vec2 random = hash22(uv + vec2(time)); + + vec4 acc = vec4(0.0); + for (int i = 0; i < samples; i++) { + acc += texture(tex0, uv + circle * sampleTexture(random)); + } + return acc / float(samples); +} + +//------------------------------------------------------------------------------------------- +void main() { + vec2 uv = v_texCoord0; + float radiusSqr = pow(radius, 2.0); + o_color = blur(uv, radiusSqr); + o_color.rgb *= gain; +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/kawase-blur.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/kawase-blur.frag new file mode 100644 index 00000000..05400ce3 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/blur/kawase-blur.frag @@ -0,0 +1,25 @@ +#version 330 + +out vec4 o_color; +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform int iteration; +uniform float spread; + +void main() { + ivec2 size = textureSize(tex0, 0); + vec2 pixelSize = vec2(1.0/size.x, 1.0/size.y); + vec2 halfPixelSize = pixelSize / 2.0f; + vec2 d = (pixelSize.xy * vec2(iteration, iteration)) + halfPixelSize.xy; + d *= spread; + + vec4 dec = vec4(2.2); + vec4 enc = vec4(1.0/2.2); + + vec4 cOut = pow(texture(tex0, v_texCoord0+ vec2(-1, 1)*d), dec); + cOut += pow(texture(tex0, v_texCoord0 + vec2(1, 1)*d), dec); + cOut += pow(texture(tex0, v_texCoord0 + vec2(1, -1)*d), dec); + cOut += pow(texture(tex0, v_texCoord0+ vec2(-1, -1)*d), dec); + + o_color = pow(cOut/4.0, enc); +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/color/color-lookup.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/color/color-lookup.frag new file mode 100644 index 00000000..13758d3b --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/color/color-lookup.frag @@ -0,0 +1,41 @@ +#version 330 +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform sampler2D lookup; +uniform float seed; +uniform float noiseGain; + + +out vec4 o_color; + +#define HASHSCALE 443.8975 +vec2 hash22(vec2 p) { + vec3 p3 = fract(vec3(p.xyx) * HASHSCALE); + p3 += dot(p3, p3.yzx+19.19); + return fract(vec2((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y)); +} + +// -- from https://github.com/jeromeetienne/threex.coloradjust/blob/master/threex.coloradjust.js +vec4 sampleAs3DTexture(sampler2D lut, vec3 uv, float width) { + float sliceSize = 1.0 / width; // space of 1 slice + float slicePixelSize = sliceSize / width; // space of 1 pixel + float sliceInnerSize = slicePixelSize * (width - 1.0); // space of width pixels + float zSlice0 = min(floor(uv.z * width), width - 1.0); + float zSlice1 = min(zSlice0 + 1.0, width - 1.0); + float xOffset = slicePixelSize * 0.5 + uv.x * sliceInnerSize; + float s0 = xOffset + (zSlice0 * sliceSize); + float s1 = xOffset + (zSlice1 * sliceSize); + vec4 slice0Color = texture(lut, vec2(s0, 1.0-uv.y)); + vec4 slice1Color = texture(lut, vec2(s1, 1.0-uv.y)); + float zOffset = mod(uv.z * width, 1.0); + vec4 result = mix(slice0Color, slice1Color, zOffset); + return result; +} + +void main() { + vec4 color = texture(tex0, v_texCoord0); + vec3 noise = vec3(hash22(v_texCoord0-vec2(seed)), hash22(-v_texCoord0+vec2(seed)).x); + vec3 graded = sampleAs3DTexture(lookup, min(vec3(1.0), max(vec3(0.0),color.rgb + noise * noiseGain)), 16.0).rgb; + o_color.rgb = min(vec3(1.0), max(vec3(0.0), graded)); + o_color.a = color.a; +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/color/color-mix.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/color/color-mix.frag new file mode 100644 index 00000000..28e17375 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/color/color-mix.frag @@ -0,0 +1,20 @@ +#version 330 + +uniform float[25] colorMatrix; + +vec4 colorTransform(vec4 color, float[25] matrix) { + float r = color.r * matrix[0] + color.g * matrix[5] + color.b * matrix[10] + color.a * matrix[15] + matrix[20]; + float g = color.r * matrix[1] + color.g * matrix[6] + color.b * matrix[11] + color.a * matrix[16] + matrix[21]; + float b = color.r * matrix[2] + color.g * matrix[7] + color.b * matrix[12] + color.a * matrix[17] + matrix[22]; + float a = color.r * matrix[3] + color.g * matrix[8] + color.b * matrix[13] + color.a * matrix[18] + matrix[23]; + return vec4(r, g, b, a); +} + +in vec2 v_texCoord0; +uniform sampler2D tex0; + +out vec4 o_color; +void main() { + vec4 c = texture(tex0, v_texCoord0); + o_color = colorTransform(c, colorMatrix); +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/color/subtract-constant.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/color/subtract-constant.frag new file mode 100644 index 00000000..2bec0732 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/color/subtract-constant.frag @@ -0,0 +1,11 @@ +#version 330 + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform vec4 constant; + +out vec4 o_color; +void main() { + vec4 c = texture(tex0, v_texCoord0); + o_color = max(vec4(0.0), c - constant); +} diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/dither/a-dither.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/dither/a-dither.frag new file mode 100644 index 00000000..71b46108 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/dither/a-dither.frag @@ -0,0 +1,55 @@ +#version 330 + +// this shader is based on the "a dither" work by Øyvind Kolås +// https://pippin.gimp.org/a_dither/ + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform int pattern; +uniform int levels; + +float mask1(int levels, float l, int x, int y, int c) { + float mask = ((x ^ y * 149) * 1234& 511)/511.0; + return floor(levels * l + mask)/levels; +} + +float mask2(int levels, float l, int x, int y, int c) { + float mask = (((x+c*17) ^ y * 149) * 1234 & 511)/511.0; + return floor(levels * l + mask)/levels; +} +float mask3(int levels, float l, int x, int y, int c) { + float mask = ((x + y * 237) * 119 & 255)/255.0; + return floor(levels * l + mask)/levels; +} + +float mask4(int levels, float l, int x, int y, int c) { + float mask = (((x+c*67) + y * 236) * 119 & 255)/255.0; + return floor(levels * l + mask)/levels; +} + + + + + +out vec4 o_color; +void main() { + vec4 c = texture(tex0, v_texCoord0); + + ivec2 ic = ivec2(v_texCoord0 * textureSize(tex0, 0)); + + vec3 rgb = vec3(1.0, 0.0, 1.0); + if (pattern == 0) { + rgb = vec3(mask1(levels, c.r, ic.x, ic.y, 0), mask1(levels, c.g, ic.x, ic.y, 1), mask1(levels, c.b, ic.x, ic.y, 2)); + } else if (pattern == 1) { + rgb = vec3(mask2(levels, c.r, ic.x, ic.y, 0), mask2(levels, c.g, ic.x, ic.y, 1), mask2(levels, c.b, ic.x, ic.y, 2)); + } else if (pattern == 2) { + rgb = vec3(mask3(levels, c.r, ic.x, ic.y, 0), mask3(levels, c.g, ic.x, ic.y, 1), mask3(levels, c.b, ic.x, ic.y, 2)); + } else { + rgb = vec3(mask4(levels, c.r, ic.x, ic.y, 0), mask4(levels, c.g, ic.x, ic.y, 1), mask4(levels, c.b, ic.x, ic.y, 2)); + } + + + + o_color.rgb = rgb; + o_color.a = 1.0; +} diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/transform/flip-vertically.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/transform/flip-vertically.frag new file mode 100644 index 00000000..d615460c --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/transform/flip-vertically.frag @@ -0,0 +1,12 @@ +#version 330 core + +in vec2 v_texCoord0; +uniform sampler2D tex0; +uniform vec4 constant; + +out vec4 o_color; +void main() { + vec2 uv = v_texCoord0; + uv.y = 1.0 - uv.y; + o_color = texture(tex0, uv); +} diff --git a/settings.gradle b/settings.gradle index f8a14c65..e3d1033d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,6 +5,7 @@ include 'orx-camera', 'orx-easing', 'orx-file-watcher', 'orx-filter-extension', + 'orx-fx', 'orx-gradient-descent', 'orx-integral-image', 'orx-interval-tree',