Recently, I started to think of which order should post-process effects should run. Its an interesting problem since its a often a matter of balancing performance, quality and correctness.
The usual post-process effects that you would find in a modern game are, Anti-Aliasing Resolve, Tone-Mapping, Bloom, Depth Of Field, Motion Blur and Color Correction.
- The AA Resolve is the process of downsampling a high-res image (rendered usually using the hardware Multi-Sampled Anti-Aliasing support) to an output resolution. It give a nice anti-aliased image. We could replace that pass with other Anti-Aliased post-process such as the recent MLAA technique.
- The Tone-Mapping is the process of taking a high dynamic range (HDR) image to a displayable range (LDR).
- Bloom is a process of blurring an image, and adding the result back on top of the source image. This gives a nice effect of light-bleeding.
- Depth Of Field is a process of having an object in focus sharp, and objects out of focus blurry.
- Motion Blur is a process of blurring areas of the screen that are in motion.
- Color Correction is a process of changing the color palette of your image. It usually also includes a brightness/contrast pass.
Typically, on the current platforms (XBox 360 and Ps3) you would have a game render frame that would look like the following:
1- Scene Opaque (in MSAA)
2- AA Resolve
3- Scene Transparency
4- Bloom
5- Tone-Mapping
6- Depth Of Field
7- Motion-Blur
8- Color Correction
I’ve integrated the position of the Scene rendering just to give us a better idea of how it all fits together within the frame.
But this is not exactly correct. Depth Of Field and Motion-Blur should be done in HDR, not LDR, so pre ToneMapping. Also, since Bloom simulates light bleeding, Depth Of Field and Motion-Blur should also be done pre Bloom. This will give a nice glow effects around moving and out-of-focus lights.
Color-Correction needs to be done in LDR. This because color-correction is an artistic tweak over the rendered image. We can easily represent LDR colors, harder to do so with HDR colors. Also, color should be preserved post-color correction. If the color correction was to be done in HDR (pre Tone-Mapping) colors would change.
There is the remaining question of the Anti-Aliasing, and the order of Depth Of Field with Motion-Blur. Lets remind ourselves of the new proper order of post-processing effects:
1- Opaque
2- AA Resolve
3- Transparency
4- Depth Of Field
5- Motion Blur
6- Bloom
7- Tone-Mapping
8- Color-Correction
For anti-aliasing to look the best, you would want to put it in the very last stage or your rendering pipeline, so all way after Color-Correction: You would get this new full-screen effect pipeline:
1- Opaque
2- Transparency
3- Depth Of Field
4- Motion Blur
5- Bloom
6- Tone-Mapping
7- Color-Correction
8- AA Resolve
This requires to have all your other effects to be done at full MSAA resolution, which can be costly. On current console hardware, this is almost impossible to do without sacrificing some big quality for performance, or just frame-rate (which ultimately results in a quality loss).
Now when it comes to Motion-Blur and Depth Of Field, ideally, you would want those two effects to be combined into one. Or you want the 2nd effect, to have information on how the 1st effect happen, to make sure the effect is more correct overall. Its a similar issue that you have between Bloom and Motion-Blur. You want the blurry pixels resulting of the Depth of Field to be Motion Blurred properly, and you want also the blurry pixels caused by motion blur to be properly blurred out depending on their depth (knowing even that their depth have changed during motion), so Depth of Field needs to be temporal, like Motion-Blur.
In the world of video-games, this is almost impossible to do with current technologies, so I guess you would have to choose what is the best for your game. Some games choose to even only do one or the other: They would for example, at very slow movements, only have Depth of Field, and at fast movement have only Motion-Blur.
To finish, I’m sorry I don’t have a demo, or a set of screen-shots to illustrate my post. This is all very theoretical. Some are conclusions that came from my experience in implementing those effects in God Of War 3 and Mercenaries 2. I hope to be able to illustrate this, and deliver a demo very soon, but I hope this will help you think a little bit more about the problem, and how to resolve it.
Nicolas Bécavin wrote:
Nice one. We came out we pretty much the same layout as your final one. Except that we are technically doing bloom before DOF as we are using the same blurred target for both effect.
And a question for you. Where is gamma correction in your pipeline ? (I mean sRGBlinear) ?
Link | June 23rd, 2011 at 12:25 am
esmolikowski wrote:
Gamma correction is part of the lighting pass. We store our textures in gamma space (Diffuse, Specular, AO) and the HW loads them in linear for our lighting.
Our final framebuffer is linear, although we could store it in gamma space for the tonemapping (I think some projects do that). Not sure if Depth Of Field or Motion Blur should be done in linear or gamma space.
Link | June 24th, 2011 at 12:24 am
esmolikowski wrote:
@Nicolas: For us every effect computes all the data it needs. So Depth Of Field will compute its own blur, and Bloom too. While performance might not be as high as we could make it, it gives a significant quality improvement since we get the flexibility to cater the blur for each effect.
Bloom will do a Gaussian Blur, and will also remove the “dark” colors through a threshold. Depth Of Field would do just a box filter blur, or can also add some Bokeh during its blur, and wont deal with the threshold of color.
I used to do like you, but sometimes, spending an extra 0.5/1m in your special data catering can significantly improve quality.
Link | June 24th, 2011 at 12:43 am