# 41 pinball lamps in one material, with an ID map

> Graveyard Pinball's playfield has 41 individually lit lamps drawn by one material: a lit map, an 8-bit lamp-id map and one float per lamp.

Canonical page: https://andersonmancini.dev/blog/graveyard-pinball-41-lamps-one-draw

Published: 2026-09-09 · 1 min read · Tags: shaders, tsl, game-dev, pinball, textures

The playfield of [Graveyard Pinball](https://andersonmancini.dev/blog/graveyard-pinball.md) has **41 individually lit lamps** that glow as the ball scores. They are not 41 objects. They are one material and three small maps, all generated by a script in world coordinates, so a lamp sits exactly where it is in the 3D table.

## The three maps

| map | what it holds |
|---|---|
| board art | the playfield with every insert OFF, dark glass |
| lit map | every insert LIT: color plus a tight halo, black elsewhere |
| id map | an 8-bit lamp id per pixel, 0 for none, sampled with NEAREST and no mipmaps |

A JSON manifest lists every lamp: id, name, group, color and position, plus `bind`, which ties a lamp to a reactive prop on the table.

## About ten lines of shader

Read the id at this pixel. If it is not zero, look up that lamp's level in a one-row texture with one float per lamp, and add `lit(uv) * level * gain` to the board's own emissive. One material, one draw call, any number of lamps, each with its own brightness. A level above 1 pushes the color into the bloom.

With WebGPU, the same math is a TSL emissive node: the ids texture is read with an integer texel fetch so there is no filtering.

## The API a game needs

```js
lamps.set('letter_3_A', 1)        // sustained, >1 overdrive
lamps.flash('bumper_1', { peak: 1.5 })
lamps.chase('letters', { step: 0.07 })
lamps.bindFlash('cauldron_01')    // flash every lamp bound to that prop
```

The rules, what lights what, belong to the game: cauldron hits spell GRAVEYARD, three lanterns make the jackpot, a bank of tombs advances the multiplier.

## Changing the playfield

Because the art and the maps are generated, editing the layout means editing the generator, then re-running it. Lamp shapes are small paths: circle, ring, tomb, diamond, star, chevron, pill and skull.

The display that complements them is in [the DMD post](https://andersonmancini.dev/blog/graveyard-pinball-dmd-in-4kb.md). The project is on its [project page](https://andersonmancini.dev/projects/graveyard-pinball.md).

## Related projects

- [Graveyard Pinball](https://andersonmancini.dev/projects/graveyard-pinball.md) — Free Halloween game
