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
.




April 24, 2010 at 8:37 am
Could these help make faster effects for Krita, digiKam and all kipi-plugins?
OpenCL would be very nice as well.
April 24, 2010 at 7:03 pm
Yeah These could.
About OpenCL i personally do know any opensource implementation of it. Right now each video vendor has it own OpenCL implementation and it could be a problem when implementing the OpenCL kernels.
April 25, 2010 at 8:38 pm
In theory OpenCL code should run on any device that supports it. Even if some code is vendor specific at the beginning it should be easy to change that later.
We would love to have OpenCL support in Krita.
April 25, 2010 at 1:07 pm
We had glsl code editor where you could write code like you wrote in the blog post and Krita would run it as filter. But nobody was around to maintain. Maybe you can help us? We are nice to newcomers
May 16, 2010 at 1:48 am
What are the values in
uniform vec2 offset[9]; ?
uniform int kernel[9]; ?
is the matrix convolution the one that goes in kernel matrix?
if so, what goes in offset matrix?
May 16, 2010 at 1:04 pm
Hi,
you can see what is offset in the code: http://gitorious.org/bb-labs/bb-labs/blobs/master/shaders/one.cpp basically it is the position offset in the image.
June 11, 2010 at 7:42 pm
I used RenderMonkey, and got same results for car image, which is great. My question, if I use this result and apply the filter again, will this help sharpen the image more? (I haven’t figured out how to do this in RenderMonkey, that’s why I’m asking).
June 12, 2010 at 2:34 pm
Hi Martin,
Sharpen has a threshold you can apply the filter again and probably the image will not change.
Igor