High Dynamic Range Rendering
First, there's a lot of confusion about what HDR actually is, and I want to clear it up. HDR does not automatically mean "iris adjustment" although the two often go together. HDR, at its simplest, means that colors won't get washed out during the rendering pipeline.
Game graphics inputs are 8-bit (per channel textures). The output is 8-bit (unless you have a 10-bit monitor). So if we only perform one rendering step, it is impossible to lose color resolution. Even if our lighting step brightens the light beyond the brightest color possible (255,255,255), it doesn't matter, because your monitor can't display the difference anyways.
However, if we have post-processing effects that darken the screen again, we CAN lose color resolution. I made an extreme example to showcase this idea. Here's my "brighten" post-processing effect, which increases the brightness of each pixel by four times:
#version 400 uniform sampler2D texture1; uniform bool isbackbuffer; uniform vec2 buffersize; out vec4 fragData0; void main() { vec2 tcoord = vec2(gl_FragCoord.xy/buffersize); if (isbackbuffer) tcoord.y = 1.0 - tcoord.y; vec4 texcolor = texture(texture1, tcoord); fragData0 = texcolor * 4.0; }
And here's my "darken" post-processing effect, which reverses this effect:
#version 400 uniform sampler2D texture1; uniform bool isbackbuffer; uniform vec2 buffersize; out vec4 fragData0; void main() { vec2 tcoord = vec2(gl_FragCoord.xy/buffersize); if (isbackbuffer) tcoord.y = 1.0 - tcoord.y; vec4 texcolor = texture(texture1, tcoord); fragData0 = texcolor / 4.0; }
Here is a simple scene with no post-processing effect applied:
If I place the brighten effect first, and follow it by the darken effect, the color will get clamped at the max value of (255,255,255) and then darkened, resulting in a washed out image:
If we use the darken effect first, and then follow up with the brighten effect, the color gets compressed and inaccurate. I had to crank the multiplier up to 60 to show the effect, but you get the idea.
HDR solves this problem by using higher-accuracy float buffers in the middle stage processing. In this example, it results in an image that is identical to what we could see if neither of these post-processing effects were in use:
In real world usage, it can be used to prevent post-processing effects from washing out your colors. However, unless you are using a post-processing effect that darkens the whole screen, even bright pixels, you're not going to see any difference. This is where the iris adjustment shader comes in. Most effects actually brighten the screen, but iris adjustment is one that uniformly dims the screen, regardless of pixel brightness. That's why this effect is closely associated with HDR.
Texture Formats
When rendering to floating-point textures, you might think that would increase memory usage a lot. We do have the option to render to 32-bit floating point RGBA textures. However, we also have half-float 16-bit textures, which will probably produce the same results in most cases. But wait, we don't actually need the alpha channel at this stage in the rendering pipeline, and there's a compressed float format available called GL_R11F_G11F_B10F. This eliminates the alpha channel and uses the extra bits to add precision to the color, packing a floating point RGB image into the same space as an 8-bit RGBA image. I just tested, and it even works on Intel integrated graphics! It is likely that in the future this will be the default setting, and HDR will always be enabled by default, at no cost. To start with I am going to make it an explicit option until we figure out how well it works on all hardware, and whether we need a higher-resolution RGBA16F format.
You will have access to this feature in the next beta build.
- 6
5 Comments
Recommended Comments