Last week i was having fun with OpenGL(in fact QGL) and creating some interesting effects with it like edge detection, embossing and sharpening. So i decided to work with GLSL(OpenGL Shading Language) and create the same effects using Fragment Shaders(yeah hardware accelerated effects).

So i used QGLShaderProgam that allows me create Fragment shaders in a Qt Way(tm). Initially i create two filters the first one was sharpening and the second was edge detection. Both work in a same way(with little modifications), applying a matrix convolution in the image.

The matrix convolution used in sharpening is:

0 -1 0

-1 5 -1

0 -1 0

And the matrix convolution used in edge dection is:

-1 -1 -1

-1 8 -1

-1 -1 -1

Below you can see the fragment shader used in sharpening.

*uniform sampler2D sampler;*

*uniform vec2 offset[9];*

*uniform int kernel[9];*

*void main()*

{

vec4 sum = vec4(0.0);

int i;

*for (i = 0; i < 9; i++) {*

vec4 color = texture2D(sampler, gl_TexCoord[0].st + offset[i]);

sum += color * kernel[i];

}

*gl_FragColor = sum;*

}

The shader used in edge is almost the same

*uniform sampler2D sampler;*

*uniform vec2 offset[9];*

*uniform int kernel[9];*

*void main()*

{

vec4 sum = vec4(0.0);

int i;

*for (i = 0; i < 9; i++) {*

vec4 color = texture2D(sampler, gl_TexCoord[0].st + offset[i]);

sum += color * kernel[i];

}

*sum += 0.51;*

*gl_FragColor = sum;*

}

The original image used in my experiments can be seen below:

The result of sharpening filter is:

Yeah we have a little bit improvement on the image.

And the result of edge filter is:

The embossing filter is a little bit complicated as you can see:

*uniform sampler2D sampler;*

uniform vec2 offset[9];

uniform int kernel[9];

void main()

{

vec4 sum = vec4(0.0);

int i = 0;

for( i = 0; i < 9; i++) {

vec4 color_tmp = texture2D(sampler, gl_TexCoord[0].st + offset[i]);

float h = (color_tmp.x + color_tmp.y + color_tmp.z + color_tmp.w)/4.0;

if (h > 1)

h = 1.0;

*if (h < 0)*

h = 0.0;

*vec4 color = vec4(h, h, h, h);*

sum.x += color.x * kernel[i];

}

*sum.x /= 1.0;*

sum.x += 0.51;

*if (sum.x > 1)*

sum.x = 1;

if (sum.x < 0)

sum.x = 0;

*gl_FragColor = vec4(sum.x, sum.x, sum.x, 1);*

}

And the result is:

Qt already do OpenGL accelerated filters in QGraphicsEffects classes(look in qt_top_dir/src/opengl/qglpixmapfilter*) it is not anything new but it is interesting use it in others KDE application like krita filters.