Hey guys,
So, i read along many articles about HDR rendering and i just want to summarize what i understood about the pipeline:
- Render the scene to a texture
- apply a bright-pass filter and downsample the texture to half its size
- apply a Gaussian blur in two passes(through x-Axis and Y-Axis)
- additively blend the scene texture with the gaussian blur
I tried to do those steps but apparently i went wrong somewhere.
I did check out the DX SDK sample about HDRLighting but i really didn't understand much of it.
Yes you missed the most important part of HDR rendering.
You forgot to calculate luminance and to tonemap the final render target.Check this article
Imo, HDRLighting example from DXSDK is really easy to follow and produces good results. Try reading it carefully.
So the pipeline should be:
- Render the scene to a texture
-Transform the texture into a luminance texture with a smaller size than the original texture (example 256x256).
-Downsample the luminance texture multiple times until size is 1x1.
- apply a bright-pass filter and downsample the texture to half its size (also uses the luminance value in some calculations)
- apply a Gaussian blur in two passes(through x-Axis and Y-Axis)
- additively blend the scene texture with the gaussian blur
-Tonemap the final scene texture with the 1x1 luminance value.
Yes you missed the most important part of HDR rendering.
You forgot to calculate luminance and to tonemap the final render target.Check this article
Imo, HDRLighting example from DXSDK is really easy to follow and produces good results. Try reading it carefully.
So the pipeline should be:
- Render the scene to a texture
-Transform the texture into a luminance texture with a smaller size than the original texture (example 256x256).
-Downsample the luminance texture multiple times until size is 1x1.
- apply a bright-pass filter and downsample the texture to half its size (also uses the luminance value in some calculations)
- apply a Gaussian blur in two passes(through x-Axis and Y-Axis)
- additively blend the scene texture with the gaussian blur
-Tonemap the final scene texture with the 1x1 luminance value.
In the past I have performed the tonemap before the bright-pass. This has a couple of advantages that I can think of:
the bright pass doesn't need a changing cut off, just set it to 1.
more stages of the pipe-line can be done in rgb8 buffers.
Yes you missed the most important part of HDR rendering.
You forgot to calculate luminance and to tonemap the final render target.Check this article
Imo, HDRLighting example from DXSDK is really easy to follow and produces good results. Try reading it carefully.
So the pipeline should be:
- Render the scene to a texture
-Transform the texture into a luminance texture with a smaller size than the original texture (example 256x256).
-Downsample the luminance texture multiple times until size is 1x1.
- apply a bright-pass filter and downsample the texture to half its size (also uses the luminance value in some calculations)
- apply a Gaussian blur in two passes(through x-Axis and Y-Axis)
- additively blend the scene texture with the gaussian blur
-Tonemap the final scene texture with the 1x1 luminance value.
thanks for the input. I just get too frustrated with DX SDK samples framework sometimes.
i did modify the FX file a bit to include what SimonJacoby method.
He used a const value for luminance as 2.0f.
But in your method, i have a few questions:
1- In step 1, What do you mean by a luminance texture(do you mean just a floating-point texture)?
2- In step 2, how do you do that??
3- In step 3, by a bright pass filter, do you mean something as simple as Color = Color - float3(0.3f,0.3f,0.3); and that is it or is there something more to it??
4- In the final step, by Tonemapping, do you mean just add the Vignette and the luminance code together or is there something a bit more fancy??
1- In step 1, What do you mean by a luminance texture(do you mean just a floating-point texture)?
2- In step 2, how do you do that??
3- In step 3, by a bright pass filter, do you mean something as simple as Color = Color - float3(0.3f,0.3f,0.3); and that is it or is there something more to it??
4- In the final step, by Tonemapping, do you mean just add the Vignette and the luminance code together or is there something a bit more fancy??
1. Luminance. So basically a single value per pixel that represents its brightness.
2. One method would be to first scale down the full texture to a fixed size (e.g 64x64), then draw the texture using a shader that averages 4 adjacent pixels to a single value until the result is a single pixel.
3. Basically yes. This is also the point at which I would recommend applying the exposure function. I would put the exposure and bright pass filter into the same function, writing the <=1 and >1 values to two separate buffers.
4. Not sure what vignette has to do with it. This is the stage where you accumulate the <1 buffer and the blurred >1 buffer for the final result.
I think it's important to keep in mind that HDR, bloom, tone mapping, and exposure are all very separate things (even if they are related). A lot of people just lump them into one process, and incorrectly assume that the way the DirectX or Nvidia samples are the only way to do it.
1. HDR just means you're using a range for lighting and rendering values that's wider than your displayable range.
2. Bloom is an effect meant to simulate glares that occur from bright objects. It doesn't require HDR, but you can do it better with HDR because you can determine which pixels are really really bright..
3. Exposure is just a scalar applied to your HDR values. Since you can't typically view really bright and really dark things simultaneously, adjusting exposure lets you pick whether you want to be able to see the bright stuff or the dark stuff. So if you're in a house you'd use a higher exposure, and then when you step outside to a bright sunny day you'd switch to a lower exposure.You can also implement "auto-exposure" if you want, where you try to choose a good exposure based on what's currently on the screen. Most of the samples use the Reinhard algorithm for this, which uses the geometric mean (log average) of pixel luminance combined with a key value.
4. Tone mapping is applying a curve to HDR pixel values, which is typically nonlinear. Tone mapping is basically like choosing film for a camera: certain tone mapping operators will let you display a wider range of brightnesses, and will do a better job of preserving contrast and detail. However it also affects the final "look", and consequently certain operators might be chosen due to artistic preference. Most of the samples use one of the Reinhard operators for this, and so do a lot of games. Reinhard tends to be good at preserving details, but can produce results that more washed out. "Filmic" operators (popularized by Naughty Dog) tend to preserve less detail, but give look that's more saturated with crushed blacks that's closer to the look movies usually go for.
In the past I have performed the tonemap before the bright-pass. This has a couple of advantages that I can think of:
the bright pass doesn't need a changing cut off, just set it to 1.
more stages of the pipe-line can be done in rgb8 buffers.
Am I missing something?
Usually you don't want to do that (if you can spare the performance) for the same reason you want to do any other post-process effect in HDR: if you don't do it in HDR, the bright spots won't be preserved and will become "washed out". For bloom this usually means all of your bloom blurs out to white, rather than to the actual color of the pixel.
3- In step 3, by a bright pass filter, do you mean something as simple as Color = Color - float3(0.3f,0.3f,0.3); and that is it or is there something more to it??
There's no real "right" way to do a threshold for bloom, since bloom is fundamentally a hack and not anything close to a real simulation of glare. So yeah, just subtracting some value (and clamping to 0 so that you don't get negative values) can work just fine.
all of this is really easy to understand, but from what i searched, the only good implementation of HDR with bloom effects and all the good stuff is DX SDK which i really have a hard time getting through with it. Is there any other source code that doesn't make me want to bang my head on the wall just for the sack of it??
And i have a few question on the HDR article in the D3DBOOK in the luminance transform section:
- In The implementation, why did he fetch it multiple times, shouldn't he calculate the luminance for EACH pixel one pixel at a time??
- Shouldn't he convert the pixels to CIE Yxy then calculate the luminance?? why did he do the opposite??
- And where is equation x??
- Is there a full implementation on how to get the average luminance based on the author's method??
- Render the scene to a texture
- apply a bright-pass filter and downsample the texture to half its size
- apply a Gaussian blur in two passes(through x-Axis and Y-Axis)
- additively blend the scene texture with the gaussian blur