Garfield Dance Party

Live Demo

Overview

This whole thing started as a joke. My love for Garfield began because he was easy to draw, and I liked his comics. I used to doodle him all over my notes during class, and my intro to animation course was no exception. One weekend on a ferry ride, I figured: why not try 3D modeling the very cat I’ve been obsessively drawing for months? That led to this WebGL animation.

Built with: JavaScript, WebGL, GLSL


The Scene

  • Initial Scene: Garfield stands in a minimal, grey room.
  • Event Trigger: Sunglasses and textured speakers fall in with basic physics.
  • Animation: Garfield begins a continuous head bop; camera orbits the scene.
// Head bobbing logic based on sine wave
let bob = Math.sin(Timer * 4.0) * 0.2;
mvMatrix = mult(mvMatrix, translate(0, bob, 0));

Building Garfield

  • Built entirely from primitives: spheres, cones, cylinders.
  • Used a hierarchical model: body → head → ears/eyes, enabling smooth transformations.
  • Accessories (glasses, speakers, music notes) are grouped compound objects for easy manipulation.

Musical Notes & Chaos

To amplify the absurdity, floating music notes are periodically spawned and animated to rise and spin around Garfield.

function spawnNote1(x, y, z) {
mvPushMatrix();
mvMatrix = mult(mvMatrix, translate(x, y + noteYOffset1, z));
mvMatrix = mult(mvMatrix, rotate(noteRotAngle1, [0, 1, 0]));
note1();
mvPopMatrix();
}

Each note follows a sine-wave lift and spins slowly in place, providing ambient motion synced loosely with Garfield’s dancing and shader pulses. This adds visual rhythm, even without audio.

Shader Candy

The shaders in this project do a lot of heavy lifting, these shaders simulate a club-like environment with banded lighting, glowing textures, and rainbow gradients that shift over time. These shaders combine to deliver reactive, expressive lighting and surface effects — all rendered in real time.

🌈 Rainbow Lighting (Vertex Shader)

vec3 palette(float t){
vec3 a = vec3(0.5, 0.5, 0.5);
vec3 b = vec3(0.5, 0.5, 0.5);
vec3 c = vec3(1.0, 1.0, 1.0);
vec3 d = vec3(0.00, 0.33, 0.67);
return a + b*cos( 6.28318*(c*t+d));
}

✨ Glow Effect (Fragment Shader)

vec2 uv = vec2(fTexCoord.x/2.0, fTexCoord.y/2.0)*2.0-0.5;
uv = fract(uv*5.0)-0.5;
float l = length(uv);
vec3 col = palette(l + Timer);
vec4 text1 = mix(texture(checkered, fTexCoord), vec4(col,1.0), .5);
fragColor = text1;

🎨 Cartoon Lighting / Cel Shading

float lightDotNormal = max(dot(L, N), 0.0);
float mul = 10.0;
float div = 10.0;
float lightBandsMultiplier = float(mul/div);
float lightBandsAdditive = float(mul/2.0);
float LdotN = floor((lightDotNormal*1.7*div+lightBandsAdditive)/mul)*lightBandsMultiplier;

Tech Stack

  • WebGL: Real-time 3D rendering
  • JavaScript: Animation, scene logic, physics
  • HTML GLSL (Shaders): Lighting, glow, rainbow, cel shading