Bloom demo with source code

Hello

I have prepared a small demo that shows two techniques of creating a bloom effect. Maybe it will be useful to someone.
There are actually two demos. One uses Gaussian blur to blur the screen. The other uses linear scaling that is repeated four times, hence I called it “quadlinear”. Both demos use FBOs and GLSL, so if your graphic card doesn’t support them, don’t bother trying to run the demos :stuck_out_tongue:

The first demo can be launched by clicking here
The second demo can be launched by clicking here

NOTE: When the demo starts the bloom is turned off. In order to turn it on, press “b”.

Source code for both demos is here
And here’s a screenshot:

http://www.insightmachines.com/devel/bloom/bloom.png

Any comments/questions are welcome :slight_smile:

Cheers,
Grzegorz

looks very nice… pity my laptop video card does not like using FBO or GLSL so i saw a blank screen when turning on the bloom effect

Cool! I don’t know GLSL, but from what I can see this looks like it is blurring the textures on the box. Can this get that “fuzzy silhouette” effect between different objects as well?

I also discovered that my video card supports GLSL, which is a nice surprise. :slight_smile:

Bloom is a post-processing technique. You render the whole scene to a FBO and then render the image from the FBO onto the screen using a shader program that applies various operations like a Gaussian blur for example.

I get it now, thanks for the clarification. The ‘texture’ it is being applied to is actually the entire FBO, which makes more sense.

The Gaussian blur function looks more like it is taking 9 samples from a hat function horizontally and then vertically, rather than sampling a full 2D Gaussian though. Of course the resulting effect may well be much the same, and it has got to be faster.

Edit: I’m wrong. I don’t quite get what the filter is, but not just a hat function. :-\

The Gaussian blur shader is taken from here.
It is not really a hat function, just something similar, but easier (faster) to calculate.

This is nice article on the matter: http://prideout.net/bloom/index.php

Ah yes. I know this one. It’s a very good article indeed. The quadlinear method in my demo is very similar to the “'quick and dirty” method described by Philip. The Gaussian filter is different though, because Philip takes a more mathematically correct approach and uses square matrices, while I used a less elegant, yet faster method adapted from the article I mentioned earlier.

That one’s definitely a hat function. I really don’t know whether the hat function is linearly separable. If it is then that should be fine, but to be on the safe side I’d replace the 1/5, 4/25, 3/25, 2/25, 1/25 with values taken from a Gaussian function. This wouldn’t affect the speed at all.

I’m probably getting too pedantic, since mathematical correctness might not have any effect on the visual result. :-\

Edit: Ok, the hat function isn’t linearly separable. Just consider the example of the pixel one diagonal away. The pixel to the side will take 4/25 of your value, then in the vertical pass the one on the diagonal will get (4/25)*(4/25) = 0.0256 of your value. But the correct amount according to the function being used (i.e. the hat function: 5 minus the distance divided by 25) should be (5-sqrt(2))/25 = 0.1436. So I’m guessing the actual effect is more like a “plus” than a circle.

The screenshots in that link were apparently taken from ATI slides, not from the results of that persons code.

This isn’t a “plus” either, because if you consider pixel (x,y), the pixels above and below it during the vertical pass are already blurred with pixels on their right and left. So in the end the value at (x,y) will depend on values of all 80 pixels around (x,y) and of course the original value at (x,y). Moreover, a pixel further away will have a smaller influence than a pixel close to (x,y), so there is some similarity to a Gaussian curve.

It has significantly higher effect directly to the left and right where it tails off linearly, whereas in diagonals it tails off quadratically. So while not exactly a “plus”, it is much more like one than it is like a circle.

It’s not similar to a Gaussian, because Gaussians are linearly separable.

On a more constructive note, here’s values for a Gaussian with standard deviation of 1 at distances 0-4:
0.4, 0.2426, 0.05412, 0.00444, 0.00012

If this was applied horizontally and then vertically it’d work like a 2D Gaussian.

Edit: Corrected a mistake with the std dev.

Thanks Jono!

Std dev of 1 does not work too well here as the last two weights (0.00444 and 0.00012) are practically zero. However a std dev of 2 gives more useful values:
0.2, 0.18, 0.12, 0.06, 0.03

Nevertheless the real problem with this filter is that it seems to be too weak, while being rather slow.

Are you operating on a full framebuffer sized texture? Shrinking it down to half or even a quater size can give almost as good results but dramatically faster (which may also let you take more samples).

Also, by clever offsetting of your blur samples to fall between texels you can (ab)use texture filtering to give you two samples for the price of one texture lookup.

I went back over the hat function more carefully, and even though it isn’t quite correct it doesn’t make a “plus” like I first thought. As you said, it is probably close enough to make no noticeable difference. :persecutioncomplex:

Sigh. At least I’ve learnt about blur effects.