In this chapter

In this chapter

  1. Less purple everywhere
  2. A whole town on sixteen lights
  3. Fine in a screenshot, wrong in a drag
  4. The trade-off

Less purple everywhere

The first lighting plan named a nicely specific problem: a broad lavender ambient light and a pink rim light were tinting too many materials the same way. The town had atmosphere, but roofs, walls and trim were starting to look alike.

Day, golden hour and night became matched profiles, so the key light, ambient fill, sky, water, windows, glow and reflections all shift together. Rain is a separate setting, which means you can have a rainy afternoon or a dry night.

Daylight turned out to be the most useful test. Night makes a lot of architectural mistakes look romantic. In daylight the same building needs clear planes and believable material colours, with no warm windows to carry it.

One town, three moods
Canal quarter in day
Pick a time of day. These archived captures come from different milestones, so they aren’t a controlled before-and-after comparison.

A whole town on sixteen lights

A glowing window doesn’t always need a real light of its own. PixelPunk keeps the glow you see separate from the small pool of lights that actually illuminate nearby geometry, so hundreds of fixtures can look lit while the pool stays capped at sixteen.

The light sources come from the generated fixtures themselves. A lamp’s position, colour and direction follow a mesh that exists, and a dark window can’t throw a mysterious streak across the canal. Guessing where lights ought to be from a building’s rough shape was less reliable.

Four times a second, a selection pass ranks the sources by camera focus and screen coverage. Additive halos and emissive surfaces keep everything outside the pool looking lit. Reflections on the water are stylised streaks, tinted and placed from the same source data and clipped to the terrain footprint. They aren’t full scene reflections.

Fine in a screenshot, wrong in a drag

The fifth lighting review found that rebuilding fixtures threw away the whole light pool, and every replacement lamp faded in from zero. During repeated edits the town never finished lighting up before the next rebuild knocked it back down.

At the measured drag cadence, the town got only 53% of the light energy it should have. Still images barely showed it, because taking a screenshot paused things long enough for the fades to catch up. The problem only existed over time, so finding it took a per-frame measurement.

The fix keeps a lamp if its fixture still has the same identity, position, colour and range. Identity alone wasn’t enough, since a reused batch index might now point at a different window. With that check in place, unchanged lamps survive a rebuild.

53%Light delivered before
99.5%After keeping the pool
16Real-light ceiling
Recorded Canal quarter drag-cadence experiment, lighting pass 6, 16 September. These are light-energy ratios, not frame-rate gains.

The trade-off

The second fault was a pool full of lights that were still fading out. A new source could be turned away while an outgoing one held its slot. In the recorded orbit, seven slots could be stuck that way, and 27 wanted sources were refused.

Now, when the pool needs room, it takes back the dimmest outgoing light. The ceiling stays at sixteen and the recorded refusals go away. The price is that a fade-out sometimes gets cut short, ideally at the edge the camera is leaving, which beats an unlit fixture in the view it’s moving into.

Later passes gave the sky and water more depth, made the neon properly HDR and put the sun on a continuous path. After the light-pool bug, though, a good-looking still frame no longer counted as proof that anything looked good in play.

From the project notebook

This chapter draws on the project’s records as they stood on 23 September 2026.

  • docs/lighting-and-texture-plan.md · Direction and lighting foundation
  • docs/visual-handoff.md · Passes 3–6, water, neon and sun path
  • artifacts/lighting-pass6/g-drag/performance.json
Read the source excerpts
End of part 03Back to the chapters