Lesson 8 of 10 · Shader animation
Seamless loop
Triangle in perfect orbit. The loop that never cuts.
Sometimes you need the animation to repeat exactly, a GIF, a social media loop. No jump, no cut.
The formula: cos(T * 6.2831 / dur) where dur is the duration in seconds. 6.2831 is TAU (2*PI), one full revolution.
The last frame is the first. No cut. No jump.
TAU / durConverts your time to angle. When
T = dur the angle is TAU (full revolution). Cosine returns to start. Closed loop.Change
3. (loop duration in seconds) to 1.5 for a faster loop. To 8. for a slow one. It always closes perfectly, the last frame is identical to the first.The code
void main(){
vec2 p = (2.*gl_FragCoord.xy - R) / min(R.x, R.y);
float ph = T * 6.2831 / 3.;
vec2 c = vec2(cos(ph) * 0.4, sin(ph) * 0.4);
float ang = ph * 2.;
float ca = cos(ang), sa = sin(ang);
vec2 q = p - c; q = vec2(q.x*ca-q.y*sa, q.x*sa+q.y*ca);
vec2 aq = abs(q);
float d = max(aq.x*.866+q.y*.5, -q.y) - 0.12;
vec2 sq=p-c+vec2(.05,-.07); sq=vec2(sq.x*ca-sq.y*sa,sq.x*sa+sq.y*ca);
vec2 asq=abs(sq);
float shadow = smoothstep(-.01,.15,max(asq.x*.866+sq.y*.5,-sq.y)-.12);
float orbit = smoothstep(0.02, 0.0, abs(length(p) - 0.4));
vec3 col = vec3(0.03, 0.02, 0.04) * shadow;
col += vec3(0.3, 0.2, 0.15) * orbit * 0.3;
col += vec3(0.95, 0.45, 0.35) * smoothstep(.01,-.01,d);
col += vec3(0.8, 0.3, 0.2) * exp(-max(d,0.)*6.) * 0.3;
col = hueShift(col, 0.0);
gl_FragColor = vec4(col, 1.);
}