Shader animation and Canvas animation are the same principle, through the timer cycle rendering, and change the attributes of the graphics in the Canvas to achieve animation.

Some Shader editors already implement timers and pass time-dependent values to Shader code. For example, the time-dependent properties of ShaderToy are iTime/iTimeDelta. The time-dependent property in GL-Transition is Progress. By combining variables in the shader code with time, you can make the animation happen.

First, displacement animation

In the previous article, we talked about coordinate operations, where addition and subtraction are displacement:

Instead of the conventional displacement animation, here are some complex movements:

1. Circular motion

St += vec(cos(u_time), sin(u_time))

Second, the rotation

Rotations can be easily accomplished with matrices:

But what you see is that when we multiply the matrix times the coordinates, we get exactly the top circular motion, and that’s because the rotation coordinates are in the lower left corner, and if we want to rotate the rectangle, we have to move the center point to the center of the rectangle, or another way of saying it, we have to move the center of the rectangle to the lower left corner.

Wrapped code:

mat2 rotate2d(float _angle){
    return mat2(cos(_angle),-sin(_angle),
                sin(_angle),cos(_angle));
}
Copy the code

When we rotate materials on a non-square canvas, we run into an unavoidable problem called stretching. For example, when the canvas is rectangular, it exposes the problem of stretching when rotating:

// Some code
void main() {
    vec2 st = textureCoordinate;
    float ratio = inputImageTextureSize.x / inputImageTextureSize.y;
    float animationTime = getAnimationTime();
    float easingTime = animationTime;

    float bigRotation = 30./180.*3.14159;
    st = rotateUv(st, bigRotation*easingTime, vec2(. 5.. 5), 1.);

    gl_FragColor = texture2D(inputImageTexture, st);
}
Copy the code

This article also mentioned the problem, the reason will appear this problem, because of high due to the wide ratio is 1:1, that although the x and y coordinates are 0 ~ 1, but they said the length is different, because of the length is different, resulting in rotation, the proportion of pixel movement does not conform to the canvas:

The solution is also relatively simple. When we rotate, we can stretch the Y-axis in proportion to the canvas:

void main() {
    vec2 st = textureCoordinate;
    float ratio = inputImageTextureSize.x / inputImageTextureSize.y;
    float animationTime = getAnimationTime();
    float easingTime = animationTime;

    float bigRotation = 30./180.*3.14159;

    st.y *= 1./ratio;
    st = rotateUv(st, bigRotation*easingTime, vec2(. 5.. 5), 1.);
    st.y *= ratio;

    gl_FragColor = texture2D(inputImageTexture, st);
}
Copy the code

Three, scaling

Scaling is the multiplication and division of coordinates, and can also be done with rectangles:

Similarly, if the coordinate system is not transformed, the center of the scale is still in the lower left corner:

Two animations together:

Wrapped code:

mat2 scale(vec2 _scale){
    return mat2(_scale.x,0.0.0.0,_scale.y);
}
Copy the code

4. Sine motion

Sines and cosines are very nice animated curves, and we showed this diagram when we talked about function visualization (from Bookofshader) :

So you get an idea of what sines and cosines can do, so let’s try:

This is cartesian coordinate motion, suppose we change coordinates to polar coordinates, can you imagine the general effect?

What if I wanted to make an outward-diffused animation, like radar? Remove the sin() function:

Related links:

  • Gist.github.com/ayamflow/c0…
  • Duriansoftware.com/joe/An-intr…
  • Stackoverflow.com/questions/3…
  • Stackoverflow.com/questions/3…
  • Neevek.net/posts/2017/…