There are a number of different colour spaces that I use in my art. Let's look at them, how they differ, and where they come into play. Colour spaces are ways of organizing and specifying colours. Different colour spaces have different ranges of representable colours, different numbers of colours that can be represented, and different utilities with respect to the technologies of displaying and manipulating colours.
First up is good old RGB. This is the default that SVG and CSS and HTML play with; all those hex numbers:
The problem with RGB is that it doesn't map particularly well to human perception and is non-linear, so manipulating colour values mathematically isn't foing to work very well.
Sure, if you increase the red value and hold everything the same, generally things look redder.
Can you really predict what
And what if you just want to make things lighter? Well, generally incrementing all the values will do that:
Unless you already maxed out on one of the components, or you hit the max value, so now you have non-linear effects and weird hue changes:
Maybe you just want to blend two colours: 30% this and 70% that. Sunshine on the water? What is
A better RGB space to be playing in for these kinds of operations is CIE-XYZ: it is a linear RGB colour space. The definition of the axes is based on a series of experiments with human perception. Converting from RGB and XYZ requires multiplying the appropriate matrix by the scaled (0 to 1) RGB values. Which matrix to use depends on the exact RGB space and reference white value.  shows some tables for the conversion. For example, for sRGB with reference white D65 the calculation is:
⎡ X ⎤ ⎡ 0.4124564 0.3575761 0.1804375 ⎤ ⎡ R ⎤ ⎢ Y ⎥ = ⎢ 0.2126729 0.7151522 0.0721750 ⎥ ⎢ G ⎥ ⎣ Z ⎦ ⎣ 0.0193339 0.1191920 0.9503041 ⎦ ⎣ B ⎦
Converting back to RGB means multiplying by the inverted matrix, and then rescaling the decimal RGB values back to the 0 to 255 range and rounding.
Now we we can interpolate colours with a little more confidence. The 30% to 70% blend of
Compare the interpolation using RGB coordinates:
We can now apply lighting models with more confidence as well. For example, the Lambert reflection model for diffuse lighting:
Id = L·N Il C
We can get a little more sophisticated here, taking into account surface albedo (brightness) by multiplying that in as well as the intensity of the source light. Wikipedia includes a nice set of albedos for a variety of surfaces.
Finally, the ambient light colour can be added in to the directional light being applied to the surface colouring.
For example, here we apply this lighting model to some pie slices, where the light source is to the bottom of the octagon. The lighting colour is
No ambient lighting, no albedo moderation (i.e. albedo=1.0):
White ambient lighting, no albedo moderation:
Red ambient lighting, no albedo modification:
Red ambient lighting, albedo of snow (0.5):
Red ambient lighting, albedo of sand (0.25):
HSL is a colour space defined in terms of hue, saturation, and luminance. Hue is given as an angle (0 to 360); saturation and luminance are percentage ranges. The idea is that it is more intuitive to work with: want to darken a colour? Just adjust the luminance coordinate. Want a range of colours with the same lightness? Just turn the hue knob but keep the rest the same. The problem with it (see  for more details) is that it doesn't actually match human colour perception with respect to lightness, so I use a variation called HSLuv, which is something of a cross between HSL and CIELUV LCh. The colour range is a little murkier, but you can bank on the perceptual uniformity of a given lightness value across different hues.
HSLuv can be handy when you just want to add some shadowing: just tweak the luminance coordinate, or when you want to make a palette of colours with the same brightness or make a colour gradient that reduces in brightness.
A palette of random colours, shifted to all have the same luminance (50%):
A palette based on a random colour, with luminance values evenly divided:
Using HSL luminance tweaks can be a quick way of getting some shading messing about with lighting models: here I just adjust the luminance based on the angle bisecting the first point of the triangle, for a nice textured effect.