Jump to content
  • Advertisement
Sign in to follow this  
  • entries
  • comments
  • views

Fun hacks to fiddle with colour

Sign in to follow this  


Download the RenderMonkey workshop
HDR source image not included, it's too big - you can download several from Paul Debevec's site, then convert them to DDS with the texture tool in the DX SDK

Creating the shader
This sort of effect is easiest to do as a post-process. You only need to do the calculations once per pixel. So, we start off by rendering our OMFG HDRTASTIC SCENE (TM) to a texture.

float3 clrIn = tex2D(Texture0, texCoord).rgb;

Now to adjust the saturation. Real cameras (and eyes!) don't just take in red light, and make red, etc.; each pigment responds to different frequencies of light based on a nice smooth response curve. We can fake this by simply multiplying the input colour's R, G, and B components by constants and adding them together for each output channel. To make things easier, instead of specifying 3 complete colours, we're going to just use two constants, A and B, to specify how quickly the response falls off from the 'center' frequency. If A and B are 0, the output will be the same as the input; if they are 1, the output will be greyscale.
float3 responseR = float3( 1.0, b, a);
float3 responseG = float3( b, 1.0, b);
float3 responseB = float3( a, b, 1.0);

clr.r = dot(clrIn, responseR);
clr.g = dot(clrIn, responseG);
clr.b = dot(clrIn, responseB);

Once we have this result, we can multiply the result by another colour to give the whole scene a slight tint (but don't go overboard - your entire scene probably does not need to be bright pink). After that, we do something fancy to get the exposure + gamma in a nice range (exp is used here), and output the final result.

clr = 1 - exp(-exposure * tint.rgb * clr);

return float4(clr.r, clr.g, clr.b, 1);

HDR results
First, the original HDR input image with A=B=0, tint=1,1,1, and exposure = 1: (tonemapped so we can see it on an LDR monitor, but basically, this is what the original looks like)

Setting A=0.4 and B=0.2 takes away some of the colour by mixing the red, green, and blue values together. Setting the tint to 1,0.8,0.7 or so gives a nice sepia look. Also, if we adjust the values somewhat and give it a bluish tint, we can get a night-time effect (although the overly bright sky gives it away).

On the other hand, if we use negative values (here, A=-0.1 and B =-0.2), the colours become slightly richer (bump the exposure up slightly to compensate for the decreased brightness). However, exaggerating the effect can give unpleasant results - if you want a major increase in colour saturation, you will probably need to resort to a more sophisticated technique.

LDR results
But wait, you cry! Unlike most, I know that "HDR" is not another name for "massively overdone bloom", and I've realized that my game looks just fine without it! Well, guess what - it works just as well with ordinary images, as long as you don't try to push it too far. We only need to slightly change the end of our shader:

clr = exposure * tint.rgb * clr;

return float4(clr.r, clr.g, clr.b, 1);

Top: Original screenshot (from CounterStrike: Source); sepia; Bottom: increased saturation; night.

These images have more extreme settings as well as some gamma adjustment.
Sign in to follow this  


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!