News: Discontinued. goto details;
View the full online documentation and check out the demos.
Make It Colorful is a collection of color types for a variety of color spaces beyond just RGB. Benefits of using Make It Colorful include:
- More natural HSV color space usage than is provided by UnityEngine.Color.
- Hue-based color spaces avoid the muddy gray mid-sections of gradients and animations common when interpolating between two RGB colors.
- Luma-based color spaces avoid the bands or flashes of inconsistent brightness in gradients and animations common when interpolating between two HSV colors.
- Working with apparent brightness as perceived by humans is simple, all the math has been taken care of for you.
- The CMYK color space is useful for anyone who is more comfortable working with subtractive color spaces from the printing industry.
Make It Random provides full featured and interoperable color space types based on combinations of hue, saturation/chroma, and value/lightness/luma, plus ink-style subtractive components:
- HSV | HSL | HSY
- HCV | HCL | HCY
- CMY | CMYK
Color operations include:
- Conversions between all color types
- Linear interpolation within any color space
- Color space boundary validation
- Representation uniqueness checks
For even more fun with colors, check out Make It Random, which includes Make It Colorful, along with utilities to generate random colors and plenty more.
Full source code is included.
For inquiries or suggestions, feel free to use this thread, or contact me on Twitter @AndyGainey or email againey@experilous.com.
The Details
Hue
- The six hue-based color spaces all use the same cyclic hue component.
- Interpolation of hue avoids muddy gray intermediate colors.
- Hue interpolation can favor the shortest direction, or can be forced to follow the color wheel in the forward or reverse direction.
- Hue values outside the standard range from 0 to 1 will still behave well and convert to RGB properly.
Saturation and Chroma
- Saturation results in simple-to-use cylindrical color spaces.
- Chroma produces more complex bi-conic color spaces, but with the benefit of more predictable visual behavior.
- Conversions between saturation and chroma are just a single cast away.
- Chroma interpolation will effectively blend between vividness levels.
Value, Lightness, and Luma
- Value offers a fast though somewhat simplistic measure of luminance.
- Lightness better distinguishes the luminance differences between pale colors, at the expense of slightly more complex computations under the hood.
- Luma represents human-calibrated apparent brightness, automatically handling the differences in luminance of various hues.
- Luma interpolation will effectively blend between apparent luminance levels.
Subtractive Color Spaces
- CMY offers the inverse of RGB, with increasing values of cyan, magenta, and yellow “ink” subtracting color from a pure white base.
- CMYK includes the key component for subtracting black/gray directly.
- Maximum values for key automatically calculated upon conversion from any other color space.
Color Space Boundary Validation
- Easy checks to validate if a color can be directly converted to a non-HDR RGB, with all components between 0 and 1.
- If not within the RGB-safe range of the color space, easily get the nearest color that is.
- Additional utility functions to find the limits of individual color components for non-cylindrical chroma-based color spaces.
Canonical and Equivalent Colors
- For colors with more than one representation, check if the color is in the canonical representation.
- Get the canonical representation if a color is currently in a non-standard form.
- Useful for comparing two colors for equivalence, even if their literal component values differ.
Conversions
- Implicit conversions to and from
UnityEngine.Color. - Explicit conversions between any other pair of color spaces.
- Create colors in one color space using individual component values from any other explicitly indicated color space.
Samples
Hue
If you want to just pull vibrant colors directly from the one-dimensional color wheel, it’s as simple as constructing an instance of ColorHSV with a hue in the range [0, 1) and a saturation and value both equal to 1.
Color c = new ColorHSV(0.37823f, 1, 1);
Inversely, if you just want to figure out the hue of a color and ignore everything else, simply convert to any of the hue-based color spaces and pull its hue field.
float hue = ((ColorHSV)color).h;
Luma
Like with hue, if you are most interested in the apparent luminance of a color, you can find out what it is by converting to one of the luma-based color spaces and pulling the luma field.
float luma = ((ColorHCY)color).l;
If you want to force one color to have a matching apparent luminance of another color, you can figure out the hue and chroma of the first color, the luma of the second color, and then construct a third color using those three values. The chroma may need to be adjusted for it to be convertible to a valid RGB color, so the color space bound functions can come in handy here.
var hcy = (ColorHCY)firstColor;
hcy.y = ((ColorHCY)secondColor).y;
hcy.c = Mathf.Min(hcy.c, ColorHCY.GetMaxChroma(hcy.h, hcy.y));
var rgb = (Color)hcy;
If you’d rather less then potential change in chroma in case of an out-of-range color, you can use GetNearestValid() instead. This will adjust both chroma and luma if necessary, compromising between the two.
var hcy = (ColorHCY)firstColor;
hcy.y = ((ColorHCY)secondColor).y;
var rgb = (Color)hcy.GetNearestValid();
K-Lock
Another useful method of forcing colors to match on a single component value is known as “K-lock”, which is forcing the key component of the the CMYK color space to a constant value while the other components are free to change. This is as easy to implement as converting to CMYK, setting the key, and converting back.
var cmyk = (ColorCMYK)color;
cmyk.k = fixedKey;
color = cmyk;
Animated Color Blending
When blending from one color to another during an animation, you may want to use a different color space to do the blend, especially if you’re encountering unwanted muddy greys in the middle of the blend, or noticing uneven changes in apparent luminance. You can achieve this by usig the following during each frame of animation (as an example, this is applied to a sprite renderer):
spriteRenderer.color = ColorHCY.Lerp(startColor, finalColor, animTime / animDuration);
Quick Links
- Asset Store
- Documentation
- Demos
- Twitter: @AndyGainey
- Email: againey@experilous.com