acron.noise

Deterministic value noise + seeded PRNG — the determinism primitives.

Built for worlds baked from code: bake terrain from THESE functions into float fields and the renderer never re-derives a height — it samples exactly what the physics sampled. No shader/CPU drift, ever, which is only true because the noise is built on exact 32-bit integer hashing (wrapping multiplies and unsigned shifts), not on fract(sin()) chaos that rounds differently on every platform. One seed, one world, on any machine.

Two forms, one contract:

  • The scalar functions (hash2i(), vnoise(), fbm(), ridged(), pvn()) are plain Python on ints and floats: tests, scatter placement, a probe of the height under one prop.

  • field() evaluates one of them on a regular grid in the engine (acron.raster.ValueNoise, C++ — a 2048² six-octave fbm in about a tenth of a second), for the bake. It is bit-identical to the scalar form sampled at (x0 + i * dx, y0 + j * dy): the same IEEE double operations in the same order (the native file is built with floating-point contraction off, so no fused multiply-add rounds once where Python rounds twice). C++ games call ValueNoise directly.

RNG([seed])

mulberry32 — tiny, fast, reproducible: one seeded stream per consumer.

Global Functions

clamp(v: float, a: float, b: float) → float
dmod(a: float, n: float) → float
fbm(x: float, y: float, octaves: int = 4, lac: float = 2.07, gain: float = 0.5, seed: int = 0) → float

Fractal sum of value noise, 0..1.

field(kind: str, width: int, height: int, x0: float = 0.0, y0: float = 0.0, dx: float = 1.0, dy: float = 1.0, *, seed: int = 0, octaves: int = 4, lac: float | None = None, gain: float = 0.5, per: int = 1, single: bool = False) → array

kind ("value", "fbm", "ridged" or "periodic") on a width x height grid: sample (i, j) at (x0 + i * dx, y0 + j * dy), row-major with j outermost, as an array('d') — or array('f') when single (what acron.gpu.float_texture() uploads without a conversion).

Bit-identical to the scalar functions at the same points. Evaluated in the engine when it ships acron.raster; in Python (slowly — a texel at a time) otherwise, with the same result.

hash2i(x: int, y: int, seed: int = 0) → float

Integer hash of a lattice point -> [0, 1). Exact: wrapping 32-bit multiplies of the low 32 bits of each argument.

lerp(a: float, b: float, t: float) → float
pvn(x: float, y: float, per: int, seed: int) → float

Periodic value noise, for the seamless detail tile.

ridged(x: float, y: float, octaves: int = 4, lac: float = 2.11, gain: float = 0.5, seed: int = 0) → float

Ridged multifractal — sharp crests, good for mountain rims. 0..1.

sstep(e0: float, e1: float, x: float) → float
vnoise(x: float, y: float, seed: int = 0) → float

2D value noise, quintic smoothstep (C2 continuous -> clean normals).