Files
oak-editor/app/shaders/gaussianblur.frag
T

76 lines
2.8 KiB
GLSL

#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;
uniform bool repeat_edge_pixels_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_in);
// 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;
}
if (repeat_edge_pixels_in
|| (pixel_coord.x >= 0.0
&& pixel_coord.x < 1.0
&& pixel_coord.y >= 0.0
&& pixel_coord.y < 1.0)) {
composite += texture2D(tex_in, pixel_coord) * weight;
}
}
gl_FragColor = composite;
}