Skip to content
Docs
Open Promoeyes
terrain-bands

terrain-bands

PRIMITIVES — "One ground, three worlds." Three scenes on one tag: <heightfield>. A seeded-fBm plane is terrain, mountains and sea depending on two numbers — amplitude and ridged — and on the material you hang on it.

Read the rig's notes
  1. TERRAIN    (7.0s) — rolling dune country at amplitude 260, ridged 0.
                         Vertex colours ramp sand→ochre with a sun-dot shade
                         term, exactly the three.js terrain demo's canvas
                         shading, computed per vertex instead.
  2. MOUNTAINS  (7.0s) — the SAME generator at amplitude 980, ridged 1. The
                         1-|n| crease is the only thing that changed; fog
                         does the rest by stacking the ridgelines.
  3. SEA        (7.5s) — amplitude 22, animate 0.35, over a static seabed.
                         Displacement moves to the GPU here and rides inside
                         a MeshPhysicalMaterial, so transmission, ior and the
                         HDR environment survive on a MOVING surface — the
                         swell reflects and refracts instead of just wobbling.

Chains (match key → scenes):
  land   S1 dunes → S2 range → S3 sea surface. One classic match-move all the
         way: the ground never leaves frame, it only changes what it is.
  haze-a / haze-b — every scene, colour/pose morph.

Look: golden-hour desert cooling into night water.
S1 sand #efd1b5 sky over #c98f63/#7a4a33 ground · S2 the same sky pushed cold
(#cbb6c8 → #4a3a52) · S3 night water #0b1a2e/#123a5c under a #dfe8f5 horizon.
Every scene carries the same two-lobe haze rig:
  haze-a  warm key glow, sized so the radial falloff is in frame
  haze-b  the cold counter-lobe, low and wide behind the ridgeline

Units: THE MEASUREMENT STANDARD — the ground is 7500mm × 7500mm and the
camera stands 620mm above it, i.e. a 7.5m tabletop landscape seen from
knee height. Fog density 0.00026 puts the e-fold at ~3.8m, which is what
makes the far edge of the plane dissolve instead of ending on a hard line.
Multiply size, camera and amplitude by 10 (and divide density by 10) for an
epic-vista read at identical proportions.

── AUTHORED AS BANDS ────────────────────────────────────────────────────
This is promos/primitives/terrain/terrain.promo with every field written as a
TABLE OF NUMBERS instead of named scalars. perlin / fBm / ridging are not
three operators — they are one sum of noise bands, and a band is four
numbers:

  bands            // freq   amp   fold  warp
    4.5    368.59   0     0        one row  = perlin
    22.5    73.72   0     0        several  = fBm, and the row RATIOS
    112.5   14.74   0     0        are lacunarity and gain
  colors           // at   colour
    0    #6b3f2c
    1    #f2d9bd

`amp` is that band's real contribution, so `amplitude` is the column sum.
`fold` is ridging. Nothing is named; the operator is the row's shape.

The ppug codec already parses this — any tag whose children are numeric
rows is a property channel — and packages/core/xml-scene.ts lowers the table
back onto the same generator scalars, so this reel and terrain.promo
parse to the SAME document and render the same frames. Every cell is
printed to the shortest decimal that still recovers those scalars at
float32, the width of a GLSL uniform.

Preview: /packages/runtime/index.html?project=promos/primitives/terrain/terrain-bands.promo
Topic
terrain
Scenes
3
Kind
reference rig
//
    PRIMITIVES — "One ground, three worlds." Three scenes on one tag:
    <heightfield>. A seeded-fBm plane is terrain, mountains and sea depending on
    two numbers — amplitude and ridged — and on the material you hang on it.

      1. TERRAIN    (7.0s) — rolling dune country at amplitude 260, ridged 0.
                             Vertex colours ramp sand→ochre with a sun-dot shade
                             term, exactly the three.js terrain demo's canvas
                             shading, computed per vertex instead.
      2. MOUNTAINS  (7.0s) — the SAME generator at amplitude 980, ridged 1. The
                             1-|n| crease is the only thing that changed; fog
                             does the rest by stacking the ridgelines.
      3. SEA        (7.5s) — amplitude 22, animate 0.35, over a static seabed.
                             Displacement moves to the GPU here and rides inside
                             a MeshPhysicalMaterial, so transmission, ior and the
                             HDR environment survive on a MOVING surface — the
                             swell reflects and refracts instead of just wobbling.

    Chains (match key → scenes):
      land   S1 dunes → S2 range → S3 sea surface. One classic match-move all the
             way: the ground never leaves frame, it only changes what it is.
      haze-a / haze-b — every scene, colour/pose morph.

    Look: golden-hour desert cooling into night water.
    S1 sand #efd1b5 sky over #c98f63/#7a4a33 ground · S2 the same sky pushed cold
    (#cbb6c8 → #4a3a52) · S3 night water #0b1a2e/#123a5c under a #dfe8f5 horizon.
    Every scene carries the same two-lobe haze rig:
      haze-a  warm key glow, sized so the radial falloff is in frame
      haze-b  the cold counter-lobe, low and wide behind the ridgeline

    Units: THE MEASUREMENT STANDARD — the ground is 7500mm × 7500mm and the
    camera stands 620mm above it, i.e. a 7.5m tabletop landscape seen from
    knee height. Fog density 0.00026 puts the e-fold at ~3.8m, which is what
    makes the far edge of the plane dissolve instead of ending on a hard line.
    Multiply size, camera and amplitude by 10 (and divide density by 10) for an
    epic-vista read at identical proportions.

    ── AUTHORED AS BANDS ────────────────────────────────────────────────────
    This is promos/primitives/terrain/terrain.promo with every field written as a
    TABLE OF NUMBERS instead of named scalars. perlin / fBm / ridging are not
    three operators — they are one sum of noise bands, and a band is four
    numbers:

      bands            // freq   amp   fold  warp
        4.5    368.59   0     0        one row  = perlin
        22.5    73.72   0     0        several  = fBm, and the row RATIOS
        112.5   14.74   0     0        are lacunarity and gain
      colors           // at   colour
        0    #6b3f2c
        1    #f2d9bd

    `amp` is that band's real contribution, so `amplitude` is the column sum.
    `fold` is ridging. Nothing is named; the operator is the row's shape.

    The ppug codec already parses this — any tag whose children are numeric
    rows is a property channel — and packages/core/xml-scene.ts lowers the table
    back onto the same generator scalars, so this reel and terrain.promo
    parse to the SAME document and render the same frames. Every cell is
    printed to the shortest decimal that still recovers those scalars at
    float32, the width of a GLSL uniform.

    Preview: /packages/runtime/index.html?project=promos/primitives/terrain/terrain-bands.promo
promo#terrain
  // =======================================================================
  // SCENE 1 · TERRAIN — rolling dunes, ridged=0, colours baked per vertex
  // =======================================================================
  scene#t1-terrain(duration=7 transition=match)
    camera(type=perspective fov=55 near=5 far=24000 position="0 1250 3400" look_at="0 0 -1500")
      position
        0 0 12