Altar of Oba The code behind a pillar of light
664 addressable pixels on three buses, a Raspberry Pi at fifty frames a second, and one decision that made all of it tractable: the code never addresses a pixel, it addresses a place on the sculpture.
Altar of Oba stood in Black Rock City in 2023, a piece built with lead artist Dipo Doherty that paid homage to the ancient Benin culture and served as a pillar of color and light for the ideas that embody Afrofuturism.
My role was lighting and power. Dipo's vision was already there in the panels; the job was to give it a second life after dark, in light that answered the color he had painted rather than washing over the top of it. What follows is how that was actually built.
The eyes
The signature fixtures were made rather than bought: custom acrylic iridescent eyes, four of them, eleven inches across, two per face. Each carries two rings of the same diameter at different depths behind the acrylic, a 45 pixel iris and a 30 pixel ring of whites. Iridescent acrylic is a difficult material to light. It changes what it does depending on where you stand, so the trim had to read across the open playa and still leave the acrylic something to do up close.
In software an eye opens the way an eye opens. Both rings light only below a threshold that climbs through the eye's own bounds, so the lit area creeps up the circle like a lid lifting, holds at the top, then runs back down. While that happens the flood lights at the base fade out, moving the attention off the sculpture and onto the thing looking at you. It is about ten lines of geometry, and it only works because of the next part.
A model of the pillar, in feet
The controller builds the sculpture before it builds a single effect. Twelve feet tall, two and a half wide, two deep, flaring a foot wider at the top and bottom corners, all of it in feet rather than pixel indices. Each of the four edge runs then places its 90 pixels along that outline at equal spacing, so a pixel's position in software is where its counterpart actually sits on the piece. The model knows what it cannot see, too: each five meter run left a tail of strip tucked inside the top, and those eight pixels are a named hidden segment, excluded on purpose rather than by accident.
On top of that sits a naming layer. One long run snakes through the structure, but nothing downstream ever says "pixels 42 through 21 of the right hand run." It says the top right of face A. Ranges compose into bigger ranges, so there is a name for a side, a face, a third of the height, both faces at once, all four eyes, just the irises, everything. Runs installed backwards are declared backwards once, in the model, and never thought about again.
Color taken off the panels
A great deal of care went into the palette. Seven colors drive the whole piece, taken from the panels themselves: a green, a yellow, a red, a blue, a lighter blue, a pink and a purple. Every effect draws from that list, so the light complements the bold choices already on the piece rather than competing with them, and brings the whole thing back to life after dark.
The stripe patterns go further and give the pillar's three horizontal bands their own palettes, because the panels do not use one palette top to bottom either. Pinks, purples and a red through the top third. Blues and a lighter blue through the middle. Yellow, green and red at the foot. The bands scroll, so the piece reads as one object whose color story changes with height, rather than a tube with a rainbow running up it. Where patterns overlap, the blend weights toward the brighter of the two and keeps the brighter value rather than averaging them down. Two lights add. Two paints do not.
Effects written in space
Because every pixel knows where it is, an effect can be a shape rather than a sequence. The clearest case is the helix: a curve spirals around the pillar just outside the corners, each pixel works out how far it sits from that curve at its own height, and brightness falls off as the cube of the distance. Nothing is drawn onto the strips. A lit object orbits the sculpture and the sculpture samples it. Four can run at once, two spinning each way, blended per pixel. The same effect crosses both faces, rides through the flare and lands on the eyes with no special case for any of them, which is what the model was for. Twenty three effects are built this way.
Two altars, one real, one in shadow
A thirty three item playlist runs the show on a loop, each item naming an effect, how long it holds, and how it gives way to the next. The transition machinery is the part I would keep in any future piece.
The controller builds the model of the pillar twice. One copy is what the sculpture is showing. The other is a shadow, and the incoming effect renders onto it in full, as though it were already playing. A transition merges the two pixel by pixel, and when it finishes the shadow is promoted and becomes the live one. The effect that was running in the dark never knew it was in the dark.
So transitions are geometry, three or four lines each. A wipe upward is a height threshold that climbs. A wipe from the center is the band around zero widening. A wipe downward is the same test flipped. Add a cosine to the climbing threshold and it overshoots and settles, and that is a different transition. Six exist, none longer than a paragraph, and no effect anywhere contains a line of transition code.
artist Dipo Doherty, lead artist
where Black Rock City, Burning Man 2023
fixtures 4 custom iridescent acrylic eyes, 11in, fully addressable LED trim
pixels 664: 360 edge trim, 180 iris, 120 eye whites, 4 floods
buses 3 off one Raspberry Pi: 2 × PWM GPIO, 1 × SPI for the eyes
software Python, 23 effects, 6 transitions, a 33 item playlist
frame rate 50fps target, threaded output, per stage timing
664 pixels, three wires
The output side is where the elegance stops and the Raspberry Pi starts having opinions. A Pi has only so many pins that can clock WS281x timing reliably, so the pixels leave on three buses: face A and its two floods out one pin, face B and its two floods out another, and all 300 eye pixels on the SPI line, because that was the third channel available and the eyes were the run that could not afford to stutter. The eyes also arrived with their red and green swapped relative to the trim, being a different batch, so they carry their own channel order in the mapping. One line of code, and about an hour of standing in the dust wondering why the irises were wrong.
Clocking that many pixels out is the real frame budget, not the maths. The next frame is built while the last one is still going down the wire, on its own thread, and the loop times each stage separately and prints them every tenth frame. The target is fifty frames a second and it takes what it can get.
Keeping it lit
The most useful thing I learned here has nothing to do with pattern design, and it cost most of an evening to find.
The rest is desert insurance. It runs as a system service that restarts on failure and comes up on boot, so the piece recovers from a power cut without anyone climbing it, and every start writes its own timestamped log. If a write to the pixel bus fails, the controller shuts every channel to black rather than leaving half a frame stuck on the strip: dark on purpose beats frozen. Development ran on the same code, with a 3D simulator on a laptop and stand-ins for the display and the pins when the hardware libraries are absent. A file watcher restarts the process whenever anything changes, which makes the loop on site: edit on the laptop, sync to the Pi, look up.