Skip to content
Docs
Open Promoeyes
glow

glow

GLOW — one material, forty ways to spend it. The material under study:

Read the rig's notes
  standard#glow(color=#1a1206 emissive=#ffb347 emissive-intensity=2.2 metalness=0 roughness=1)

WHAT EACH KNOB IS FOR
  emissive=#ffb347          the colour the surface GIVES OFF, added after lighting: the same
                            on the lit and the shadow side.
  emissive-intensity=2.2    a multiplier in LINEAR light, no ceiling. 1 = the hex as typed;
                            past ~1.6 the bloom picks it up (see BLOOM).
  color=#1a1206             the base, what the key reflects. The glow hue at ~10 % value:
                            OFF, the tube reads as dark amber glass, not orange plastic.
  roughness=1               no specular: the key leaves no white stripe to bloom.
  metalness=0               metal has no diffuse and mirrors the HDR: a gold bar, not a neon.

HOW BLOOM SEES IT (step(name=bloom …) is SELECTIVE by default)
  The bloom renders the scene a second time with every non-light material swapped for black;
  "light" = emissive non-black and emissive-intensity ≥ 0.01 (emissive_min). Light materials
  keep their OWN shader there, so a bright LIT base blooms too — keep the base dark.
  Everything else renders black in that pass, so a phone in front CUTS the halo (scene 11).
  The bright-pass keeps a pixel when the linear luminance passes `threshold`:
      L = 0.2126 R + 0.7152 G + 0.0722 B   of emissive(linear) × emissive-intensity
      #ffb347 → (1.000 0.451 0.063) → L 0.54 per unit → blooms from ×1.58 at threshold 0.85
  smooth-width 0.01 (default) makes that a cliff: a value keyed across it pops the halo on.
  Engine: packages/engine/engine/post/classic/selective-bloom-pass.ts, gpu/post/bloom.ts.

MATCH LUMINANCE, NOT INTENSITY (scene 03)
    hue        L/unit   blooms from (thr 0.85)   × for L 1.2
    #ffb347    0.54     ×1.58                     ×2.2   ← glow
    #7ad7ff    0.60     ×1.42                     ×2.0   ← glow-cyan
    #ff3d7f    0.26     ×3.25                     ×4.6   ← glow-pink
    #2f6bff    0.18     ×4.63                     ×6.5   ← glow-blue
  I = target L / L(hue). A blue neon that "won't glow" needs ×3 the amber's number.

GLOW IS NOT LIGHT
  An emissive surface lights nothing: no pool on the floor, no rim on the phone. A practical
  is a glow + a point light at the same spot and colour, its intensity keyed on the same
  curve (scenes 04, 06, 07, 11, 13). decay=2 in mm: radiance ≈ albedo/π × I/d².

IT IS A CHANNEL — and the WebGPU TRAP that comes with it
  `emissive_intensity` rows under a mesh node key it per node (a named material is FORKED per
  attachment). path3d is a factory: its channels go under `properties` (scene 06).
  TRAP (three r185 NodeMaterialObserver): a changed material value is noticed by the FIRST
  render pass of the frame only. The bloom's light pass then keeps the old value — a ring
  keyed ×2.2 → ×4.6 brightens on screen but never grows a halo (measured on a probe).
  A node whose world matrix changes is refreshed in every pass, so EVERY node here that keys
  emissive also moves: a spin about its symmetry axis, a drift, or a moving parent.
  Without motion, author the brightness as a static attr instead of a key.

PARTICLES WITH REPEAT
  One `repeat` + `vary kind=expr` writes a whole field: positions on a ring or a perimeter
  from the index `i`, key TIMES staggered by `i`, values from sin(). The swarm (04), the
  comets (05), the shockwaves (07), the marquee (09), the equaliser (10), the tunnel (13), the
  vortex (15), the fireworks (16), the painting (17) and the rain (18) are one prototype each.
  A pinned bar (10) scales a PIVOT group whose origin is the pinned end; a spiral (15) is a
  turning group around a shrinking one. Keyed position/scale on a PRIMITIVE is a delta on its
  authored value (18 relies on it); a `g` takes its transform as rows only — its position=,
  rotation= and scale= attrs are ignored, so every static group here carries one-row keys.
  A camera keyed with `position` rows keeps its FIRST look direction; an orbit (28) keys
  position and look_at together as frame keyframes.

TONE CURVE
  bloom → output(neutral) → ssaa 4 everywhere (tonemapping/tonemapping.promo: neutral for sets
  with a screen). Past ~×4 an amber core rolls off to cream; hot blue leans violet.

THE SCENES
  01  RECIPE      the recipe beside three wrong ones, then all four switched OFF
  02  LADDER      ×0.6 → ×8 on one hue: the halo starts at ×1.58
  03  MATCH       four hues at ×2.2 (top) and luminance-matched (bottom)
  04  SWARM       140 fireflies converge into a halo round the phone, flaring as they land
  05  ATOM        three comets (26 beads each, one repeat per orbit) circle the phone
  06  LIQUID NEON one path3d tube, its `d` keyed: ring → heart → bolt, a cyan echo behind
  07  PING        four shockwave rings run across the floor from the phone's foot
  08  BURN        the phone burns away in amber embers and sets as a neon bolt (morph)
  09  MARQUEE     32 bulbs: a comet chase twice round, then full blaze
  10  EQUALISER   48 bars round the phone, each pinned at its inner end, dancing on sin()
  11  ECLIPSE     the phone slides in front of the halo; its practical rises with it
  12  BOKEH       glow dots far behind + dof: soft coins, the screen sharp
  13  TUNNEL      24 rings struck one after another ahead of a camera flying to the phone
  14  OUTRUN      a streaming synthwave grid, a sun striped by black non-lights
  15  VORTEX      160 motes spiral into the glass: turn one group, scale the one inside
  16  FIREWORKS   three shells, Fibonacci-sphere sparks flown out and dropped
  17  PAINTING    a long exposure: 200 beads light along ∞ and stay lit
  18  RAIN        110 glow drops falling on a loop (delta rows + hold snaps)
  19  TRACE       the bolt hands back to the phone with morph=outline in amber
  20  HELIX       a double helix of beads and rungs; a pulse climbs it twice
  21  PULSE KNOT  a dim (2,3) torus knot with three bright packets running round it
  22  STARS       stars light, lines grow between them: the app's bolt as a constellation
  23  OPEN        a hanging neon OPEN sign whose E buzzes on its own tube
  24  SCOPE       one tube keyed through flat → sine → beat → heartbeat → square
  25  FACE SCAN   a laser bar sweeps the glass; a 10 × 20 dot mesh lights where it passes
  26  PORTAL      gyroscope rings snap open and the phone flies through the membrane
  27  LANTERNS    45 sky lanterns rise and sway; dof turns the far ones into coins
  28  SATURN      the phone as a planet in a tilted ring of 360 ice grains
  29  CODE RAIN   a 24 × 18 wall of green cells, a falling head per column
  30  LED WALL    392 LEDs sampled from a formula: a diagonal wave, then a ripple
  31  WIRE CAGE   two glowing wire cubes counter-rotating round the phone
  32  RUNWAY      approach lights: waves running down to the phone through fog
  33  SPARKLER    220 sparks on true parabolas (two nodes, two easings)
  34  RADAR       a sweeping arm lights each blip the instant it crosses it
  35  FOOTSTEPS   glowing prints walk a Bézier up to the phone
  36  DOMINOES    glow tiles topple on edge pivots into the phone, which wakes
  37  PENDULUMS   a 15-pendulum wave drifting through snake and braid
  38  SKYLINE     dusk: ~490 windows switch on in a wave across five towers
  39  BLOSSOM     a flower of light opens with an overshoot, petal by petal
  40  END CARD    text3d in glow, struck like a sign, embers rising

UI: glow.screens.html → scripts/html-screens.mts (glow.sections.json) → t-gw-phone.
Preview: http://localhost:4444/runtime?project=promos/primitives/materials/glow/glow.promo
Scenes
40
Kind
reference rig
//
    GLOW — one material, forty ways to spend it. The material under study:

      standard#glow(color=#1a1206 emissive=#ffb347 emissive-intensity=2.2 metalness=0 roughness=1)

    WHAT EACH KNOB IS FOR
      emissive=#ffb347          the colour the surface GIVES OFF, added after lighting: the same
                                on the lit and the shadow side.
      emissive-intensity=2.2    a multiplier in LINEAR light, no ceiling. 1 = the hex as typed;
                                past ~1.6 the bloom picks it up (see BLOOM).
      color=#1a1206             the base, what the key reflects. The glow hue at ~10 % value:
                                OFF, the tube reads as dark amber glass, not orange plastic.
      roughness=1               no specular: the key leaves no white stripe to bloom.
      metalness=0               metal has no diffuse and mirrors the HDR: a gold bar, not a neon.

    HOW BLOOM SEES IT (step(name=bloom …) is SELECTIVE by default)
      The bloom renders the scene a second time with every non-light material swapped for black;
      "light" = emissive non-black and emissive-intensity ≥ 0.01 (emissive_min). Light materials
      keep their OWN shader there, so a bright LIT base blooms too — keep the base dark.
      Everything else renders black in that pass, so a phone in front CUTS the halo (scene 11).
      The bright-pass keeps a pixel when the linear luminance passes `threshold`:
          L = 0.2126 R + 0.7152 G + 0.0722 B   of emissive(linear) × emissive-intensity
          #ffb347 → (1.000 0.451 0.063) → L 0.54 per unit → blooms from ×1.58 at threshold 0.85
      smooth-width 0.01 (default) makes that a cliff: a value keyed across it pops the halo on.
      Engine: packages/engine/engine/post/classic/selective-bloom-pass.ts, gpu/post/bloom.ts.

    MATCH LUMINANCE, NOT INTENSITY (scene 03)
        hue        L/unit   blooms from (thr 0.85)   × for L 1.2
        #ffb347    0.54     ×1.58                     ×2.2   ← glow
        #7ad7ff    0.60     ×1.42                     ×2.0   ← glow-cyan
        #ff3d7f    0.26     ×3.25                     ×4.6   ← glow-pink
        #2f6bff    0.18     ×4.63                     ×6.5   ← glow-blue
      I = target L / L(hue). A blue neon that "won't glow" needs ×3 the amber's number.

    GLOW IS NOT LIGHT
      An emissive surface lights nothing: no pool on the floor, no rim on the phone. A practical
      is a glow + a point light at the same spot and colour, its intensity keyed on the same
      curve (scenes 04, 06, 07, 11, 13). decay=2 in mm: radiance ≈ albedo/π × I/d².

    IT IS A CHANNEL — and the WebGPU TRAP that comes with it
      `emissive_intensity` rows under a mesh node key it per node (a named material is FORKED per
      attachment). path3d is a factory: its channels go under `properties` (scene 06).
      TRAP (three r185 NodeMaterialObserver): a changed material value is noticed by the FIRST
      render pass of the frame only. The bloom's light pass then keeps the old value — a ring
      keyed ×2.2 → ×4.6 brightens on screen but never grows a halo (measured on a probe).
      A node whose world matrix changes is refreshed in every pass, so EVERY node here that keys
      emissive also moves: a spin about its symmetry axis, a drift, or a moving parent.
      Without motion, author the brightness as a static attr instead of a key.

    PARTICLES WITH REPEAT
      One `repeat` + `vary kind=expr` writes a whole field: positions on a ring or a perimeter
      from the index `i`, key TIMES staggered by `i`, values from sin(). The swarm (04), the
      comets (05), the shockwaves (07), the marquee (09), the equaliser (10), the tunnel (13), the
      vortex (15), the fireworks (16), the painting (17) and the rain (18) are one prototype each.
      A pinned bar (10) scales a PIVOT group whose origin is the pinned end; a spiral (15) is a
      turning group around a shrinking one. Keyed position/scale on a PRIMITIVE is a delta on its