Latest ArticlesEngine Architecture #1
Static Shadows #1
Paint on Mesh
A Tale of the Internet
High Dynamic Range Apr 12, 2006
What is High Dynamic Range?Usually 3D programs render to a frame buffer with 24-bit RGB color, 8-bits for each color channel. (32-bit if it includes an alpha channel.) With High Dynamic Range techniques, the render buffer instead uses 16 bits per color channel, allowing a much greater range of unique values. 2^16 = 65536 possible values per channel with HDR, instead of 2^8 = 256. Also note that HDR uses floating-point values, so they have an exponential component.
To use HDR, instead of rendering to the frame buffer, we create a render target texture using HDR color depth, and render the world to this texture. Then we render this texture to the frame buffer for display. Now, imagine adding just this to an existing engine. The output would look exactly the same! Hardly that exciting.
Just increasing the value range isn't enough, we have to use this increased range somehow. Your monitor or TV screen is limited to 8-bits per channel, so the final image you see will still be a standard 24-bit RGB color image. What HDR does is allow some cool post-processing effects, like Exposure control and Bloom/Glow.
It is possible that the added range can be immediately useful with blending such as with transparencies and reflections that reduce the intensity, since values above 1 might be reduced to different values in the 0-1 range.
How to Use HDRSome things need to be added to an engine for best use of HDR. I added a brightness slider for lights, to allow them to take advantage of color values above 1.0. I also added sliders to control HDR effects and mappings, things like exposure, glow level, and glow threshold. Finally there are HDR texture formats, usually unneeded, but useful for textures that include bright light like a skybox. Making sure game levels look fine with both HDR on or off is an added nuisance.
I have a couple of personal preferences I want to mention. I think there are a couple of areas where HDR effects might be overused. One is having bright light blowing out too much of the scene. Pictures taken with cameras can easily get lost in bloom, (and I try to avoid this in my own pictures,) but the human eye is more resistant. I do think the high brightness can make a good temporary effect, either for a flash of light, or with automatic exposure adjustments to allow you to soon adjust and see the scene more clearly. The other is that I usually don't like setting the bloom/glow threshold so low that everything glows a bit.
ExposureWe can adjust the mapping of the 16-bit values to the 8-bit output, to allow a wider range values to be display within the visible [0,1] range. Because we have extra data, we can also simulate exposure by adjusting the mapping function to scale brighter or darker values into the main part of the visible 8-bit range.
An Automatic-Exposure effect is possible by computing the average brightness of the buffer. This can be done by rendering back and forth between buffers to smaller sized target areas with texture-blending on, until everything is blended into a single pixel, then reading this pixel's value and using it to adjust exposure. You don't need to start with the whole buffer, you can use a good-sized rectangle from the center ignoring the edges.
Bloom/GlowThis is a very commonly used HDR post-processing effect. Where the color in the buffer is above a certain threshold, it will extend to and brighten nearby pixels. (You can create similar effects without HDR though.)
HDR makes it possible to create bloom using a standard Gaussian blur. You want the bright colors to blend over the dark colors only, not the other way around. Since the HDR range extends far above 1 and is later mapped down to a linear range [0,1] this happens naturally. The blur is created in a separate HDR buffer usually of a lower resolution than the render buffer. Then in the final step it's blended with the render buffer based on brightness and mapped/written to the frame buffer.