Hello, Hsluv!



This is my first post, and I want to talk about color theory, and all the different color models that are useful to generative artists.



I can only describe color as 'screwy'. It is weird. It isn't smooth. It is counter-intuitive in endless ways.



I'll explain a few of the tools that made my series 'Color, from Hierarchy' possible.

The Curse of RGB

We see color in Red, Green, and Blue. Our rods and cones have response curves which are centered on the Red, Green, and Blue wavelengths:

But physical colors involve photons which are not at the peak of the response curve. And since the curves overlap, some physical colors cannot be represented in separate Red, Green, and Blue intensity (particularly those wild blue butterflies). But many common colors can be, so computer monitors, and the most common color models represent color in RGB.

In the wild west of the old days, color values varied from monitor to monitor. 255 red and 128 green would be a different color on HP monitor vs some other brand. So in 1996 HP and Microsoft defined the sRGB color space.

By defining sRGB, the amount of Red, Green, and Blue and the limits of the color space were agreed upon. So R=255 isn't just a max value, it's an absolute, specifically defined color.

All the problems...

OK, so let's try to make some art with the sRGB gamut. Let's try to generate a bunch of bright, mostly saturated colors.



We'll trace the boundary of the gamut, starting with green, then on to red, then on to blue. Then throw them all on the page.

Hmm, a few issues. Blues are way too dark. Greens are super bright, and are really 'washed out'. Purples and reds look good, but are really under-represented.

Washed out greens?

This is caused by the boundary of the sRGB color space. Almost half of the boundary is green - which means our steps along the boundary result in a lot of very close greens. Blue is under-represented, and red is barely in the picture.

Darker blues?

And blue... it looks darker. Blue actually looks darker, even if it is pure red vs pure blue.

Non-linearity, Non-uniformity

As is the scaling between lightness values. sRGB defines an exponential scaling function (gamma 2.2). This prevents 'wash-out' for bright colors, and provides equal perceptual difference between gray values.

But this means you can't do math on an sRGB color! Averaging sRGB colors doesn't produce their average, it produces something. And try doing other kinds of math (adding colors, subtracting) - you will get very poor results.

Whenever you are working with RGB, try to find out if it is 'Linear sRGB', or just sRGB (which is non-linear).



Most image libraries produce sRGB. Any value in an OpenGL framebuffer will be linear (unless you specifically ask for non-linear).

Enter, HSL...

Hue, Saturation, Lightness is a better model. It represents color as:

- Hue - what angle on the boundary of the sRGB triangle,

- Saturation - which isn't shown on the color gamut. All desaturated colors are black/gray/white.

- Lightness - which is different than luminance, and luma, and everything else that sounds like lightness in color theory. It is lightness.

HSL can do a lot of neat things, like represent slightly desaturated 'pastel' colors, or generate palettes of dark, to medium, to bright colors along some hue. But it still has the washed out greens and darker blues issue. It is still picking colors off the sRGB color gamut!

Let's get perceptual...

HSL aligns a lot better with how we perceive color. We perceive lightness differences as texture. This is why pastel colors 'look' the same. They are all bright. Similar saturation.



Saturation, we really don't notice much. Variation in saturation can often look very strange, even confusing.



Let's try generating perceptually uniform colors.

That is better!

Made with HSLuv...

HSLuv is a perceptually uniform color model. Well, sort-of.



HSLuv has absolute hue uniformity. If you take any color, and add, say 10 degrees, the difference will always look the same. This means no washed out greens! It also means the reds show up, and the oranges, purples, etc.

HSLuv has absolute lightness. Any color (any hue/saturation) will have exactly that lightness.. This means our blues don't get so dark. We see dark blues, and dark oranges, and dark reds, and dark greens (because I added em!) The poor performance of HSL/RGB is really clear in the HSLuv Comparison page.

HSLuv hides all the crimes in the saturation value. It isn't geometrically possible to define an entirely uniform color space, but remember, we don't perceive saturation changes much? Yeah!

Credits

Thanks to Alexi Boronine for creating the HSLuv color model, and helping with the implementation in pretty much every popular language!

Also lots of thanks to Tyler Hobbs, who has a ton of useful posts on generative art.

Thanks to Wikipedia for the images, and content on color theory.