41 pinball lamps in one material, with an ID map

· 1 min read · shaders, tsl, game-dev, pinball, textures

A gothic pinball playfield with glowing orange letters, cyan rings and a magenta jackpot star lit on dark glass inserts

The playfield of Graveyard Pinball 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 #

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. The project is on its project page.

Related projects