Dev Blog

Dev-Blog 128: Color Grading: Another cool rendering trick

09/03/2014

devblog_header03

Welcome back, followers of the fearsome!

On Monday we showed our game off at the Seattle Indie Expo, and it was super fun to meet a bunch of Seattle indie developers, as well as meeting all the people checking out our game! We’ve gotten a lot of feedback, and we’re going to be incorporating all of that into our game to make it even better. Here’s a quick pic I snapped of Caley and Jesse and our setup.

photo

Alright, now to the tech stuff. This week I put in something I’ve been wanting to put in the game for a long time: Color grading. Color grading isn’t new, and I am definitely not claiming this is something unique. However, it is very cool, and I wish more people knew about it. Every artist I show this too reacts as if their mind is blown, and every programming is like ‘yea, I knew that’. There have been many games that are using this already, like The Witness, and a lot of AAA games. There’s a great description on how to use it on Code Laboratorium, and this week I’ll try to give you my version here as well.

The basic idea of color grading is to map every possible color to another (color graded) color. In other words, you basically want to be able to call a function in the form of:

Color GetColorGradedColor(Color rawColor)

 

One way to map each possible color to each other color is to use a huge array. If we’re using 8 bits per color channel, that means 256 steps per color channel, so we’d need an array of 256 * 256 * 256 different mapped colors. That’s a lot of memory, and a lot of cache misses to deal with! Luckily there is an easier and faster way.

Imagine that there was a way to store all these mapped colors in a cube. the X axis could be the Red value, the Y axis the Green value, and the Z axis the Blue value. Now, if we had a color value, we could just use the RGB value as the XYZ coordinate in the cube, and get the color graded color. Now also imagine that the color grading is pretty smooth, and neighboring colors in the cube are very close together. That means we could just take a lower resolution cube, and interpolate for any colors in between.

I’ve just described the exact behaviors of a 3d-texture. For my implementation I’m using a 3d texture of 16x16x16 pixels as my color grading look-up texture (also called a LUT). I’ll get into how to create these textures later, but for now, imagine we’ve got a color grading 3d texture completely set up. What actually needs to happen to get the screen to show up completely color graded? It’s simple: Render the entire screen to a render target, then render this render target to the screen using the color grading pixelshader.

The color grading pixel shader is very simple (this is GLSL, but it should be pretty easy to convert this to HLSL):

uniform sampler2D TextureMap;
uniform sampler3D ColorGradingLUT;
varying vec2 f_texCoord;
const float lutSize = 16.0;
const vec3 scale = vec3((lutSize - 1.0) / lutSize);
const vec3 offset = vec3(1.0 / (2.0 * lutSize));
void main()
{
 vec4 rawColor = texture2D(TextureMap, f_texCoord);
 gl_FragColor = texture3D(ColorGradingLUT, scale * rawColor.xyz + offset);
}

Note that the alpha of the color isn’t used in this shader, as the screen is drawn without Alpha blending. The scale and offset parameters are there because of the way textures are interpolated. There’s a great explanation in GPU Gems about this.

Alright, so now that we’re able to combine an input texture (from your render target) and a 3d color grading look up texture into a final color graded output image, we need to start worrying about how to create these color grading textures. (This is the part that usually blows the artists mind). The basic process is this:

1) Create a screenshot of your game, and insert the color cube information to the image.

2) Load the screenshot into photoshop, aperture, paint .net, gimp, or whatever color correction application you prefer, and change the colors of the image using whatever plugin you want.

3) Save the screenshot once you’re done

4) Load the screenshot back into your tool, and extract the color cube information.

That’s it! Pretty simple, right? Here it is in pictures:

editor

This is the interface we have in the editor for generating the color grading textures. The button ‘Generate Screenshot’ will create a screenshot of the game, attach the color cube information at the top, and save it out to disk as a png (you’ll want to use a loss-less image format, don’t use jpg!). This is the image it generated:

color grading test

 

Notice the color grading information in the top left. To generate this screenshot, all existing color correction and bloom in the engine was turned off, so the image is as close to the raw data as you can get.

Now, I’ve loaded this image into paint.net, and changed the color, then saved it out to this image:

color grading test after

 

I didn’t change these colors to look particularly good, just enough to show a difference between the incoming and outgoing image. Next, this image is loaded back into the editor, which extracts the colors from the image, and puts them in a 3d texture to use as the color grading LUT:

editor after

That’s all there is to it! I’ve added a few extra things like being able to blend between color gradings within a level, which creates really cool mood changes when you walk into a cave or when you get into a village. Here’s a few more extreme color gradings:

color grading collage

Alright, that’s it, hope it was helpful. Keep color grading them games!

Nick_avatar64-Nick

Twitter: Nick: @nickwaanders Jesse: @jouste Caley: @caleycharchuk SlickEntertainment: @SlickEntInc

Google+: Nick: +NickWaanders Jesse: +JesseTurner Caley: +CaleyCharchuk

Facebook: https://www.facebook.com/SlickEntertainmentInc

Posted by: Under: Tech,Vikingsquad

Follow us!

titlebutton_twitter titlebutton_facebook titlebutton_youtube titlebutton_twitch titlebutton_spreadshirt

Join our mailing list!

/ /

Dev Blog

January 20 2017

I almost can’t believe it: Slick Entertainment is a decade old! In the last 10 years we’ve made a bunch of great games, and I am super proud of what we’ve achieved with our small team: 4 fun games, custom C++ engine on 6 different platforms, 3 games feature online multiplayer, all hand-drawn art for […]