The Darkening

Artificial Noodles ·

Inspired by Photochromic lens on Wikipedia

Built with Pure WebGL2 · FBO Ping-Pong · GLSL Fragment Shaders

Techniques Exposure Accumulation · Diffusion Simulation · Thin-Film Interference · Voronoi Crystal Grains

Direction You are the light that damages the glass

Result A pane of glass that remembers everywhere you’ve lingered — and slowly, incompletely, forgets

The Story

Photochromic lenses contain millions of silver halide crystals embedded in a glass matrix. When ultraviolet light strikes, the crystals undergo a chemical reaction — silver ions reduce to metallic silver, and the glass darkens. Remove the UV and a slower thermal process reverses the reaction, clearing the lens. But the reversal is never perfect. Each cycle leaves microscopic damage. Over years, the lenses develop a permanent tint — a memory of accumulated light.

What struck me about this process is its asymmetry. Darkening is fast, driven by energetic photons. Clearing is slow, dependent on ambient heat. And speed matters — move through hot sunlight quickly and the heat actually fights the darkening reaction, keeping lenses lighter than if you sat still. The glass is caught between two forces: light that wants to change it and heat that wants to undo that change.

There’s something human in that. We darken quickly under pressure. We clear slowly. And we never quite return to the state we were in before.


The Take

Your cursor is ultraviolet light. Where you hover, the glass darkens — a smooth, smoky transition from clear to opaque grey. But the beauty is at the edges. Where the exposure is thin, silver halide crystals catch light in iridescent halos — the same thin-film interference that gives soap bubbles and oil slicks their rainbow sheen.

Linger and the darkness deepens. Move fast and heat reduces the reaction — the glass barely responds. Leave an area and watch it slowly, incompletely clear. The more you expose, the more fatigue accumulates — permanent damage that resists clearing. Five lines of text emerge from the crystal depth as you explore: from “Silver halide” to “Some darkenings are permanent.”

The interaction embodies the phenomenon. You don’t adjust parameters — you ARE the UV source, painting destruction across the glass surface.


The Tech

FBO Ping-Pong Simulation

The simulation runs in a WebGL2 framebuffer at 75% resolution, ping-ponging between two RGBA16F textures each frame. Four channels track the state: R = current exposure intensity, G = crystal density (nucleation and diffusion-driven growth), B = fatigue (permanent, monotonically increasing), A = total accumulated dose (for interference thickness).

The cursor applies a wide Gaussian exposure field — radius 0.28 in normalized coordinates when lingering, shrinking to 0.10 when moving fast. Speed is tracked frame-to-frame and multiplied against the exposure rate via a quadratic heat factor: mix(1.0, 0.05, speed² ). This means fast movement almost completely suppresses the reaction.

Diffusion and Crystal Growth

Exposure diffuses through the glass via a discrete Laplacian (5-point stencil) at a rate of 0.25 per second, creating organic spreading from the cursor footprint. Crystal density nucleates where exposure crosses 0.15–0.45 and grows via an 8-neighbor anisotropic diffusion kernel (cardinal neighbors weighted 0.2, diagonals 0.05) modulated by local exposure. This produces subtly branching crystal growth patterns rather than uniform fill.

Thin-Film Interference

The render shader maps crystal state to color via physical thin-film interference. For each pixel, the crystal grain’s “thickness” (derived from Voronoi cell hash + accumulated dose) determines the phase difference for red (620nm), green (530nm), and blue (470nm) wavelengths: sin²(π · 2d/λ). The resulting spectral color is most vivid in the transition zone — medium exposure where the crystal film is thin enough for maximum constructive interference. At full darkness, colors are muted; at the edges, they bloom.

Voronoi Crystal Grains

Two scales of Voronoi tessellation (20 and 50 cells, both shifting with accumulated dose) create the crystal grain structure. Each grain gets its own interference thickness from a deterministic hash, producing different colors across adjacent crystals. Grain boundaries glow faintly brighter — simulating light catching crystal facet edges — and rare sparkle points flash at boundaries in dark zones.

Fatigue

The product of exposure × crystal density accumulates irreversibly in the B channel. Above 0.2 fatigue, Voronoi-based crack patterns appear as permanent dark fractures. Fatigue also slows the clearing rate by up to 80%, making heavily-used areas resist returning to clear.


Experience: The Darkening


This blog post was AI generated with Claude Code. Authored by Artificial Noodles.