Skip to main content
GameDev.net gamedev.net
🔒 Locked

How can I improve this glsl Bloom Shader? (Code within)

Started by AntonyCoder May 27, 2006 at 7:36 AM 11 replies 26.8k views
Original Post
AntonyCoder
AntonyCoder
I've wrote a Bloom shader in glsl and although it works, technically at least, it looks pretty awful and nothing like Ghost Recon or any other hdr game. Here's the shader,

uniform sampler2D tex0;

void main(void)
{
	vec4 blurSample = 0.0;
	vec4 tmpPix;
	vec4 offPix;
	for(int tx =-2;tx<3;tx++)
        {
		for(int ty =-2;ty<3;ty++)
		{
			vec2 uv = gl_TexCoord[0].st;
			uv.x = uv.x + tx*0.01;
			uv.y = uv.y + ty*0.01;
			tmpPix = texture2D(tex0,uv);
			offPix = -0.3+tmpPix;
			offPix = offPix *32;
			blurSample = blurSample + offPix;
			
		}	
        }
	blurSample = blurSample / 256;
	gl_FragColor = texture2D(tex0,gl_TexCoord[0].st)*2+blurSample*1.2;
}

tex0 = the viewport copied to a texture. I then use this shader on a screen sized quad over the viewport using material replace not blend/add. As you can see I take a 4x4 sample of each pixel, then scale it into a -0.3 to 0.7 * 32 value, then soften the final sample by deviding it by 256, then I combined this with a 2x amplification of the source viewport with a 1.2 amplification of the blursample vector. Is there a better way? Should I look into multi-pass techniques, and if so are there any tutorials glsl examples you can point me in the direction of please? How did you handle bloom personally? Taking into account I'm using a pixel shader model 2 card that has no hdr floating point texture support.
OrangyTang
OrangyTang
Quote:
Original post by AntonyCoder
As you can see I take a 4x4 sample of each pixel, then scale it into a -0.3 to 0.7 * 32 value, then soften the final sample by deviding it by 256, then I combined this with a 2x amplification of the source viewport with a 1.2 amplification of the blursample vector.

Good bloom requires a big filter kernel. There are several ways of doing this, but the most common is the 'separable gaussian', ie. you first do a wide (say, 8 samples) horizontal blur, then a vertical blur. The end result being that you get the equivilent of an 8x8 blur with only a fraction of the work.

Good weights (gaussian works well) are also important.
Anudh
Anudh
Here's some screenshots of the fakish bloom I implemented, doesnt use shaders.

Image Hosted by ImageShack.usImage Hosted by ImageShack.us

And heres a comparison with bloom disabled and enabled.
Image Hosted by ImageShack.usImage Hosted by ImageShack.us


It looks more like an indoor sun :p. What I did was render the scene to a texture, and render the lighted parts to another texture. And then blur the 'lighted parts' texture and blend together the results. Yea, it was more trouble than its worth. But its faster than using a shader and will also work on poorer hardware. Notice the framerate doesnt suffer if (fake) bloom is enabled on my GF 5200.
-[Anudhyan][Website]
AntonyCoder
AntonyCoder
I tried it Orang, and the blur does appear a little better, but I'm still having trouble.

To really notice the bloom I have to amplify the blurred sample but then anything that's whitish on the screen just becomes obscured which is not what I'm after.

Maybe I should add a feature to my postfx system to render lights only as billboards(I.e the corona) and then blend that with the naked scene?

Here's the update shader,

uniform sampler2D tex0;void main(void){	vec4 blurSample = 0.0;	vec4 tmpPix;	vec4 offPix;	vec2 uv = gl_TexCoord[0].st;	for(int i=-4;i<5;i++)	{		tmpPix = texture2D(tex0,uv + vec2( i*0.005,0 ));		offPix = -0.3+tmpPix;		offPix = offPix * 15;		if( (offPix.r+offPix.g+offPix.b)>0 )		{			                blurSample = blurSample + offPix;			}	}	for(int i=-4;i<5;i++)	{		tmpPix = texture2D(tex0,uv + vec2( 0,i*0.005 ));              	offPix = -0.3+tmpPix;		offPix = offPix * 15;		if( (offPix.r+offPix.g+offPix.b)>0 )		{			blurSample += offPix;		}	}	blurSample = blurSample / 64;	gl_FragColor = blurSample*1.2;}


If you have the time could you improve it using some techniques you know to help get me started on the right track? I'd appreciate it :)
--

Looking good Anhud. Certainly better than mine :)
How did you seperate dark and light areas when applying the bloom? The only way I can do it is by checking in the pixel shader and discarding any changes made by any samples below 0.5 (On each rgb component)

I've seen that there are ways to do this without shaders but I'm not so sure I can try, my postfx system is pivoted around shaders really.
AntonyCoder
AntonyCoder
btw anuld, mind if I nick your cursor style for my fps tech demo? :)

deavik
deavik
Quote:
Original post by Anudh
It looks more like an indoor sun :p. What I did was render the scene to a texture, and render the lighted parts to another texture. And then blur the 'lighted parts' texture and blend together the results. Yea, it was more trouble than its worth. But its faster than using a shader and will also work on poorer hardware. Notice the framerate doesnt suffer if (fake) bloom is enabled on my GF 5200.

Hi Anudh, that's some nice work, I was amazed to find rendering time doesn't change if you add the bloom. I had a couple of questions:

1. For render to texture, does the FX series have support for FBO or do you use the WGL render_texture?

2. Since you mentioned no shaders, do you do the blurring of the second texture on the CPU? How is the readback so fast that it doesn't affect performance?

Baffled, but impressed! [smile]
Anudh
Anudh
Quote:
btw anuld, mind if I nick your cursor style for my fps tech demo? :)

Sure, no problem :) But thats a crosshair not the cursor, the cursor is hidden, the crosshair is always in the middle of the screen.

Quote:
1. For render to texture, does the FX series have support for FBO or do you use the WGL render_texture?

Yes my GF FX 5200 supports FBO and I used FBO in this instance.

Quote:
2. Since you mentioned no shaders, do you do the blurring of the second texture on the CPU? How is the readback so fast that it doesn't affect performance?

Yes the whole thing is done on the CPU, the scene texture is alpha-blended and drawn repetitively on top of itself, each time moving it a bit. One speed factor is the FBO used and not glCopyTexSubImage and not using a shader. I also did a similar bloom with a shader and found it to be slower.

@deavik: Where do you live in Kolkata ?
-[Anudhyan][Website]
deavik
deavik
Quote:
Original post by Anudh
Yes the whole thing is done on the CPU, the scene texture is alpha-blended and drawn repetitively on top of itself, each time moving it a bit. One speed factor is the FBO used and not glCopyTexSubImage and not using a shader. I also did a similar bloom with a shader and found it to be slower.

I have heard that in the FX series, even though it supports shaders, the performance is notoriously bad - and some owners of the card say so with great emphasis. From what you are describing, I think you'll find that the shader approach is much faster than the texture readback in a newer card.

Quote:
@deavik: Where do you live in Kolkata ?

Salt Lake. [grin] I'm sending you a PM ...
Anudh
Anudh
I have heard that in the FX series, even though it supports shaders, the performance is notoriously bad - and some owners of the card say so with great emphasis. From what you are describing, I think you'll find that the shader approach is much faster than the texture readback in a newer card.

Yea, I implemented self-shadowing relief and it was running at 0 FPS [sad]. And I had to run at at resolution of 320x240 to be able to get 5 FPS.
-[Anudhyan][Website]
Anudh
Anudh
Quote:
I have heard that in the FX series, even though it supports shaders, the performance is notoriously bad - and some owners of the card say so with great emphasis. From what you are describing, I think you'll find that the shader approach is much faster than the texture readback in a newer card.

Yea, I implemented self-shadowing relief and it was running at 0 FPS [sad]. And I had to run at at resolution of 320x240 to be able to get at least 5 FPS.
-[Anudhyan][Website]
Anudh
Anudh
btw AntonyCoder, I tried your shader, and got a really cool effect, nice work [smile].

Image Hosted by ImageShack.usImage Hosted by ImageShack.us
I'm going to use it for fire, notice the floor. This will be really great for the fire coloring. Thanks.
-[Anudhyan][Website]
Kalidor
Kalidor
Quote:
Original post by AntonyCoder
I tried it Orang, and the blur does appear a little better, but I'm still having trouble.
...
What OrangyTang meant was to first blur horizontally and render that to a texture, then in another pass you blur the horizontally-blurred texture vertically. What you are doing in that shader is blurring the original texture horizontally, and then blurring the original texture vertically and adding them together; something like the Matrix Effect. What you want is to have one shader blur horizontally only, render into another texture with that shader, then use that new texture and render with another shader that blurs vertically.
AntonyCoder
AntonyCoder
Lol nice to see it running with some real media instead of the primitive levels I build(I'm the worst artist in the world. In fact you can't even call me an artist. I'm just a tist.)

I think it looks good for scary levels. I mean you alien looks like a complete physco with my shader running :) Alien verus predator eat yer heart out.
-

OK kalidor guess I assumed wrong. It's easy for me to try because I wrote a pretty nice multi-pass post fx system so I can easily add shader passes with texture outputs. I'll post a demo to your announcements soon.



Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.