Colors
We haven't much of a chance to talk about GLSL vector types. Before going further it's important to learn more about these variables and the subject of colors is a great way to find out more about them.
If you are familiar with object oriented programming paradigms you've probably noticed that we have been accessing the data inside the vectors like any regular C-like struct
.
vec3 red = vec3(1.0,0.0,0.0);
red.x = 1.0;
red.y = 0.0;
red.z = 0.0;
Defining color using an x, y and z notation can be confusing and misleading, right? That's why there are other ways to access this same information, but with different names. The values of .x
, .y
and .z
can also be called .r
, .g
and .b
, and .s
, .t
and .p
. (.s
, .t
and .p
are usually used for spatial coordinates of a texture, which we'll see in a later chapter.) You can also access the data in a vector by using the index position, [0]
, [1]
and [2]
.
The following lines show all the ways to access the same data:
vec4 vector;
vector[0] = vector.r = vector.x = vector.s;
vector[1] = vector.g = vector.y = vector.t;
vector[2] = vector.b = vector.z = vector.p;
vector[3] = vector.a = vector.w = vector.q;
These different ways of pointing to the variables inside a vector are just nomenclatures designed to help you write clear code. This flexibility embedded in shading language is a door for you to start thinking interchangably about color and space coordinates.
Another great feature of vector types in GLSL is that the properties can be combined in any order you want, which makes it easy to cast and mix values. This ability is called swizzle.
vec3 yellow, magenta, green;
// Making Yellow
yellow.rg = vec2(1.0); // Assigning 1. to red and green channels
yellow[2] = 0.0; // Assigning 0. to blue channel
// Making Magenta
magenta = yellow.rbg; // Assign the channels with green and blue swapped
// Making Green
green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0)
For your toolbox
You might not be used to picking colors with numbers - it can be very counterintuitive. Lucky for you, there are a lot of smart programs that make this job easy. Find one that fits your needs and then train it to deliver colors in vec3
or vec4
format. For example, here are the templates I use on Spectrum:
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
Mixing color
Now that you know how colors are defined, it's time to integrate this with our previous knowledge. In GLSL there is a very useful function, mix()
, that lets you mix two values in percentages. Can you guess what the percentage range is? Yes, values between 0.0 and 1.0! Which is perfect for you, after those long hours practicing your karate moves with the fence - it is time to use them!
Check the following code at line 18 and see how we are using the absolute values of a sin wave over time to mix colorA
and colorB
.
Playing with gradients
The mix()
function has more to offer. Instead of a single float
, we can pass a variable type that matches the two first arguments, in our case a vec3
. By doing that we gain control over the mixing percentages of each individual color channel, r
, g
and b
. Take a look at the following example. Like the examples in the previous chapter, we are hooking the transition to the normalized x coordinate and visualizing it with a line. Right now all the channels go along the same line.
Now, uncomment line number 25 and watch what happens. Then try uncommenting lines 26 and 27. Remember that the lines visualize the amount of colorA
and colorB
to mix per channel.