Arctic Night

How the screensaver is built, in one page. ← back to the night

An exported night from the app: green and violet aurora light
 crossing pink volumetric clouds above dark snowy mountains, a full moon, and their
 reflection in the frozen lake. Seed 16.2666, 56% through the night.

One exported night. This 153 KiB image is nearly 2× the size of the entire app that rendered it.

A photoreal, scrubbable, touchable arctic night with procedurally synthesized sound and one six-family generative composer, in a single self-contained HTML file: WebGL2 + Web Audio, no dependencies, no network, 92 KiB deployed.

The mathematics is the machinery, not an illustration laid over it. The few equations below isolate mechanisms that actually ship in the simulation.

Download Mac App & Screensaver
One 479 KiB disk image · Apple silicon · macOS 13 or later
Download Windows App + Screensaver
One 3,899 KiB signed installer · x64 · Windows 10 1809 or later
Download for Lively Wallpaper
One 194 KiB ZIP · wallpaper + screensaver · requires Lively Wallpaper

Download Arctic Night for Windows

Arctic Night is newly released and digitally signed by David Chen. While its Microsoft Defender SmartScreen reputation is still building, Windows may display “Windows protected your PC.”

To install safely:

  1. Select More info.
  2. Verify the publisher is David Chen.
  3. Select Run anyway.

If the publisher is different or listed as unknown, cancel the installation.

Windows 10 version 1809 or later · x64 · Includes the app and screensaver · 3.9 MB

A seeded night in six stages

auroracloud transportreflection capturemain scenebloompost  (HDR path: RGBA16F · RGBA8 fallback)

One float seed chooses the terrain, winter, ice, sky, settlements, and aurora. The same seed always rebuilds the same world, and the 🔗 button preserves its state. Each draw then resolves two sky transports—emissive aurora and cloud extinction/scatter— before making the compact view the ice mirrors, the live scene composite, bloom, and the final filmic grade.

STATIC SCENE DATA HDR: RGBA16F · RGBA8 fallback CLOUD FIELDS 3D shape + weather 48×24×48 96×64 seed / load MASSIF BUFFER albedo + normals depth + occlusion 240 steps seed / size LIVE-SCENE DATA lake + snow · 5 layers Milky Way atlas · seed / size star grid · 1,800 once/load EVERY DRAWN FRAME AURORA emission night only CLOUDS extinction + scatter REFLECTION sky capture sky only MAIN ice mirror + live scene BLOOM spiral + moon window POST tone-map grade + grain SCREEN SCENE LIGHT STACK aurora profile + cloud-scattered fill

Static structure is paid for once. Each frame lights the landscape, captures the finished sky, and then mirrors that result in the ice.

Bake once, relight forever

The mountains are a raymarched heightfield, but only when the seed or resolution changes. A 240-step march with 32-way stratified sampling builds erosion, scree, snow, normals, depth, and sky occlusion into a G-buffer. The lake, snowbank, and Milky Way atlas follow the same rule. Because this work is offline, snow can mantle broad terrain while softening its fine rock relief, rather than inheriting every fracture beneath it.

Per frame, those surfaces become texture reads and lighting math. Cool sky, warm sunset, directional Moon, and the aurora’s live wash remain separate, so one fixed world can move continuously from dusk into moonlit night. Lake powder and snow-dusted floes now use that same horizontal-snow light stack; their baked masks describe depth and shape, never borrow the sky’s color as painted albedo.

baked once · relit per frame

The geometry is baked once. Drag to relight it.

The sunset is a light, not a backdrop

Sunset is not a background swap. Raw timeline position moves one solar anchor along a sinking, leftward arc and scrubs the lab’s compact cloud illustration across its 210-second scene span, while a separate darkness coordinate drives five keyed palettes for the zenith, horizon, Sun, ice, and snow. Near the horizon, an art-directed exponential extinction tint removes blue fastest as the optical path grows, so the afterglow warms as its source falls instead of merely becoming dimmer.

Crepuscular rays are an angular light field around that same anchor. Each seed rolls seven to eleven spokes, their phase, and a slow moving warp; a cubic profile narrows the bright shafts, while a radial envelope starts outside the solar rim and dissolves them into the sky. The same solar state lights cloud bodies from below—peach near the horizon, then apricot, pink-orange, muted red, and finally neutral gray as the long path loses its color—while it rakes mountain faces and snow grains, feeds the ice interior, aims a perspective lane of frost glints, enters the lake’s reflection capture, and finally blooms in HDR.

One sunset, everywhere
s(p) = ((−.06 − .30p2)A, H − .012 − .19p) P(p) = .62 + .38 min(1, p/.85) T(m) = exp[−m(.45, 1.0, 2.2)] θ = atan2(ysy, xsx),  r = ‖qs B(θ,t) = [.5 + .5 sin( + φ + w(θ,t))]3,  n ∈ {7,…,11} R(q,t) = mix[.31, B(θ,t), smoothstep(.06,.16,r)] M(r) M(r) = smoothstep(.045,.10,r) exp(−1.9r)

s(p) is the Sun’s normalized screen position: raw timeline position p moves it relative to aspect ratio A and horizon H. The separate darkness coordinate P reaches 1 at p = .85 and then holds, so the palettes can reach full night while the Sun keeps moving. T is the RGB transmission multiplier; the exponential is applied to each channel, so the larger blue coefficient removes blue fastest as air-mass proxy m grows. For sky sample q = (x,y), r and θ are polar coordinates around the Sun. B is the angular spoke pattern: the cube narrows its bright peaks; seed-fixed n and φ choose the count and phase, and w adds the slow living warp. R is the resulting ray brightness. The mix holds the spokes at their mean brightness (.31) near the convergence point, then reveals the pattern between r = .06 and .16 to prevent a tiny pinwheel. M(r) is the radial envelope: smoothstep keeps rays off inside the solar disc and ramps them on across its rim (.045–.10), while the exponential fades them into the distant sky. The rendered field also carries the sunset color, dusk gate, and above-horizon mask.

position p .24 · darkness P .73 · 11 rays

Scrub the dusk and remove one cause at a time. The light reaches night before the Sun finishes moving.

The aurora is a field, not a sprite

Up to three vertical emission sheets stand along smooth traveling paths. A small prepass integrates their density into 128 depth cells per screen column. Analytic cell integration conserves the light of a thin crossing at any slope; the renderer then lights those crossings with bundled strands, descending precipitation, moving active regions, and restrained HDR flares. A fold turning edge-on therefore gathers naturally into a ray instead of merely bending a painted texture.

Each detail field fades toward its mean before the pixel grid can no longer resolve it, turning distant structure into a luminous veil instead of shimmer or stripes. The finished curtain is also reduced to a 128×1 ground-light profile that snow, trees, clouds, and ice can sample in one tap. Clouds take the hue of the curtain above them; in return, their broader solar scattering adds a softer downwelling fill to the massif, snow, and lake without replacing the aurora’s spatial light.

Conserved curtain light
L(u) = ∫ ρ(u,t) E(u,t) dt ρ̄cell = √π |erf(d1) − erf(d0)| / (2|d1d0|) erf(d) ≈ tanh[d(1.128 + .0904d2)]

u is a screen column, t is distance along its viewing ray, ρ is sheet density, E is emitted light, and L is the accumulated curtain light. d0 and d1 are signed normalized distances from the sheet at a cell’s ends; ρ̄cell is that cell’s integrated mean, with the error function evaluated by the tanh approximation shown. Fold-apex cells split at the quadratic turning point first, so even a sub-pixel sheet keeps its light instead of becoming a dashed line.

sheet field

Drag the seam. More folds make the integrated field bloom into rays; the masked sheet only wiggles.

The sky answers touch

A touch first samples the finished aurora image, so empty sky does nothing and soft edges behave exactly as they look. The renderer’s density column then identifies which curtain lies under the finger, even where several overlap. No second interaction model approximates the scene.

The event records screen position, scene time, strength, and curtain depth. Only that sheet moves gently away while a restrained shimmer spreads and reaches exact zero after about three seconds; dragging paints a continuous path into a 24-slot event ring. Because the timestamp belongs to scene time, scrubbing backward replays the viewer’s own gestures. Retained events cost nothing outside their active time window. The disturbance enters the normal render path, so its reflection, snow light, and cloud light follow automatically.

The ice answers too: tap the lake and a hairline star cracks out under your finger, lives four seconds, then refreezes by running its birth backward: rays retracting tip-first, the way real cracks heal from their thinnest ends. At sunset it reads like the pane’s own healed ridges; under the aurora it’s a dark thread against the lit mirror. One crack at a time, rendered live against the untouched bake, and the night is always tranquil again within seconds.

The clouds part under your finger: a touch is a jet aimed through the deck along your own line of sight, modulating the same weather cause the light probes read, so the opening bends the deck’s real structure, piles a rim, and is lit honestly at any hour — it thins slowly, holds while you hold, and re-forms in seconds, and a drag lays a trail of partings that is itself the wind read. Touches are recordings on the night’s own clock: scrub the timeline and they replay exactly, quieting while the slider moves.

The Moon is direct too: drag vertically to change its phase, or sideways to carry it across the sky. Terminator, halo, landscape light, glitter, reflection, bloom, and HDR export all follow the same lunar state, so the whole lighting world moves with it. A touch that begins on the Moon belongs to the Moon, leaving aurora, ice, and music undisturbed.

The aurora has a voice

Every night writes its own score. The seed chooses one of six whole-piece families: the Canon’s recurrence, the aria’s withheld high note, the nocturne’s slow bloom, the harmonic river’s endless figuration, the cantabile prayer’s unbroken line, or the suspended meditation’s stillness. Each family has its own form and melodic grammar. No recording is sampled and no whole-piece critic chooses a winner: the same seed and performance number always produce the same composition.

The composer works from the whole piece downward. It lays out form and harmony, voice-leads a sparse structural melody, then ornaments the spaces between important tones. Themes return recognizably; prepared suspensions earn their resolutions; detail drawn from 150 classical themes never erases the underlying phrase. Melody and accompaniment share one tactus, so deliberate crushed notes resolve immediately instead of becoming the almost-simultaneous dissonances that first made the ensemble sound sloppy.

Inside the Canon grammar, 64 lawful eight-bar walks compete on singable steps, prepared dissonance, cadence, contour, and range; the seed chooses among the best five. This is local voice construction, not whole-song auditioning.

One real production score, from seed to form, string, and stone, through the app’s score dynamics, output ceiling, and rate-keyed room. Each green ring fades with its string and basilica decay. Drag the score or the time control to scrub. Enter any numeric seed; 29.2018 is the preserved Canon.

The same procedural harp belongs to the listener. The finished aurora image is its own hit test, so touching visible light plays one note from the composition’s full authored pitch map while empty sky stays silent. A touch takes the instrument from the score, and the score waits: the composition pauses under the hands and resumes where it stood a few seconds after the last touch, so answering the night never costs a verse.

tap = this seed’s phrase · drag = play
listen seed 29.2018 · pew

Tap for this seed’s phrase. Drag to play. Switch Stage / Pew to hear what 100 feet of air and stone do to the same string.

The instrument models a plucked string rather than playing a sample: tuned partials, pluck position, damping, and sympathetic resonance feed a procedural stereo room. The listener sits about 100 feet away, hearing softened direct sound followed by reflections and a basilica decay that shortens for denser writing and opens fully for sparse passages and manual touch. Its diffuse field blooms gradually, while a steepened final decay reaches silence without chopping the tail.

One plucked string
f0 = 440·2(m−69)/12,   fh = h f0√(1 + 9×10−6h2) Ah ∝ |sin(πhp)| e−h[.045+.15(1−b)] / h1.72 x(t) = Σh=110 Ahe−t/τh sin(2πfht)

m is MIDI pitch, h = 1…10 is the partial number, p is normalized pluck position, and b is brightness. f0 is the fundamental; fh, Ah, and τh are each partial’s frequency, amplitude, and decay time; and x(t) is the summed string signal after t seconds. Slight string stiffness and faster decay for high modes shape the note. No recorded harp is hiding underneath.

Playback has two reusable layers. First, each distinct string needed by the score is rendered once into a small buffer, replacing a fresh bank of oscillators for every note and cutting measured audio work by 40–50%. Then a pure-DSP copy of the instrument renders the complete performance in six-second pieces, 35–90 seconds ahead. Its string and room state cross every piece boundary, and an AudioWorklet consumes the queue on the real-time thread, so playback has neither audible seams nor last-moment note construction. Manual touch stays live through the original instrument.

The score also owns ordinary music-player behavior: media keys and the lock screen play, pause, seek, and skip; desktop tabs may continue sounding; phones pause when backgrounded. Favorites can name a night’s musical family directly from its seed, without composing or rendering the score.

The ice has an inside

The near lake is translucent volume, not a reflective plane with cracks painted on top. The interior technique was studied from TDM’s Frozen Lake (CC BY-NC-SA) and reimplemented in this project’s own noise stack. A refracted ray descends through a warped fracture field from the exact coordinate of the surface web. Shallow convergence produces a white surface fracture; deeper convergence becomes its cyan vertical curtain. Junctions continue downward as narrow spines, while bubbles and regional thickness break up the slab.

The bake stores anatomy and depth, not final color. At runtime, reflection lies above the deep volume and below the surface fracture; sunset, Moon, stars, and aurora relight all three. Distance extinguishes the interior, bright cracks matte the mirror crossing them, and no baked line becomes thinner than one texel; it widens and dims instead of breaking into distant dashes. Healed seams, frost, and freeze ridges keep the surface imperfect without making it glow.

Inside the ice
pk+1 = pk + .5dcrack(pk)

pk is the ray position after step k, is its refracted unit direction, and dcrack is the conservative warped-Voronoi distance to the nearest fracture. Advancing by half that distance prevents the warped metric from stepping through a thin wall.

Snow is shaped by light

The foreground bank is a marched surface whose rounded lip and wind swell determine their own shoreline. Snow patches and snow-dusted floes on the lake use the same material and the massif’s live illuminants. Most visible texture comes from stored normals and live illumination, not painted color: clumps appear under grazing light, and aligned crystals gather into warm sunset or cool moonlit glitter. Polished ice answers with a mirror instead.

A real sky, knowingly composed

The 1,800 brightest Yale-catalog stars turn around the northern celestial pole with their real positions, brightness order, and broad colors. The Milky Way follows the galactic equator, including the Great Rift and the warmer direction of its hidden core.

The clouds are a bounded volume, not translucent shapes composited over the sky. A 96×64 seeded weather field chooses condensation base, footprint, and lobe height; a separate 48×24×48 three-dimensional field supplies broad body and eroded detail. Nightly coverage is rolled mostly evenly from .40 to .62, with a small preference for the middle, while the end of the timeline retains 15% optical thickness so the same weather keeps moving as a thin veil instead of disappearing.

Cloud transport without slices
ρ̄i = ½[ρ(si − Δs/(2√3)) + ρ(si + Δs/(2√3))] Ti+1 = Ti exp(−σtρ̄iΔs) ΔLi = Ti[1 − exp(−σtρ̄iΔs)] Vi Q = (LMoon, Aupper, Alower, T)

At ordinary optical depth, each of 28 view segments samples density ρ at the two Gauss nodes around its center si, rather than at one repeated plane. As the night thins the medium, one estimator fades its nested secondary density budget from eight probes to four and then two. The retained pair follows the original central moon-direction route, so lunar shadowing cannot switch suddenly to an unoccluded estimate. Only then does the view budget descend from 28 to 16 segments; dense grazing paths still retain Beer–Lambert extinction. Their mean ρ̄i drives Beer–Lambert transmittance T; σt is the extinction coefficient, Δs the segment length, and Vi the directional and hemispheric visibility of that piece of cloud. The cloud pass stores the palette-free transport tuple Q, so the main scene can apply the live Sun, visible lunar disc, and local aurora color without marching the volume again.

The first sampling stratum is translated differently for every pixel and advances through a low-discrepancy temporal phase, breaking fixed ray planes into fine grain. History is accepted only when old and new opacity agree, so a scrub, resize, or changed silhouette resolves immediately instead of dragging a ghost. Moonlight follows the part of the lunar disc visible above the massif and stays concentrated around exposed cloud edges; aurora light inherits the curtain’s color but remains a subtle fill.

The Moon uses sphere lighting, so half phase has a straight terminator; photographic maria texture its earthshine face, and landscape illumination rises nonlinearly with the lit fraction; a full Moon is far brighter than a quarter. Trees occupy three hazed rows, village windows keep individual dusk schedules, and the bedside clock remains a crisp direct-view overlay. The implied viewpoint is near 62° north, but star motion is slowed, the Moon rides higher, and the Milky Way is brighter: a composed long exposure of a plausible place.

A spherical Moon
z = √(r2u2v2) D(u,v) = (u,vŝ sin(πφ) − z cos(πφ),   day side: D > 0

(u,v) is a point on the lunar disc of radius r; z is the reconstructed sphere depth, ŝ points toward the projected Sun, φ is lunar phase, and D is the signed illumination test. φ = 0, ½, 1 gives new, half, and full; D > 0 selects the day side without drawing a shadow disc.

Fast, because it runs all night

The normal scene renders at 0.75× device pixels and changes cadence with need: responsive during input, 32 fps when untouched, and about 11 fps in bedside-clock mode. Its large clock glyph and control palette use cached, non-animated color steps; the former Canvas2D clock reflection was removed so no duplicate text raster or texture upload rides the dusk morph. The aurora pass sleeps before dusk. Cloud transport shades only its half-width, 29%-height sky band and republishes each complete result for one to three display frames — holding longest exactly when the thinning deep-night deck would otherwise march hardest — before advancing the same full estimator; the main scene still applies current lighting every frame. Dry weather columns stop before the 3D shape lookup, moonless nights skip lunar visibility probes, and vertically aligned light samples share one weather lookup.

Static bakes run in small flushed strips so slow drivers never receive one dangerous GPU packet; time is wrapped before floating-point precision can decay. The built-in benchmark times every pass at the actual backing resolution when GPU timers are exposed, including the cloud draw/hold average; elsewhere a 50-frame whole-scene drain estimates frame time and the theoretical ceiling. The Mac screensaver goes further: each display gets its own seeded night only after the host proves a unique visible owner; ambiguity stays black and page-free, and dismissal destroys its WebView and timers instead of parking them.

The same shaders run through Metal, D3D, and native GL. The scene and bake programs are separated to stay below Chrome’s Metal pipeline limit; the bake further splits into one program per G-buffer owner, because D3D compiles every reachable loop and a first-ever load once spent close to a minute linking one all-pass program — five small programs compile concurrently while the loading card names the wait up front (its take-a-minute warning is static markup, so even an engine that blocks the page outright shows it), with an honest bar where per-program completion is pollable: each finished compile advances it, and GPU fences carry the final stretch through the scene bakes. WebKit goes further: it serializes and retires its largest compiler cohorts, completion-stages each static owner, then materializes every distinct live pipeline in a one-pixel offscreen target before the sole real canvas presentation. That targets Safari/Metal’s attachment-specific pipeline creation without slowing the already-reliable Blink, Gecko, or native paths. Sine-free hashes avoid D3D’s fast-sine stripes, and diagnostic views plus reproducible links turn ugly frames into test cases. Clock mode requests a wake lock while active and moves the canvas, digits, Moon, and scene reflections through a small OLED-safe pixel orbit.

Tuned by eye, exported in HDR

The method is physical first, perceptual second: establish plausible behavior, then tune how strongly it appears against photographs and the live render. Fine detail lives in light rather than paint, repeating lattices are rejected, and anything too small to resolve fades toward its mean.

The live canvas displays SDR, but the camera button rerenders at 2× resolution into an Ultra HDR JPEG. Its three-channel gain map preserves colored highlights that a single luminance gain would wash out, opens as a normal photograph anywhere, and restores the Moon, aurora, sunset, snow glitter, and ice on an HDR display. Aurora and cloud transport are prepared once at export resolution, then that exact phase is shared by the SDR base and HDR rendition so sampling grain cannot become false gain-map detail. It is a higher-fidelity render, not a screenshot. Press ? in the app for everything else.