Color correction as a post-processing effect

A forum to store posts deemed exceptionally wise and useful
Post Reply
Radikalizm
Posts: 1215
Joined: Tue Jan 09, 2007 7:03 pm
Location: Leuven, Belgium

Color correction as a post-processing effect

Post by Radikalizm »

Some time ago I got a message from someone on these boards asking me to do a small guide on how to do real-time color correction as a rendering post-process. To be honest, I had forgotten all about it, until I took a look at my color grading implementation just a few days ago to make some alterations.

So here it is:
Color correction as a post-processing effect
Note: I want to point out that this is a guide, not a tutorial. I will be explaining the process, but I will not provide a full and working implementation. Pseudocode will be provided where needed.
The technique described here has been created using both personal research and various online resources. Since it's been a long time since I've first implemented this I can't really give any sources.

Description
The technique described in this guide allows you to do full-screen color correction as a post-processing effect by remapping parts of your final color palette using a shader. The technique can be implemented in about any rendering pipeline and is non-intrusive (ie. it does not affect any other parts of the rendering pipeline). Remapping of colors can be done easily and intuitively in popular image editing applications like Adobe Photoshop or Gimp.


Assumptions
Throughout the guide I will assume that the people interested in using this technique are already familiar with how post-processing works and how a post-processing framework can be implemented. Therefore I will not be going into setting up post-processing effects, how to set up screen quads, shaders, etc.

The technique:
The technique contains 2 passes: an offline remapping pass in Adobe Photoshop, Gimp or any other image editing suite allowing per-channel curve editing and importing/exporting of curve data, and an online color correction pass which will use the data created in your image editing software to alter your final scene output.

1. Remapping your colors
In this pass we will be taking an image of your original scene, and we will be correcting the colors to a desired result using the curves tool of your preferred image editing suite.
So, first of all we will require an image. This can be a simple screen capture of your scene output, but in theory could be any image you want (this will not guarantee good results, and will probably end up looking horrible). For this guide I will be using a debug-render made with my personal engine:
Image
A normal render of Crytek's sponza atrium scene, please forgive the few material quirks found in the image

As you can see, the image looks rather dull and grey, which makes it a perfect candidate for color correction.
To apply color correction to this image we will be using a curve editor. In Adobe Photoshop it can be found in Image>Adjustments>Curves..., in Gimp it can be found in Colors>Curves...
Image
Curve editors in Photoshop and Gimp respectively

You can alter individual curves for color channels by using the drop-down box marked 'Channel:'. You can play around with the curves for each channel until you get a good result. It can take some practice to get good results, but just hang in there. Photoshop also allows you to easily remap your black, mid and white tones respectively using the 3 eyedropper tools seen below the curve graph.
After playing with the curve controls I got this result:
Image
The source image subtly remapped

Note: It is important not to close the curve editor window when you're happy with the result. We will be exporting the curve data to a file, and closing and re-opening the window will apply the alterations to the source images and you won't be able to get to the curve data anymore.

We will now be exporting our curve data to a file, to do this click the icon marked in below image and select Save preset... for Photoshop, or Export settings to file... for Gimp. Save the curves file to a place where you can find it again easily, because we will be needing it immediately.

Image
The icons are marked with a red circle

Now, we will need to create a new image, we need a 1-dimensional image as a matter of fact, so we will be creating it with a width of 256 and a height of 1. (we use a width of 256 since an 8 bit integer color channel can hold values ranging from 0 to 255)
Once this image is created we will apply a black to white linear gradient on it from left to right. It is important that the gradient is evenly spread for the color correction to work properly.
Now that our gradient is in place we open the curve editor once again, click the same icons as marked above and choose Load preset... for Photoshop, or Import settings from file... in Gimp.
Open the curves file we exported earlier and apply it to our gradient image. You should now have an image looking similar to this (colors will vary based on your remapping):

Image

This image will be used as an input texture in our second pass, so save it somewhere where you can find it.

2. Color correction
On to the technical part. This part will be quite a bit shorter than the previous part since the technique is actually rather simple.

I'm gonna go ahead and assume you have a post-processing framework set up, and that you now only require a pixel shader to get it running.

In the previous pass we created a 1D texture holding our color data for remapping our scene, we will use this texture together with our normal scene output as input for our post-processing effect
The process of applying our remapped data is quite straight forward, for each pixel we do the following:
1. Sample the color of our original scene output
2. Sample our curve texture once for each color channel in our original scene output (except alpha), using the value of said channel as the X-coordinate of our UV-coordinates. Since we're working with a 1D texture, we keep our Y-coordinate at a constant 0.5 so we sample the middle of our pixel
3. Store each sampled channel into a new color value, and optionally interpolate with our original scene output using a strength factor (this way you can tune the effect to your liking)

Pseudo-code:

Code: Select all

 
Texture curveTexture;
Texture sceneOutput;
float Strength; // This will determine how much the effect should contribute to the final scene
 
For each pixel:
    Color sceneColor = sample(sceneOutput, uv); // uv are the regular uv coordinates provided by your screen quad
 
    // Look up our remapped colors using the curve texture
    Color remappedColor;
    remappedColor.r = sample(curveTexture, float2(sceneColor.r, 0.5)).r;
    remappedColor.g = sample(curveTexture, float2(sceneColor.g, 0.5)).g;
    remappedColor.b = sample(curveTexture, float2(sceneColor.b, 0.5)).b;
 
    // Interpolate the remapped scene with the original scene
    Color outputColor = remappedColor * Strength + (1.0 - Strength) * sceneColor;
 
And that's pretty much all there is to it
Here's the final result:
Image
The final output

And here's a render of the same scene with different curve settings:
Image

Of course, the result isn't identical to the one in the image editing software since we're using a simplified approach. You'll be able to take this error margin into account after a while and you'll be able to produce good looking corrected scenes

Possible improvements
To keep this guide simple I haven't talked about gamma correction in the technique or about gamma corrected rendering pipelines. Using a corrected rendering pipeline together with a gamma corrected version of this technique will give you results which are much closer to the ones created in your image editing software. If you don't know what gamma correction is or how to implement it, here's a good read: http://filmicgames.com/archives/299

Conclusion
We've seen a simple and straight-forward way of doing color correction in real-time. I hope this guide can be of help to those interested in implementing such a system.
Last edited by Radikalizm on Mon Jan 02, 2012 6:18 pm, edited 4 times in total.
Escen
Competition winner
Posts: 167
Joined: Sun Jul 19, 2009 11:27 am
Location: the Netherlands
Contact:

Re: Color correction as a post-processing effect

Post by Escen »

This is funny, I was just getting to this subject....
Thanks Radikalizm.
Radikalizm
Posts: 1215
Joined: Tue Jan 09, 2007 7:03 pm
Location: Leuven, Belgium

Re: Color correction as a post-processing effect

Post by Radikalizm »

Escen wrote:This is funny, I was just getting to this subject....
Thanks Radikalizm.
No problem, glad I could help
Escen
Competition winner
Posts: 167
Joined: Sun Jul 19, 2009 11:27 am
Location: the Netherlands
Contact:

Re: Color correction as a post-processing effect

Post by Escen »

Didn't follow your description exactly, but playing with a 'color correction' is really worth a try.
This shader change contrast and applies a color saturation.

Image

Image
Radikalizm
Posts: 1215
Joined: Tue Jan 09, 2007 7:03 pm
Location: Leuven, Belgium

Re: Color correction as a post-processing effect

Post by Radikalizm »

Yes, it's really amazing what even a subtle correction can do, it can completely make or break a render
Virion
Competition winner
Posts: 2148
Joined: Mon Dec 18, 2006 5:04 am

Re: Color correction as a post-processing effect

Post by Virion »

nicely written guide. should put this up onto wiki.
ACE247
Posts: 704
Joined: Tue Mar 16, 2010 12:31 am

Re: Color correction as a post-processing effect

Post by ACE247 »

Great guide Rad! I unfortunately only found this now...
I'll play around with this and try combining several render passes to make material specific color corrections, or even achieve some cool new effects.
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: Color correction as a post-processing effect

Post by Mel »

Awesome sample :)

Actually some color correction is the key for stunning renderings, because they give uniformity to the final image.

I think another improvement is to be able to interpolate color tables to create smooth color correction transitions.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Post Reply