1. Help us improve the editor usability and artist workflows. Join our discussion to provide your feedback.
    Dismiss Notice
  2. We're looking for feedback on Unity Starter Kits! Let us know what you’d like.
    Dismiss Notice
  3. We’re giving 2017.1 beta testers a chance to win t-shirts and a Nintendo Switch. Read more on the blog.
    Dismiss Notice
  4. We want to know how you learned Unity! Help us by taking this quick survey and have a chance at a $25 gift card
    Dismiss Notice
  5. Are you an artist or level designer going to Unite Europe? Join our roundtables there to discuss artist features.
    Dismiss Notice
  6. Unity 5.6 is now released.
    Dismiss Notice
  7. Check out all the fixes for 5.6 on the patch releases page.
    Dismiss Notice

[Update v1.1] Make It Colorful: color types for working with various color spaces in code

Discussion in 'Assets and Asset Store' started by AndyGainey, Nov 18, 2016.

  1. AndyGainey

    AndyGainey

    Joined:
    Dec 2, 2015
    Posts:
    210
    News: Version 1.1 has been released. goto details;

    [​IMG]

    Purchase now for $5 on the Unity Asset Store.

    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.

    [​IMG]

    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.

    [​IMG]

    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.

    Code (CSharp):
    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.

    Code (CSharp):
    1. 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.

    Code (CSharp):
    1. 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.

    Code (CSharp):
    1. var hcy = (ColorHCY)firstColor;
    2. hcy.y = ((ColorHCY)secondColor).y;
    3. hcy.c = Mathf.Min(hcy.c, ColorHCY.GetMaxChroma(hcy.h, hcy.y));
    4. 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.

    Code (CSharp):
    1. var hcy = (ColorHCY)firstColor;
    2. hcy.y = ((ColorHCY)secondColor).y;
    3. 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.

    Code (CSharp):
    1. var cmyk = (ColorCMYK)color;
    2. cmyk.k = fixedKey;
    3. 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):

    Code (CSharp):
    1. spriteRenderer.color = ColorHCY.Lerp(startColor, finalColor, animTime / animDuration);

    Quick Links
     
    Last edited: Jan 14, 2017
  2. AndyGainey

    AndyGainey

    Joined:
    Dec 2, 2015
    Posts:
    210
    A minor update is incoming, version 1.1, with various utility improvements to the color types. The updated documentation is here; I'll update the top-post links once the update is approved by Unity. And here's the change log:
    • Added common color constants for each color space.
    • Added opacity functions to easily get opacity-altered variants of a color.
    • Implemented IEquatable<T>.
    • Implemented IComparable<T>, using a lexicographic ordering.
    • Added less, greater, and the -or-equal operators, using a lexicographic ordering.
    • Added functions to compute common color attributes for all color types:
      • hue
      • intensity
      • value
      • lightness
      • luma (apparent brightness)
    • Added GetValid(chromaBias) for chroma-based color types, to choose the degree to which chroma or luminance is preserved when correcting invalid colors.