Hardware accelerated gaussian blur

Started by
7 comments, last by lc_overlord 19 years, 7 months ago
Does anyone know how to do a hardware accelerated gaussian blur on a texture? I thought of a couple of ideas, and I even coded one, but it had some strange glitches I couldnt resolve, and I was wondering if anyone had any ideas/information to help so far, my ideas were like this: 1> copy textures into a smaller texture(downscale), then linearly copy them back into the original size(linear upscale); repeat to increase effect (I tried this one, but it only worked correctly on some cards for some odd reason. I would explain error in better detail if anyone wants) 2> maybe some edit of NeHe's radial blur technique to do a gaussian? Although I have no idea how to do that. :) 3> Read pixels call, blur and then TexImage? (might be slow) 4) The gl Imaging subset? I realyl dont know ANYTHING about this, or even if it supported in hardware for most cards. 5> possibly a pixel/vertex shader? (This would definitly have to be a last resort, I have a Geforce 4MX) I dont know where to go here. These are just what I have come up with, but I know there has to be someone with helpful ideas/info out there. I would love to know your opinions!
Advertisement
1> this can be done semi-automatically through auto mipmap generation, unfortunately it does not look very good

Done 3>... it's horribly slow if the buffer is of any significant size. You will want very very fast blurring code, and there's still some overhead from transferring data back and forth. (If you can, at least transfer the data only TO the card, this is much faster)

5> is the fastest - but not on your HW probably

2> might work nicely... use alpha blending and draw the texture several times, offset by some amount in each direction, with higher alpha for the center (use additive blending). Do one pass for X and one for Y.
Gaussian blur is separable, which means that you can filter first along the X axis, and then along the Y axis.

Thus, you would upload the texture, then render into some framebuffer (render target on DX, pbuffer on GL), setting up your texturing to do N taps on the X axis. The number of taps varies by how many texture units you have. Then copy the render target to a texture, and do the same thing again, but sampling along the Y axis.
enum Bool { True, False, FileNotFound };
that siunds like the way I am going to have to lean, but what is a tap?
and if I want the blur to be centered wouldnt I have to offset in four directions (+X +Y -X -Y)? I am guessing that the alpha trick is to simulate a gaussian kernal, (more pixel weight in center), but what should the alpha map look like? I think I will try to guesstimate. thank you for all the help on this
I did something similar today, it's fullscreen and it does suffer from some artifacts because i havent implemented HDR yet.
To see it just go to my site flashbang.nu (theres a link on the bottom of this post) and download the cf tech demo 2(it's on the lefthand side under files).
How do you like my Motion-Blur ? :D

Motion Blur

It doesn`t uses vertex/pixel shaders but it`s a bit slow(~10fps), and you can see the blur from moving towards.

I Also have some Averaged blur pics somewhere, I just haven`t uploaded them yet

Relative Games - My apps

IT's nice, but you can clearly see the banding of the different blur layers, if you move them closer the effect will be more clearly visible
Well the algo is like this->

-I take the pixels from frame[n] in buffer[0]
-I take the pixels from frame[n+1] in buffer[1]

For every pixel in the buffer->
-compute alpha value for both buffers
-blend pixel with formula->GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA (I just described it as a blending method so I won`t write all the code)

-Store those pixels in buffer[0];
-Make texture from buffer[0];

-Take pixels from frame[n+2] in buffer[1]
-Blur pixels from buffer[0] with buffer[1];(Thus Creating recurency)

Relative Games - My apps

Sound complicated, mine is pretty simple.
1. resd the framebuffer into a texture
2. render the texture to the viewport with a set opacity multiple times with some transformation inbetween.

i'll even post the source (it's a part of my screen class).
void screen::putRadialBlur(int i,float l, int q, float o){	/*	  note:	  I is the screentexture	  L is blurr length	  Q is quality or the number of blur layers to be renderd	  O is the opacity	*/	//Draw the previous rendering on top of it		int j=0;	float s=l/q;	glDisable(GL_TEXTURE_GEN_S);	glDisable(GL_TEXTURE_GEN_T);	glEnable(GL_TEXTURE_2D);					// Enable 2D Texture Mapping	glDisable(GL_DEPTH_TEST);					// Disable Depth Testing	glDisable(GL_LIGHTING);	glDepthMask(GL_FALSE);	glColor4f(1,1,1,o);	glBlendFunc(GL_SRC_ALPHA, GL_ONE);		glEnable(GL_BLEND);						// Enable Blending	ViewOrtho(scrx,scry);	glBindTexture(GL_TEXTURE_2D,screenTmap);			// Bind To The Blur Texture	glBegin(GL_QUADS);						// Begin Drawing Quads	while(j<q)	{		glTexCoord2f(0,1);							// Texture Coordinate	(   0,   1 )		glVertex2f(0-(j*s),0-(j*s));				// First Vertex		(   0,   0 )		glTexCoord2f(0,0);							// Texture Coordinate	(   0,   0 )		glVertex2f(0-(j*s),scry+(j*s));				// Second Vertex	(   0, 480 )		glTexCoord2f(1,0);							// Texture Coordinate	(   1,   0 )		glVertex2f(scrx+(j*s),scry+(j*s));			// Third Vertex		( 640, 480 )		glTexCoord2f(1,1);							// Texture Coordinate	(   1,   1 )		glVertex2f(scrx+(j*s),0-(j*s));				// Fourth Vertex	( 640,   0 )	//	putScreenPart(i,0-(j*s),0-(j*s),scrx+(j*s),scry+(j*s));		j++;	}	glEnd();	ViewPerspective();						// Switch To A Perspective View	glEnable(GL_LIGHTING);	glDepthMask(GL_TRUE);	glEnable(GL_DEPTH_TEST);					// Enable Depth Testing	glDisable(GL_TEXTURE_2D);					// Disable 2D Texture Mapping	glDisable(GL_BLEND);						// Disable Blending	glBindTexture(GL_TEXTURE_2D,0);					// Unbind The Texture}



Better post some images of it to
unblurred
blurred
radialblurred - same as the code above.

This topic is closed to new replies.

Advertisement