In this tutorial you'll learn how to create video-like animations, using WebGL fragment shaders and HTML canvas.
This is the last part of a series of 4 articles - if you jut landed here you may want to start there instead
When animating in 2D there are a couple major tools you will likely want on your belt: scale
and rotation
.
Enter the matrix!
In GLSL, rotation and scale are processed very efficiently using matrices
. Let's first define them:
Rotation Matrix
mat2 rotate2d(float _angle){
return mat2(cos(_angle),-sin(_angle), sin(_angle),cos(_angle));
}
Scale Matrix
mat2 scale2D(vec2 _scale){
return mat2(_scale.x, 0.0, 0.0, _scale.y);
}
See it in action
Here is how we would downScale the scene by 2.2
with an anchor point at the middle of the screen:
float downScale = 2.2;
st -= vec2(0.5);
st = scale2D(vec2(downScale)) * st;
st += vec2(0.5);
More tools for your belt
floor
find the nearest integer less than or equal to the parameter,fract
compute the fractional part of the argument,mod
compute value of one parameter modulo another.
Putting it all together
With this knowledge in hand we can now better understand how the background texture is generated and applied to the shapes.
##create the background
vec3 makeBackground (vec2 st, float angle, float progress) {
// apply the rotation around the center
st -= vec2(0.5, 0.5);
st = rotate2d(angle) * st;
st += vec2(0.5, 0.5);
// scale st up to create a repeated pattern
st.x *= 100.0;
// get the fractional coords
vec2 ipos = fract(st);
// use sin with the x position on screen to progressively change the background
st.x += sin(st.x) * sin(25.0 + progress * 150.0) * 4.0;
// get the integer coords
ipos = floor(st);
if (random(ipos) < 0.2) {
return vec3(0);
}
// use random to vary the output
return vec3(
mod(random(ipos+ 1.0)*4.0, 1.0) * 0.5,
mod(random(ipos+ 1.0)*8.0, 1.0) * 0.25,
mod(random(ipos+ 1.0)*16.0, 1.0) * 0.75
);
}
Once the color is computed, we apply it to our shape, for example on the right bar of the letter N
, we apply the color starting at 4 second, and fully visible by 6 seconds.
nRight = mix(
nRight,
makeBackground(st, 0.0, 0.5),
mapTime(4.0, 6.0, u_time + st.y / 2.0)
);
Notice how we apply an angle of 0.42
radians on the oblique bar of the letter N
:
nMid = mix(
nMid,
makeBackground(st, 0.42, 0.5),
mapTime(4.25, 6.25, u_time - st.y / 2.0)
);
Just like a lego project, we build our creation combining one piece after another.
That’s it for today!
This concludes this series of articles on animating in a fragment shader, hopefully you learned something and are now feeling creative!
Revisit other chapters:
Intro
We'll go over the basics and project setup.Hulu
Next we'll look into drawing shapes and controlling time in animation.HBO
We'll reiterate these techniques and take a dive into noise functions.checkout full source
Hope you enjoyed this tutorial! The stuff I write about is a way for me to improve my learnings - probably just like you right now. So please if you catch any issue or want to suggest an edit, use the section below or reach out on twitter. Cheers!