20 September 20261 min read← All notes

Building a gallery you can walk through

The Hall of the Works is a scroll-driven WebGL corridor. Here is how the camera walks, why it pauses, and what it costs.

  • webgl
  • three.js
  • gsap

Portfolios usually present projects as a grid of cards. I wanted mine to feel like walking into a room where someone had taken the trouble to hang the work properly.

The Tribuna of the Uffizi, Johan Zoffany, 1772–78

The Tribuna of the Uffizi

Johan Zoffany

Royal Collection Trust, 1772–78

The walk

The corridor is a React Three Fiber scene pinned behind a scroll trigger. Scroll progress runs from zero to one; the camera's job is to turn that single number into a walk.

I build a list of keyframes from the floor plan: the entrance, then for every exhibit a point across the hall facing the painting, then the end wall. Each exhibit gets two identical keyframes, so a stretch of scrolling holds the camera still. That pause is the most important part. It is where the wall label appears and where you actually read.

The frame is the budget

Everything in the room is cheap on purpose:

  • Frames are single beveled extrusions, not modelled mouldings.
  • The volumetric light is a handful of additive planes, not ray marching.
  • Paintings are 2048px WebP textures, and the whole scene mounts only when you get near it.

That leaves room for the two expensive things that sell it: a reflective marble floor and bloom on the picture lights.

Page order matters

The one real bug came from GSAP. The corridor's pin is created after the page first paints, so every pinned section below it calculated its position without it, and two sections pinned at once. Re-sorting every ScrollTrigger by DOM order, then refreshing, fixed it for good.

The hall is on the home page. Walk it slowly.