Work

Sensory Space: immersive light art, built to lower the risk of seizures

For some people with epilepsy, flashing light can trigger a seizure. Sensory Space, a generative artwork of slow light and sound, sends every frame through a limiter on the GPU, and its flash test has to catch a flash whenever the limiter is switched off.

2026 ·Sole author · open source (MIT) ·Accessibility, Digital creativity

Live at sensory-space.org; source at jason-chao/sensory_space (MIT).

Kaleidoscope, ink in water and sea glass, recorded from the engine in real time. In the app, every picture is generated live in the browser. Rendered by the Sensory Space engine.

Sensory Space is a generative artwork of slow light and sound, made to support well-being, with particular care for people on the autistic spectrum and others who need sensory support. It runs in a browser, on a phone or through a projector, and it is live now.

The opening card over a moving aurora: the title, a hand symbol with 'Tap or drag to interact with the picture', a row of eight scene thumbnails and a Begin button
The opening at sensory-space.org. The scene is already moving behind the card, and a tap anywhere begins.

For some people with epilepsy, flashing light can trigger a seizure. Epilepsy is far more common among autistic people (a median of about 12%, against under 1% in the general population), and a projector fills most of the visual field. So before writing the first scene, I set one rule: the picture must never flash, whatever a scene or a bug of mine asks for.

One limiter for every scene

None of the twenty-one scenes contains any safety code. Every frame goes through one limiter, the last stage on the GPU before the screen, and whatever a scene asks for, the limiter decides how fast the picture may actually change.

The pool light scene with a 16 by 9 grid drawn over it. One region is outlined in yellow and its eight neighbours are shaded
The limiter works on a 16 × 9 grid. Each region may change by at most 0.35 of full brightness per second.

WCAG, the web’s accessibility standard, counts a flash as a pair of opposing changes in brightness of 10% or more, and allows at most three in a second. At the limiter’s pace, a region can manage at most about 1.75. A faster change turns into a dissolve. That lowers the risk, though no software can remove it for everyone.

The limit has to work region by region. Two patches can flash in opposite directions while the average brightness of the frame stays perfectly still, so a limiter that watched the average would let a strobing chessboard through. Colour can also flash on its own. Two saturated hues alternating at the same brightness pass any brightness check, so the limiter paces colour changes at the same rate.

The flowers scene after three taps: flowers burst into scattering petals with soft blooms of light where the picture was touched
Flowers, a moment after three taps. Each tap bursts a flower into petals and opens a bloom of light, and both go through the same limiter. Rendered by the Sensory Space engine.

A test that must fail

The flash check drives the real renderer through eleven worst cases, such as brightness slammed between 0 and 1 fifteen times a second, the scene switched every 100 milliseconds, and every control randomised every two frames. It counts flashes in each of 144 regions, using WCAG’s definition.

The twelfth case switches the limiter off, and it must fail. If it ever passes, the check can no longer see a flash, and the whole run fails. The whole check runs in GitHub Actions on every push.

Two charts of the brightness of one region over time. Top: with the limiter bypassed, brightness jumps between about 0.03 and 0.74 fifteen times a second; with the limiter on, it stays near 0.7 with a slight ripple. Bottom: a step from dark to full brightness is a one-frame cut when bypassed and a straight ramp over about two seconds when limited.
One region of the real renderer, given the same instruction with and without the limiter. Bypassed, it flashes seven times a second. Limited, it does not flash, and a jump from dark to full brightness becomes a dissolve of about two seconds. Data from the flash-check harness, 4 October 2026.

Flashing that came from the projector

A few users reported two colours flashing in the colour wash, the quietest scene of all. When I measured it, brightness and colour changed by less than half a percent between frames. The flashing most likely came from the projector. A flat, dark field of colour makes a projector’s auto-iris keep adjusting the exposure, and makes the colour wheel of a single-chip DLP projector visible. I gave the scene soft texture, so a projector always has a picture to work with.

The scene that felt spooky

The fractal garden passed every check, but some users found it spooky: a dark, speckled interior, fine edges that shimmered, and a form that never settled. I softened it, viewers still found it uneasy, and I withdrew it. A limiter can catch a flash, but only viewers could tell me that a picture felt wrong.

Two renders of the fractal garden. Left: dark, speckled, star-shaped fractals on a green field. Right: a softened version with rounded, pale grey shapes edged in green
The fractal garden, first version on the left and softened on the right. Both have been withdrawn. Rendered by the Sensory Space engine.

New scenes, and touch

I visited teamLab’s immersive exhibitions and came away inspired. Five new scenes grew out of that: lamps that pass their light to their neighbours when touched, flowers that bud, open and scatter, water drawn as flowing lines of light, brush strokes drawn slowly in space, and waves of colour through a deep lattice of points. Two more came later: rolling waves, drawn in the manner of the seas in Japanese ukiyo-e woodblock prints, and soft dots at many depths, after Yayoi Kusama’s infinity rooms.

The rolling waves scene: layered swells of blue drawn as flowing lines under a dark sky
Rolling waves, drawn as flowing lines in the manner of the seas in Japanese ukiyo-e woodblock prints. Rendered by the Sensory Space engine.
The infinite dots scene: soft dots of pink, violet and teal at many depths on a dark field
Infinite dots, after Yayoi Kusama's infinity rooms. Rendered by the Sensory Space engine.

Pressing and dragging leaves a wake that each scene answers in its own way. Lava follows the hand and splits, fireflies part and drift back, and lamps light up along the path.

The light lattice scene: a deep grid of glowing amber and violet points receding into darkness
Light lattice, one of the scenes inspired by teamLab. A drag lights up the points along its path. Rendered by the Sensory Space engine.

Brainwaves as input, within limits

For custom installations, Sensory Space can also take signals from an electroencephalography (EEG) headband. They may tint the colour and the tone, but they can never move the brightness or the volume, and movement slows the scene down, since a loop that speeds up with agitation could escalate it. Nothing is scored. The coupling is weak on purpose, because a single dry electrode on the forehead mostly picks up blinks and facial muscle. The feature is off on the public site.

Try it

It works on a phone too: sensory-space.org.

Two phone screenshots: the opening card over the aurora scene, and the rolling waves scene with the control bar in two rows
Sensory Space on a phone: the opening, and the control bar wrapped into two rows to fit the screen.