boom

Started by
5 comments, last by Yours3!f 11 years, 8 months ago
Hi,

I'd like to implement the bloom effect. I already have the lighting result in a rgba16f texture, and I can already do an efficient gaussian blur. I've already implemented a filmic tone mapping too.
My question is that how do I do the bloom effect?

My thoughts were the following after reading some:
1. blur the shading result (2 passes, hori, vert )
2. downsample
3. combine the 4 + 1 (original) textures using screen blending
4. tonemap

to add, how can I downsample the texture efficiently (1 pass, maybe) ?

best regards,
Yours3!f
Advertisement
Usually you down-sample before blurring, simply to get a bigger blur radius for cheaper. To downsample, just draw a full-screen quad textured with your original texture, and make sure you're using linear filtering (not nearest/point filtering!).

Often bloom effects also include a "threshold" pass, so that the effect is only applied to "bright" pixels. You can do this during your downsample pass by simply subtracting a uniform variable from the texture sample -- e.g. [font=courier new,courier,monospace]texture2D(....) - 6.0f[/font] would make it so that only objects brighter than "6 brightness" will glow.

One issue with "screen" blending is that it only works for non-HDR textures -- i.e. "screen" requires all the values to be from 0.0 to 1.0. So you can either replace this with a simple additive blend, or you can perform the "screen" blend after tonemapping (you might have to tonemap the scene, and also tone-map your blurred bloom data).

Usually you down-sample before blurring, simply to get a bigger blur radius for cheaper. To downsample, just draw a full-screen quad textured with your original texture, and make sure you're using linear filtering (not nearest/point filtering!).

Often bloom effects also include a "threshold" pass, so that the effect is only applied to "bright" pixels. You can do this during your downsample pass by simply subtracting a uniform variable from the texture sample -- e.g. [font=courier new,courier,monospace]texture2D(....) - 6.0f[/font] would make it so that only objects brighter than "6 brightness" will glow.

One issue with "screen" blending is that it only works for non-HDR textures -- i.e. "screen" requires all the values to be from 0.0 to 1.0. So you can either replace this with a simple additive blend, or you can perform the "screen" blend after tonemapping (you might have to tonemap the scene, and also tone-map your blurred bloom data).


thanks Hodgman :)

then I'll simply use additive blending, I just thought that screen blending works better, because it preserves more details in the highlights. But I don't want to do 4 tonemapping passes.
I understand the threshold part, but how do I decide which parts to blur? obviously the threshold must be >1.0 because 0...1 is the usual range. what is an ideal value?
for example I'm using the filmic tonemapping from uncharted 2 (http://filmicgames.com/Downloads/GDC_2010/Uncharted2-Hdr-Lighting.pptx) from slide 142, and it sets some kind of white point (11.2), and I'm curious how do they set it... is it the same thing? To add can this be set automatically?
One more question about the downsampling, if I render it to a linear filtered texture then the resolution will be the same, right? So how do I get the 4 textures? (half-size, quater-size etc.)
I just thought that screen blending works better, because it preserves more details in the highlights
Yes this is true, but unfortunately the function is only valid if you're doing post-processing on "regular" 0-1 range images, not HDR images.
N.B. you could also choose to do your post-processing after tone-mapping, which is less physically correct but much cheaper. If you read about games using "screen" blending for their bloom, it means they are compositing their bloom after tone-mapping.
But I don't want to do 4 tonemapping passes[/quote]Where does '4' come from? You've got 1 bloom result and 1 regular scene that need to be combined.
I understand the threshold part, but how do I decide which parts to blur?[/quote]The threshold determines which parts of the image will 'bloom' (as they become black). You still blur these black areas, but later when blending them back into the image they have no effect.
obviously the threshold must be >1.0 because 0...1 is the usual range. what is an ideal value?[/quote]There's no such thing as a "usual" range in HDR. The whole scene might be from 100 to 1,000, with a few bright objects that are 1,000,000 and some dark objects that are 0.001. If you're basing it on real-life values, the human eye normally deals with brightness levels that differ by a factor of 10,000x.
You'll have to experiment to find what is a good threshold for your scene, depending on how bright your lights are, etc... it's an artistic choice.
One more question about the downsampling, if I render it to a linear filtered texture then the resolution will be the same, right?[/quote]Linear filtering is a property of the input texture sampler, not the output render target. To downsample by half, you render to a half-sized output render-target, while fetching from a full-sized input texture (with linear filtering on this input texture sampler).
Where does '4' come from? You've got 1 bloom result and 1 regular scene that need to be combined.[/quote]
I'm not sure, but I think I've read somewhere that I downsample 4 times, then blur each then combine. (or not exactly in this order) this way the blur radius will be much bigger.

The threshold determines which parts of the image will 'bloom' (as they become black). You still blur these black areas, but later when blending them back into the image they have no effect.[/quote]
ok thanks

There's no such thing as a "usual" range in HDR. The whole scene might be from 100 to 1,000, with a few bright objects that are 1,000,000 and some dark objects that are 0.001. If you're basing it on real-life values, the human eye normally deals with brightness levels that differ by a factor of 10,000x.
You'll have to experiment to find what is a good threshold for your scene, depending on how bright your lights are, etc... it's an artistic choice.[/quote]
yeah I've read about that too, I just thought it may make sense to decide on this. Is it a good idea to let the artist keyframe it (per scene) ?

Linear filtering is a property of the input texture sampler, not the output render target. To downsample by half, you render to a half-sized output render-target, while fetching from a full-sized input texture (with linear filtering on this input texture sampler).[/quote]
oh I got that wrong, I was thinking about the reading too, not the writing.

so just to make sure that I got downsampling right:
I should render the input texture to a half-res texture (using half res viewport), then blur that, then upsample and combine right?

I'm not sure, but I think I've read somewhere that I downsample 4 times, then blur each then combine. (or not exactly in this order) this way the blur radius will be much bigger.
Ok that makes sense now. Yeah there's a few ways you can do this:
e.g. if you only want one bloom result:
* Downsample (to half) -> blurH-> blurV-> downsample (to quarter)-> blurH-> blurV-> composite
* Downsample (to half) -> downsample (to quarter)-> blurH-> blurV-> blurH-> blurV-> blurH-> blurV-> composite
etc... each will give a different look, so experiment smile.png
So you can play with: number of times you downsample, number of times you blur each 'level', and the blur-radii used for each blur -- a lot of tweakables!
You can also try compositing together some of the different blur levels, before the final compositing with the scene -- I guess that's what you were thinking about with needing 4 tonemapping passes, if you wanted to screen-blend 4 'levels' of HDR bloom together (instead of just using the final 'level', which is what I was originally thinking of).

I should render the input texture to a half-res texture (using half res viewport), then blur that, then upsample and combine right?
Yep - and if you want another 'level' of bloom, you can render your half-res to a quarter-res, and so on.
There's no need to upsample before combining though -- it will give you the same result either way, so you may as well skip the upsampling step (and simply have the compositing shader read from the low-res bloom texture)
Is it a good idea to let the artist keyframe it (per scene) ?
It depends on the game. If it's a huge open world game with a huge variety of scenes, you may have to just pick 1 value, or try and make it dynamic (e.g. tie it to average screen luminance or something). If it's a game with more controlled scenes, e.g. a typical first-person shooter based in corridors, then you could let your artists/level designers control it.
Ok that makes sense now. Yeah there's a few ways you can do this:
e.g. if you only want one bloom result:
* Downsample (to half) -> blurH-> blurV-> downsample (to quarter)-> blurH-> blurV-> composite
* Downsample (to half) -> downsample (to quarter)-> blurH-> blurV-> blurH-> blurV-> blurH-> blurV-> composite
etc... each will give a different look, so experiment smile.png
So you can play with: number of times you downsample, number of times you blur each 'level', and the blur-radii used for each blur -- a lot of tweakables!
You can also try compositing together some of the different blur levels, before the final compositing with the scene -- I guess that's what you were thinking about with needing 4 tonemapping passes, if you wanted to screen-blend 4 'levels' of HDR bloom together (instead of just using the final 'level', which is what I was originally thinking of).[/quote]
I chose the first method as 4 blurs < 6 blurs in terms of rendering const. It looks great, so I guess I'll stick to it. I don't really want to overdo bloom. I think I'll play with this when I'll have more time. Yep that's what I was thinking about.

Yep - and if you want another 'level' of bloom, you can render your half-res to a quarter-res, and so on.
There's no need to upsample before combining though -- it will give you the same result either way, so you may as well skip the upsampling step (and simply have the compositing shader read from the low-res bloom texture)[/quote]
yeah I meant upsample as reading from lower res texture.

It depends on the game. If it's a huge open world game with a huge variety of scenes, you may have to just pick 1 value, or try and make it dynamic (e.g. tie it to average screen luminance or something). If it's a game with more controlled scenes, e.g. a typical first-person shooter based in corridors, then you could let your artists/level designers control it.[/quote]
ok, then I think I'll let it be configurable, and then the artists will decide if they want it or not.

thanks again this worked like charm :)
btw is there a way to reduce the number of passes?
now I do 7:
-use fbo #1 to downsample input texture to tex #1
-use fbo #2 to blur tex #1 horizontally to tex #2
-use fbo #1 to blur tex #2 vertically to tex #1
-use fbo #3 to downsample tex #1 to tex #3
-use fbo #4 to blur tex #2 horizontally to tex #4
-use fbo #3 to blur tex #4 vertically to tex #3
-use the input texture, tex #1 and tex #3 to combine them (and tonemap and gamma correct the result)

This topic is closed to new replies.

Advertisement