Skip to content

v3.4.0 — "Optics"

Latest

Choose a tag to compare

@Edwson Edwson released this 07 Aug 07:15
· 1 commit to main since this release
a68839a

Six new animations (80 → 86) on a new optional three.js tier. The library still has zero required dependencies — nothing extra is downloaded unless you mount one of these six.

The tier

registerAnimation accepts renderer: "three", and registerThree(name, { defaults, scene }) gives a scene the same lifecycle every other animation gets — DPR-clamped resize, pointer input, off-screen suspension, and a still frame under prefers-reduced-motion. three.js is fetched by dynamic import() the first time such a scene mounts, once per page, shared by all six.

If it cannot load, the surface paints a still poster rather than an empty box — the same way the WebGL2 tier degrades when WebGL2 is missing.

import * as THREE from "three";
Galaxy.useThree(THREE);                                   // bring your own — zero network
Galaxy.create("spiralForge", "#hero", { stars: 400000 });

Galaxy.create("eventHorizon", "#hole", { threeUrl: "/vendor/three.module.js" });
Galaxy.rendererOf("nebula");                              // "2d" | "webgl2" | "three"

The six

Scene What is actually real
eventHorizon photons integrated through the Schwarzschild metric (d²u/dφ² = -u + 3/2·rs·u²). The photon ring, the Einstein ring of the background starfield and the far side of the disk bent up over the top all emerge from the geodesics. Relativistic Doppler shift and beaming (I ∝ δ⁴) give the disk its bright/dim asymmetry.
molecularCloud a 128³ Data3DTexture raymarched in the volume's own local space, lit from within by an embedded protostar via a secondary Beer–Lambert shadow ray and a Henyey–Greenstein phase function. Rotation produces true parallax and self-occlusion.
spiralForge 340,000 stars in one draw call, each orbit integrated in the vertex shader against a flat rotation curve — no per-frame CPU work. Density-wave arms shear because ω varies with radius; colour follows a blackbody locus from a mass–temperature relation.
ringedWorld Rayleigh single scattering for a blue limb and a warm reddened terminator, plus mutual shadowing: the rings cast a real shadow on the planet (carrying their own Cassini gaps as bright lines) and the planet casts a real shadow back on the rings.
gravitySim true GPGPU — particle state lives in float render targets and never returns to the CPU. A kick–drift symplectic leapfrog keeps the disks stable; two attractors on an eccentric Kepler orbit raise tidal bridges and tails at each pericentre. The pointer is a third mass.
starGlare a hand-rolled HDR chain with no three.js addons: bright pass → progressive downsample/upsample bloom → anamorphic streak → lateral chromatic aberration → filmic tonemap.

Fixed

A shader whose program failed to build crashed instead of falling back. glPosterFallback reached for the 2D context unconditionally, but a canvas that already holds a live WebGL2 context can never hand one back — so the "graceful" path threw Cannot set properties of null. This affected the WebGL2 tier as shipped in 3.3.0, not only the new one. The poster now paints the host element with the equivalent CSS gradient when there is no 2D context.

Verified

  • npm run validate green on Node 18, 20 and 22 — manifest → lint → minify → test.mjstest-mcp.mjs
  • new tests keep the tier optional: three is not a dependency, is never statically imported, is loaded by dynamic import, and — because terser had already dead-code-eliminated the whole tier once — the minified bundle is checked for it too
  • every scene rendered headless and inspected, with the CDN intercepted so the real lazy-import path runs offline
  • both contracts measured rather than asserted: under prefers-reduced-motion all six paint a real still frame with zero rAF ticks; with three.js unreachable all six fall back to a poster with no throws

Counts

86 animations — 2D 72 · WebGL2 8 · three.js 6 (optional) · plus 13 UI components.

<link rel="stylesheet" href="https://unpkg.com/galaxyjs@3/galaxy.min.css">
<script src="https://unpkg.com/galaxyjs@3/galaxy.min.js"></script>