4: Customizing the generation for specific purposes

In the case that you use procedural color palette generation for inspiration or concept art or the likes, and other people won't be using the generated palettes, it is okay to just keep generating until you find something you like.

However, when the generated palettes have to be useable in, for example, a website, user interface, or game, it may be important to customize them for your use case. Some questions to consider include:
- How distinguishable must different generated palettes be?
- What is their relationship to each other? (will they be seen simultaneously, or in different locations, or will they be seen after each other?)
- What will they be applied to, and what does that mean for things like contrast?

Example: procedurally changing landscape

I have been working on a project in which a terrain with, among other things, changes color. One of the key elements for this project was that all transitions had to be smooth and nice to look at. This meant a couple of things for the generation of my color palettes:
- I either had to make sure I could generate an array of palettes inbetween my start and goal palette using the input variables inbetween, or simply lerp from the old palette to the new one.
- Different palettes had to be structured similarly, to make transitions less confusing.
- I did not want much grey in the palettes or transitions.

(The code for this project is not in the Unitypackage, but you can see more of it here.)

Animation of the terrain in my project, morphing shape and changing color

Lerping between colors

Lerping is great when you want to transition from one color to another, for example to make a gradient or change an object from one color to another. There are a couple of ways to go about this: you could lerp the input variables, or lerp the colors themselves. The first method requires the algorithm to be written with this purpose in mind, as you'll probably want similar input to give similar output. Otherwise you'll have seemingly unexpected jumps in the color. The second method can be applied to colors generated with any algorithm, and allows for some more freedom in the transition code. For example, you could simply use the Unity built-in Color.Lerp function, or otherwise lerp the RGB values in another development environment, but you could also lerp your HSV or HSL values. Visually, this makes a large difference. For example when lerping from red to cyan, Color.Lerp will go from red to grey to cyan, whereas lerping the HSL values will go from red through yellow and green towards cyan. Either can work for different purposes. There is a lerp function built into the HSL struct in the Unitypackage.

//these two lines output completely different colors
//the first outputs pure grey, while the second outputs a saturated acid-green
Color c = Color.Lerp(Color.red, Color.cyan, .5f).rgb;
Color c = ColorHSL.Lerp(Color.red, Color.cyan, .5f).rgb; //function from this Unitypackage
Comparison between lerping RGB values and HSL values

Designing for smooth transitions

Even though most HSL color lerps are already smooth to a certain extent, switching from some palettes to some others gets very confusing to look at. Maybe some colors transition from dark to light and some the other way around, maybe the same hues seem to swap places, such things can make a transition look very incoherent or confusing. An example of this can be seen in the gif.
To remedy this, I chose to structure my palette a certain way. Different spots in the palette would always be either lighter or darker than the main color, and would be hue-shifted the same direction from the first color as well. I exclusively used an analogous color scheme to remedy strangely transitioning hues, but allowed the hue shift to cover more of the hue wheel to make up for the loss of hue variation.

Note how the top palette transitions in a fairly natural, predictable way, whereas the bottom one seems to change in a strange way.

Comparison between lerping between two palettes with similar color relationships, or two palettes with different relationships between colors

Smooth input to smooth color transitions

Sometimes, you'll find yourself having a float that constantly increases or decreases in similar increments, like input from a slider or a time variable. You can use these to generate color palettes that create a nice smooth spectrum when sliding the slider or waiting a while, without sudden jumps in color. This requires some care about the way you implement the variable in the algorithm, specifically in the way it loops. For example, hue can jump from 1 to 0 without visual impact (red and red are equal), but saturation cannot, as that would change a color from fully saturated to completely grey. Think about where you can use sines and cosines, where you could implement Mathf.Repeat or modulos, or where Mathf.PingPong is the best fit. An example of implementation is this algorithm, using time as the input variable:

float currentTime = Time.time;

float mainHue = (currentTime % 60) * .016f; //loops from 0 to 1 each minute
//all other variables oscillate between two values at different speeds
float hueShift = Mathf.Sin(currentTime * .02f * Mathf.PI) * .1f;
float mainSaturation = .3f + Mathf.PingPong(currentTime * .015f, 5) * .1f;
float saturationShift = Mathf.PingPong(currentTime * .007f, .1f) + .01f;
float mainLuminance = .5f + Mathf.Cos(currentTime * .1f) * .25f;
float luminanceShift = (.5f - mainLuminance) * .2f;

//then generate color with the calculations of the second part of this tutorial

Further influencing color palettes

A great tool in customizing your color palettes is set minimum or maximum values for a lot of things. For example, even when using the random palettes from the second part of this tutorial, you can influence palettes a lot by changing the bounds of the random ranges. Different variables can also adapt more to other variables, to create more coherent color palettes. (for example with the adaptive saturation based on lightness, in the same part of the tutorial).
Another thing you can do is change the colors to some extent after they have been generated, for example to bring them closer together, make the palette more different from the previous one, or shuffle the colors.