Fun hacks to fiddle with colour

Published December 16, 2005
Advertisement
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.
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement