ludic/docs/language/noise/noise-fbm2.md
Orkuncakilkaya a4f1494a04
All checks were successful
docs / build-and-deploy (push) Successful in 2s
feat(stdlib): add Noise.* — deterministic fixed-point procedural noise (#3)
A Noise.* namespace for procedural generation, implemented entirely in Q16.16
fixed point over an integer permutation hash so a seed reproduces the exact same
field on every platform and run (native/headless/wasm) — the determinism edge
over float noise that drifts across CPUs.

  - value2 / perlin2 / simplex2  — value, gradient, and simplex noise -> [-1,1]
  - fbm2(x,y,seed,octaves)       — fractal Brownian motion (octaves of simplex)
  - cellular2 / cellular2_id     — Worley F1 distance + nearest-cell id
  - unit(n)                      — remap [-1,1] -> [0,1]

Covers issue phases 1–2 fully plus cellular from phase 3; domain warp, ridged/
billow, and sample1/sample3 remain as follow-ups. Pure integer IR, C-free;
cellular/fbm reuse the math prelude's fx_sqrt.

- examples/library/noise.ludic: asserts the invariants a fixed-point generator
  must hold (Perlin == 0 at lattice points, every sampler within [-1,1],
  reproducibility, seed sensitivity, non-negative cellular distance). Wired into
  `x test` (now 52 passed).
- docs: a new Noise section + per-symbol pages; inventory and coverage pass.
- seed regenerated; `x bootstrap-cfree` fixpoint holds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-30 21:50:50 +03:00

1.3 KiB
Raw Permalink Blame History

id name category kind tokens sig tip order ns member
noise-fbm2 Noise.fbm2 noise namespace-method Noise.fbm2 Noise.fbm2(x, y, seed, octaves) -> fixed Fractal Brownian motion — octaves of simplex, in [-1, 1]. 4 Noise fbm2

Samples fractal Brownian motion at (x, y): it stacks octaves layers of simplex2, each at double the frequency and half the amplitude of the last, and normalises by the total amplitude so the result stays a fixed in [-1, 1]. Layering this way adds fine detail on top of broad shapes — the standard recipe for natural-looking terrain, clouds, and marble. More octaves means more detail (and more cost); 4–6 is typical.

Each octave uses a different derived seed, and the whole thing is deterministic in fixed point across platforms and runs.

Parameters:

  • x, y — the sample coordinates (fixed)
  • seed — the base field selector (each octave derives from it)
  • octaves — how many layers to sum (higher = more detail)
program Fbm {
  entry {
    let seed = 1337
    let h = Noise.fbm2(fixed(2) / fixed(7), fixed(9) / fixed(7), seed, 5)
    print(Math.floor(Noise.unit(h) * fixed(100)))   # detailed 0..100 height
  }
}