Generative Shader Color Palettes

Learn how to use cosine palettes to generate infinite color palettes.

When you are head down learning a new technique often the aesthetics are thrown out of the window. Coding is hard enough and learning a new technique can be frustrating.

An easy way to make your project aesthetically pleasing is with cosine palettes made by Inigo Quilez

// Cosine based palette, 4 vec3 params
vec3 palette( in float t, in vec3 a, in vec3 b, in vec3 c, in vec3 d )
{
return a + b*cos( 6.28318*(c*t+d) );
}

WIth the right configuration, this function creates waves of variations for each color component. Then, together they create all of the visuals you are going to see below and almost all the demos in Offscreen Canvas

Getting started

course

Raymarching animation

The first parameter "t" of the cosine palette is the phase. So, increasing this value moves the color forward.

This raymarching demo by kishimisu uses the length of the tube as the phase and increases it with time to make it move forward.

Tubes by Kishimisu

Worms raymarched

The second parameter "a" is the baseline color. From here is where the color variation will start.

The second parameter "b" is the amplitude of change. How big the color variation is going to be? The bigger this color, the more contrast you'll have because you are taking in a larger range of colors.

This demo only uses a very low second parameter to generate pretty similar colors, with not much contrast.

Worms by IQ

Cloud Tunnel

The third parameter "c" is how frequently the color changes. A bigger value means that the colors fluctuate a lot

This demo has a very low rate of change, so its c-value is low, or its phase change is really small

Cloud Tunnel by greweb

Fractured Chroma

The third parameter "d" is another phase shift but on each individual color component. This means that you can separate the different R G and B values and create different combinations of colors.

In this demo, Mario uses this fourth parameter to shift the colors differently depending on the column where the current pixel is located, using uv.x and uv.y.

Fractured Chrome by Mario

Further reading / Inspiration