76 lines
2.8 KiB
GLSL
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;
|
|
}
|