Block filters using fragment shaders

Posted by Nils on Stack Overflow See other posts from Stack Overflow or by Nils
Published on 2010-05-09T11:57:24Z Indexed on 2010/05/09 12:08 UTC
Read the original article Hit count: 461

I was following this tutorial using Apple's OpenGL Shader Builder (tool similar to Nvidia's fx composer, but simpler).

I could easily apply the filters, but I don't understand if they worked correct (and if so how can I improve the output). For example the blur filter: OpenGL itself does some image processing on the textures, so if they are displayed in a higher resolution than the original image, they are blurred already by OpenGL. Second the blurred part is brighter then the part not processed, I think this does not make sense, since it just takes pixels from the direct neighborhood. This is defined by

float step_w = (1.0/width);

Which I don't quite understand: The pixels are indexed using floating point values??

Blurred Image

Edit: I forgot to attach the exact code I used:

Fragment Shader

// Originally taken from: http://www.ozone3d.net/tutorials/image_filtering_p2.php#part_2

#define KERNEL_SIZE 9

float kernel[KERNEL_SIZE];

uniform sampler2D colorMap;
uniform float width;
uniform float height;

float step_w = (1.0/width);
float step_h = (1.0/height);

// float step_w = 20.0;
// float step_h = 20.0;

vec2 offset[KERNEL_SIZE];

void main(void)
{
   int i = 0;
   vec4 sum = vec4(0.0);

   offset[0] = vec2(-step_w, -step_h);  // south west
   offset[1] = vec2(0.0, -step_h);      // south
   offset[2] = vec2(step_w, -step_h);       // south east

   offset[3] = vec2(-step_w, 0.0);      // west
   offset[4] = vec2(0.0, 0.0);          // center
   offset[5] = vec2(step_w, 0.0);       // east

   offset[6] = vec2(-step_w, step_h);       // north west
   offset[7] = vec2(0.0, step_h);       // north
   offset[8] = vec2(step_w, step_h);        // north east


// Gaussian kernel
// 1 2 1
// 2 4 2
// 1 2 1


   kernel[0] = 1.0;     kernel[1] = 2.0;    kernel[2] = 1.0;
   kernel[3] = 2.0; kernel[4] = 4.0;    kernel[5] = 2.0;
   kernel[6] = 1.0;     kernel[7] = 2.0;    kernel[8] = 1.0;


// TODO make grayscale first
// Laplacian Filter
// 0   1   0
// 1  -4   1
// 0   1   0

/*
kernel[0] = 0.0;    kernel[1] = 1.0;    kernel[2] = 0.0;
kernel[3] = 1.0;    kernel[4] = -4.0;   kernel[5] = 1.0;
kernel[6] = 0.0;   kernel[7] = 2.0; kernel[8] = 0.0;
*/

// Mean Filter
// 1  1  1
// 1  1  1
// 1  1  1

/*
kernel[0] = 1.0;    kernel[1] = 1.0;    kernel[2] = 1.0;
kernel[3] = 1.0;    kernel[4] = 1.0;    kernel[5] = 1.0;
kernel[6] = 1.0;   kernel[7] = 1.0; kernel[8] = 1.0;
*/

   if(gl_TexCoord[0].s<0.5)
   {
       // For every pixel sample the neighbor pixels and sum up
       for( i=0; i<KERNEL_SIZE; i++ )
       {
            // select the pixel with the concerning offset
            vec4 tmp = texture2D(colorMap, gl_TexCoord[0].st + offset[i]);
            sum += tmp * kernel[i];
       }

        sum /= 16.0;
   }
   else if( gl_TexCoord[0].s>0.51 )
   {
        sum = texture2D(colorMap, gl_TexCoord[0].xy);
   }
   else // Draw a red line
   {
        sum = vec4(1.0, 0.0, 0.0, 1.0);
   }

   gl_FragColor = sum;
}

Vertex Shader

void main(void)
{
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = ftransform();
}

© Stack Overflow or respective owner

Related posts about fragment-shader

Related posts about pixel-shader