Mixing Colors Over Time in GLSL
In the previous lessons we explored solid colors, gradients, and how values can be controlled across the screen. This time we are doing something slightly different.
Instead of changing color based on position, we are changing color based on time.
The example comes from The Book of Shaders, where you can experiment with the code yourself:
https://thebookofshaders.com/06/
The Code
uniform vec2 u_resolution;
uniform float u_time;
vec3 colorA = vec3(0.149,0.141,0.912);
vec3 colorB = vec3(1.000,0.833,0.224);
void main() {
vec3 color = vec3(0.0);
float pct = abs(sin(u_time));
color = mix(colorA, colorB, pct);
gl_FragColor = vec4(color,1.0);
}

What Is Happening Here?
This shader creates a smooth transition between two colors.
The blue color is stored in colorA:
vec3 colorA = vec3(0.149,0.141,0.912);
The yellow color is stored in colorB:
vec3 colorB = vec3(1.000,0.833,0.224);
Each vec3 contains the red, green, and blue components of a color.
The interesting part is this line:
float pct = abs(sin(u_time));
Let's break it down.
u_time continuously increases while the shader runs.
When we pass it into sin(), the result oscillates between -1 and 1.
sin(u_time)
Because mix() expects values between 0 and 1, we use abs().
abs(sin(u_time))
This converts all negative values into positive values.
The result now moves smoothly like this:
0 → 1 → 0 → 1 → 0
over and over again.
That value is stored inside pct.
Understanding mix()
The mix() function blends two values together.
mix(A, B, t)
Where:
Ais the starting valueBis the ending valuetis the blend amount
Examples:
mix(colorA, colorB, 0.0);
Returns only colorA.
mix(colorA, colorB, 1.0);
Returns only colorB.
mix(colorA, colorB, 0.5);
Returns a perfect blend between the two.
Since our pct value keeps moving between 0 and 1, the shader continuously fades from blue to yellow and back again.
color = mix(colorA, colorB, pct);
Why This Matters
Up until now many of our examples used coordinates such as:
vUv.x
or
st.x
to create changes across space.
This shader introduces another important idea:
Using time as an input.
Instead of saying:
Color depends on where a pixel is.
we are saying:
Color depends on when the pixel is being drawn.
That small shift opens the door to animation.
Where Could You Use This?
This technique appears everywhere:
Animated backgrounds
Slowly transitioning colors can make static backgrounds feel alive.
Loading screens
Colors can pulse gently while waiting for an action to complete.
Audio visualizers
The blend amount can come from music amplitude instead of u_time.
mix(colorA, colorB, audioLevel);
Interactive installations
The blend value could be controlled by sensors, mouse movement, or camera tracking.
Generative art
Many artists use color mixing as the foundation for more complex animated compositions.
Try These Experiments
Replace:
abs(sin(u_time))
with:
abs(cos(u_time))
Notice how the animation starts from a different point.
Or make it faster:
abs(sin(u_time * 5.0))
Or slower:
abs(sin(u_time * 0.25))
You can also try different color combinations and see how the mood changes.
This shader may look simple, but it introduces one of the most important ideas in shader programming.
A value does not have to come from position.
It can come from time.
Once you start feeding animated values into functions like mix(), the screen stops being a static image and becomes something that evolves continuously. That idea sits at the heart of many shader effects, generative artworks, and interactive visual systems.
Posted Using INLEO