Files
ResInsight/Fwk/VizFwk/LibRender/glsl/fs_GaussianBlur.glsl

114 lines
4.5 KiB
GLSL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#if defined(USE_TEXTURE_RECT)
#extension GL_ARB_texture_rectangle : enable
#endif
// Shader program based on source code in article:
// http://callumhay.blogspot.no/2010/09/gaussian-blur-shader-glsl.html
// Which in turn is based on GPU Gems 3; Chapter 40 ('Incremental Computation of the Gaussian' by Ken Turkowski).
// http://http.developer.nvidia.com/GPUGems3/gpugems3_ch40.html
// The sigma value is the standard deviation for the Gaussian distribution
// A higher sigma value means more blur, but the sigma value should be tuned to the kernel size.
// Defensive rule of thumb when choosing sigma values vs kernel size (see first link below):
// The gaussian distribution will have the vast majority of values in the interval [-3*sigma, 3*sigma],
// so a kernel width of 6*sigma should suffice. Just make sure to round it up to the closest odd number,
// so your kernel will be symmetric.
// http://www.gamedev.net/topic/526122-gaussian-blur-calculating-kernel-weight/
// http://en.wikipedia.org/wiki/Gaussian_blur
//
// See also for a discussion of sigma vs kernel size:
// http://theinstructionlimit.com/gaussian-blur-revisited-part-two
// His suggestions for sigma values based on kernel size
// 17-tap : 3.66 4.95
// 15-tap : 2.85 3.34
// 13-tap : 2.49 2.95
// 11-tap : 2.18 2.54
// 9-tap : 1.8 2.12
// 7-tap : 1.55 1.78
// 5-tap : 1.35 1.54
uniform float u_sigma; // The sigma value for the gaussian function: higher value means more blur
// A good value for 9x9 is around 3 to 5
// A good value for 7x7 is around 2.5 to 4
// A good value for 5x5 is around 2 to 3.5
// ... play around with this based on what you need :)
// Texture that will be blurred by this shader
#if defined(USE_TEXTURE_RECT)
uniform sampler2DRect u_blurSampler;
#else
uniform sampler2D u_blurSampler;
uniform float u_blurSize; // This should usually be equal to
// 1.0f / texture_pixel_width for a horizontal blur, and
// 1.0f / texture_pixel_height for a vertical blur.
varying vec2 v_texCoord;
#endif
// The following are all mutually exclusive macros for various seperable blurs of varying kernel size
// The original code had these as constants and using defines to choose one.
// Currently we do more or less the same, but we should investigate using uniforms instead
// Vertical or horizontal pass?
#if defined(VERTICAL_BLUR)
const vec2 blurMultiplyVec = vec2(0.0f, 1.0f);
#elif defined(HORIZONTAL_BLUR)
const vec2 blurMultiplyVec = vec2(1.0f, 0.0f);
#endif
#if defined(KERNEL_SIZE)
const float numBlurPixelsPerSide = (KERNEL_SIZE - 1.0f)/2.0f;
#endif
const float pi = 3.14159265f;
//--------------------------------------------------------------------------------------------------
/// Separable Gaussian blur shader
//--------------------------------------------------------------------------------------------------
void main()
{
// Incremental Gaussian Coefficent Calculation (See GPU Gems 3 pp. 877 - 889)
vec3 incrementalGaussian;
incrementalGaussian.x = 1.0f / (sqrt(2.0f * pi) * u_sigma);
incrementalGaussian.y = exp(-0.5f / (u_sigma * u_sigma));
incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y;
vec4 avgValue = vec4(0.0f, 0.0f, 0.0f, 0.0f);
float coefficientSum = 0.0f;
// Take the central sample first...
#if defined(USE_TEXTURE_RECT)
avgValue += texture2DRect(u_blurSampler, gl_FragCoord.xy) * incrementalGaussian.x;
#else
avgValue += texture2D(u_blurSampler, v_texCoord) * incrementalGaussian.x;
#endif
coefficientSum += incrementalGaussian.x;
incrementalGaussian.xy *= incrementalGaussian.yz;
// Go through the remaining 8 vertical samples (4 on each side of the center)
for (float i = 1.0f; i <= numBlurPixelsPerSide; i++)
{
#if defined(USE_TEXTURE_RECT)
avgValue += texture2DRect(u_blurSampler, gl_FragCoord.xy - i*blurMultiplyVec) * incrementalGaussian.x;
avgValue += texture2DRect(u_blurSampler, gl_FragCoord.xy + i*blurMultiplyVec) * incrementalGaussian.x;
#else
avgValue += texture2D(u_blurSampler, v_texCoord - i*u_blurSize*blurMultiplyVec) * incrementalGaussian.x;
avgValue += texture2D(u_blurSampler, v_texCoord + i*u_blurSize*blurMultiplyVec) * incrementalGaussian.x;
#endif
coefficientSum += 2*incrementalGaussian.x;
incrementalGaussian.xy *= incrementalGaussian.yz;
}
gl_FragColor = avgValue / coefficientSum;
}