Visualizations
041 / 500

041 · 3D

Spinning Donut

A shaded torus rendered point by point with a homemade z-buffer.

Inspired by the famous donut.c, this samples thousands of points on the surface of a torus, rotates them in 3D, projects them to the screen, and keeps only the nearest point per pixel in a depth buffer. Each point's surface normal is compared with a light direction to get its brightness. The result is real-time 3D shading with no WebGL at all.

Try it. Drag to spin the donut yourself. Release to let it coast. Press A for an ASCII version.

  • 3D rotation and projection
  • Z-buffer
  • Lambert and Blinn-Phong lighting

View the source · one module, plus a small shared runtime for sizing, the animation loop and input

Build your own

Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.

Build a spinning 3D donut in the spirit of the famous donut.c, using JavaScript and the HTML canvas element, with no WebGL. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.

Start simple:
- Make a canvas that fills the window. Render into a small offscreen canvas (about 320 pixels wide) with ImageData, then drawImage it scaled up.
- A torus is two angles: theta goes around the tube (radius 1) and phi goes around the ring (radius 2). Loop over both to get points and normals.
- Rotate each point and normal by two angles that increase every frame, push the donut about 6 units away from the camera, and project with x' = K * x / z, y' = K * y / z.
- Keep a depth buffer (a Float32Array with one value per pixel, storing 1/z). Only write a pixel when this point is nearer than what is already there.
- Light it: brightness is the dot product of the normal with a light direction.

Once that works, make it beautiful:
- Add a Blinn-Phong specular highlight (raise the normal-dot-halfway value to a power like 32) so it looks glazed.
- Color the top of the tube as pink frosting with a wavy edge, dough underneath, and scatter colorful sprinkles chosen by hashing the theta and phi cells.
- Let me drag to spin it, and keep spinning with inertia after I let go.

Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as an ASCII art mode, shadows on a floor, or other parametric shapes like a trefoil knot.
PreviousBandit CasinoEpsilon-greedy, UCB1 and Thompson sampling race to find the best slot machine. NextRain on GlassRaindrops bead, merge and run down a fogged window, each a tiny upside-down city.

Related visualizations

  • Chrome Blob3D A wobbling liquid metal droplet with real reflections, rasterized by hand.
  • Hopf Fibration3D The 3-sphere as linked circles, projected into nested tori of pastel rings.
  • Vector BallsRetro 512 chrome spheres, depth sorted, morphing from a torus knot to DNA to a smiling face.
  • Hidden 3DIllusions A live magic eye picture: a turning 3D sculpture hidden in colorful noise.
  • Dandelin Spheres3D Two spheres wedged in a sliced cone prove the focus property, with no algebra.
  • Gyroid Caves3D Fly through glassy minimal surface labyrinths, with a second maze behind every wall.
  • Shadow Sculpture3D One carved object casts three different shadows at once. Draw your own.
  • Path Tracer3D Photorealistic light, computed by bouncing millions of random rays.
  • HologramPhysics Record an off-axis hologram of glowing points, then rebuild the 3D scene from it.

Use ← and → to move between demos. While the canvas has focus, keys go to the demo instead.

← More from Emergent Mind Labs