Back to portfolio

Design Lab.

Small experiments in simulation, search, light and rendering. Everything here runs live in your browser, so go ahead and touch it.

Metaballs.

Liquid blobs that drift, merge and pull apart. There are no meshes or models: every pixel is computed from a formula describing the shapes.

How it works

Each blob is a sphere described by a signed distance function, which gives the distance from any point to its surface. A smooth minimum blends nearby spheres so they melt into one another instead of overlapping. For every pixel, a ray steps forward by that distance until it touches the surface (raymarching), and the surface normal drives the lighting. Rays that pass just beside a blob are blended into the background, which keeps the edges smooth.

A* versus Dijkstra.

Two pathfinding algorithms race through the same maze. Both find the shortest route; watch how much of the maze each one has to explore to get there.

How it works

Both algorithms always expand the cheapest cell next. Dijkstra only knows how far it has come, so its wavefront spreads evenly in every direction. A* adds an estimate of the distance left (the Manhattan distance, the same heuristic from my 8-puzzle work), so its wavefront leans toward the goal. Colour shows distance from the start, the dots are the frontier still waiting to be explored, and the counters show how many cells each has expanded so far.

Black hole.

Hot gas streaming round a black hole, inspired by Gargantua in Interstellar. Gravity bends the light so strongly that you see the far side of the disc arching over the top, and the stars behind smear into rings.

How it works

Every pixel is a ray of light traced backwards from the camera. At each small step, the ray is pulled toward the hole by an amount that grows steeply as it gets closer (the bending of a Schwarzschild black hole, which ordinary Newtonian gravity underestimates). Rays that fall inside stay black, and that is the shadow. The disc is a thick, glowing volume of gas that rays travel through, picking up light and being dimmed by it as they go. Its marbled swirls come from noise fed through noise (domain warping), recomputed every frame. The gas glows hotter and whiter near the centre, and a little brighter on the side spinning toward you, because the gas there moves at a good fraction of the speed of light (Doppler beaming). Interstellar toned that effect down so the disc looked even, and it's toned down here too. The inner gas orbits faster than the outer gas, so the disc's streaks shear into fine rings as it spins. Rays that escape look up the starfield in whichever direction they end up, so stars from behind the hole appear around its edge.

Ink in water.

Drops of coloured ink sinking through still water, curling into rings and trailing threads as they fall. Where inks overlap they mix like real dye, by each soaking up its own colours of light.

How it works

A drop of ink falling into water rolls up into a vortex ring: a doughnut of ink that spreads and slows as it sinks, trailing a thread from where it entered. Each drop here is that shape, swept through a slowly churning 3D noise field so it breaks into wisps. A ray from every pixel crosses the tank in small steps, and the ink it passes through absorbs light following the Beer–Lambert law: each ink removes the colours it isn't, so blue over pink darkens toward violet, just as dye does. The noise is computed once into a 3D texture, so each step costs only a few lookups.

Water ripples.

A pool you can touch. Ripples spread, bounce off the edges and interfere, bending the tiles and light beneath them.

How it works

Each pixel stores the water's height now and a moment ago. The next height is the average of its four neighbours, times two, minus the previous height: a discrete form of the wave equation, with slight damping so waves fade. The surface slope bends the image underneath (refraction), and where the surface curves, light concentrates into bright caustics.

That's the lab, for now.

Plain JavaScript and GLSL shaders, with no libraries or frameworks.

How I built the site See my projects Get in touch