Here's the extremely simple vertex shader; the assumption being that you'll be feeding a fullscreen quad to the vertex shader such that it's 4 vertices are positioned at the corners of the viewport:

The fragment shader is setup using macros separated based on the blur direction (i.e., horizontal/vertical) and the blur kernel size (currently 5, 7 and 9; but this can easily be extended). Here's the fragment shader:void main() {gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;gl_TexCoord[0] = gl_MultiTexCoord0;}

uniform float 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 :)

uniform float 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.

uniform sampler2D blurSampler; // Texture that will be blurred by this shader

const float pi = 3.14159265f;

// The following are all mutually exclusive macros for various

// seperable blurs of varying kernel size

#if defined(VERTICAL_BLUR_9)

const float numBlurPixelsPerSide = 4.0f;

const vec2 blurMultiplyVec = vec2(0.0f, 1.0f);

#elif defined(HORIZONTAL_BLUR_9)

const float numBlurPixelsPerSide = 4.0f;

const vec2 blurMultiplyVec = vec2(1.0f, 0.0f);

#elif defined(VERTICAL_BLUR_7)

const float numBlurPixelsPerSide = 3.0f;

const vec2 blurMultiplyVec = vec2(0.0f, 1.0f);

#elif defined(HORIZONTAL_BLUR_7)

const float numBlurPixelsPerSide = 3.0f;

const vec2 blurMultiplyVec = vec2(1.0f, 0.0f);

#elif defined(VERTICAL_BLUR_5)

const float numBlurPixelsPerSide = 2.0f;

const vec2 blurMultiplyVec = vec2(0.0f, 1.0f);

#elif defined(HORIZONTAL_BLUR_5)

const float numBlurPixelsPerSide = 2.0f;

const vec2 blurMultiplyVec = vec2(1.0f, 0.0f);

#else

// This only exists to get this shader to compile when no macros are defined

const float numBlurPixelsPerSide = 0.0f;

const vec2 blurMultiplyVec = vec2(0.0f, 0.0f);

#endif

void main() {

// Incremental Gaussian Coefficent Calculation (See GPU Gems 3 pp. 877 - 889)

vec3 incrementalGaussian;

incrementalGaussian.x = 1.0f / (sqrt(2.0f * pi) * sigma);

incrementalGaussian.y = exp(-0.5f / (sigma * 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...

avgValue += texture2D(blurSampler, gl_TexCoord[0].xy) * incrementalGaussian.x;

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++) {

avgValue += texture2D(blurSampler, gl_TexCoord[0].xy - i * blurSize *

blurMultiplyVec) * incrementalGaussian.x;

avgValue += texture2D(blurSampler, gl_TexCoord[0].xy + i * blurSize *

blurMultiplyVec) * incrementalGaussian.x;

coefficientSum += 2 * incrementalGaussian.x;

incrementalGaussian.xy *= incrementalGaussian.yz;

}

gl_FragColor = avgValue / coefficientSum;

}

## 2 comments:

Hi. Interesting article. I'm not sure why you need to execute `gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex' though. If your quad vertices go from -1 to 1 and the intention is to fill the viewport, you don't need to transform them at all. Also, you won't need texture coordinates in your vertex, as these are simply output from the VS as position * 0.5 + 0.5.

i am using same code for blurring, but the result of rendering is a black screen. how it can be like this.

Post a Comment