From b5b6ffa0a1f0badba246b8be4e22181aa42d6bfa Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 15 Dec 2019 00:37:44 +1100 Subject: [PATCH] reimplemented blur shaders with new format xml metadata These could be reimplemented almost wholesale, however the code has been cleaned up and documented and the XML metadata has been updated to support international translations. --- app/shaders/boxblur.frag | 37 +++++++++++++++++++ app/shaders/boxblur.xml | 43 ++++++++++++++++++++++ app/shaders/gaussianblur.frag | 68 +++++++++++++++++++++++++++++++++++ app/shaders/gaussianblur.xml | 43 ++++++++++++++++++++++ 4 files changed, 191 insertions(+) create mode 100644 app/shaders/boxblur.frag create mode 100644 app/shaders/boxblur.xml create mode 100644 app/shaders/gaussianblur.frag create mode 100644 app/shaders/gaussianblur.xml diff --git a/app/shaders/boxblur.frag b/app/shaders/boxblur.frag new file mode 100644 index 000000000..dfa1dce96 --- /dev/null +++ b/app/shaders/boxblur.frag @@ -0,0 +1,37 @@ +#version 110 + +uniform vec2 ove_resolution; +varying vec2 ove_texcoord; +uniform int ove_iteration; + +uniform sampler2D tex_in; +uniform float radius_in; +uniform bool horiz_in; +uniform bool vert_in; + +void main(void) { + if (radius_in == 0.0 + || (iteration == 0 && !horiz_in) + || (iteration == 1 && !vert_in)) { + gl_FragColor = texture2D(image, ove_texcoord); + return; + } + + // We only sample on hard pixels, so we don't accept decimal radii + float real_radius = ceil(radius); + + // Calculate the weight of each pixel based on the radius + float divider = 1.0 / real_radius; + + vec4 composite = vec4(0.0); + for (float i=-real_radius+0.5;i<=real_radius;i+=2.0) { + vec2 pixel_coord = ove_texcoord; + if (iteration == 0) { + pixel_coord.x += i/ove_resolution.x; + } else if (iteration == 1) { + pixel_coord.y += i/ove_resolution.y; + } + composite += texture2D(image, pixel_coord) * divider; + } + gl_FragColor = composite; +} diff --git a/app/shaders/boxblur.xml b/app/shaders/boxblur.xml new file mode 100644 index 000000000..438e1a5c8 --- /dev/null +++ b/app/shaders/boxblur.xml @@ -0,0 +1,43 @@ + + + + Box Blur + + + Blur + + + + A fast blur calculated by averaging a square of pixels around each pixel. Fast, but can have a "striated" look to it. + + + + + Input + + + + + Radius + 0 + 10 + + + + + Horizontal + true + + + + + Vertical + true + + + + + + + 2 + diff --git a/app/shaders/gaussianblur.frag b/app/shaders/gaussianblur.frag new file mode 100644 index 000000000..1986bebf1 --- /dev/null +++ b/app/shaders/gaussianblur.frag @@ -0,0 +1,68 @@ +#version 110 + +// Standard inputs +uniform vec2 ove_resolution; +varying vec2 ove_texcoord; +uniform int ove_iteration; + +// Node parameter inputs +uniform sampler2D tex_in; +uniform float sigma_in; +uniform bool horiz_in; +uniform bool vert_in; + +// Gaussian function uses PI +#define M_PI 3.1415926535897932384626433832795 + +// Single gaussian formula (unused, mainly here for documentation/just in case) +//float gaussian(float x, float sigma) { +// return (1.0/(sigma*sqrt(2.0*M_PI)))*exp(-0.5*pow(x/sigma, 2.0)); +//} + +// Double gaussian formula, actually used in the code below +// Should be faster than the single gaussian above since it doesn't need sqrt() +float gaussian2(float x, float y, float sigma) { + return (1.0/(pow(sigma, 2.0)*2.0*M_PI))*exp(-0.5*((pow(x, 2.0) + pow(y, 2.0))/pow(sigma, 2.0))); +} + +void main(void) { + // Determine this iteration should process anything or not + if (sigma_in == 0.0 // If the radius is zero + || (ove_iteration == 0 && !horiz_in) // Or this iteration (horizontal) is disabled + || (ove_iteration == 1 && !vert_in)) { // Or this iteration (vertical) is disabled + // No-op, do nothing + gl_FragColor = texture2D(tex_in, ove_texcoord); + return; + } + + // Using (3 * sigma) because 3 standard deviations covers 97% of the blur according to this document: + // http://chemaguerra.com/gaussian-filter-radius/ + float radius = ceil(3.0 * sigma); + + // Use gaussian formula to calculate the weight of all pixels + float sum = 0.0; + for (float i=-radius+0.5;i<=radius;i+=2.0) { + sum += gaussian2(i, 0.0, sigma_in); + } + + // We can take advantage of OpenGL's linear interpolation by sampling between pixels. This produces a mathematically + // identical result while allowing us to sample the texture half as many times. + vec4 composite = vec4(0.0); + for (float i=-radius+0.5;i<=radius;i+=2.0) { + // Calculate weight of this pixel using gaussian + float weight = (gaussian2(i, 0.0, sigma_in)/sum); + + // Determine pixel coordinate based on iteration + // We use two iterations horizontally and vertically since that produces a mathematically identical result and + // (2*radius) is much faster than (radius^2) + vec2 pixel_coord = ove_texcoord; + if (ove_iteration == 0) { + pixel_coord.x += i/ove_resolution.x; + } else if (ove_iteration == 1) { + pixel_coord.y += i/ove_resolution.y; + } + + composite += texture2D(tex_in, pixel_coord) * weight; + } + gl_FragColor = composite; +} diff --git a/app/shaders/gaussianblur.xml b/app/shaders/gaussianblur.xml new file mode 100644 index 000000000..a4f375d10 --- /dev/null +++ b/app/shaders/gaussianblur.xml @@ -0,0 +1,43 @@ + + + + Gaussian Blur + + + Blur + + + + A smooth blur using the gaussian function. Slower than box blur but also prettier. + + + + + Input + + + + + Sigma + 0 + 5.5 + + + + + Horizontal + + + + + + Vertical + true + + + + + + + 2 +