nx_worley_noise.nx
buildroot/runtime/nx_worley_noise.nx
about
nx_worley_noise.nx -- Worley cellular noise (F1 distance) in Q10.
Cross-cutting Substrate A primitive per
nxc2/docs/NISHI_GAME_ENGINE_ROADMAP.md.
Worley 1996 "A Cellular Texture Basis Function" (SIGGRAPH '96).
Divide the plane into uniform cells; place one feature point per
cell at a hash-determined position; the noise value at any query
point is the distance to the nearest feature point (F1). Produces
natural-looking cobblestone, rock, dried-mud, water-cell, and lizard-
scale textures that Perlin FBM cannot.
Algorithm:
1. Cell index (cx, cy) = floor(x / Q), floor(y / Q).
2. Local position within cell (fx, fy) = x - cx*Q, y - cy*Q.
3. For each neighbor cell (cx+dx, cy+dy) with dx, dy in {-1, 0, 1}:
a. Hash (ncx, ncy, seed) to a feature-point offset in [0, Q).
b. Feature absolute (relative to current cell origin):
(dx*Q + ox, dy*Q + oy).
c. Squared distance from local query point to feature point.
4. F1 = sqrt(min of those 9 squared distances).
3x3 neighborhood guarantees correctness because the feature point
closest to (fx, fy) cannot live more than 1 cell away in any axis
when feature points are confined to [0, Q) per cell.
Determinism: hash is pure LCG over (cx, cy, seed). Same query +
seed -> byte-equal output everywhere.
Fixed-point strategy: distances kept in Q20 (Q^2) until the final
integer-sqrt converts to Q10. Avoids the precision loss that would
hit a per-step Q10 divide.
Loss audit: only information-discarding op is the integer sqrt
(truncates fractional bit; ~1% error worst case). All other ops
exact in i64.
genealogy_id: worley_1996_cellular
lineage_id: nx_worley_noise_q10_f1
dependencies 3 imports · 0 importers
imports: nx_syscalls.nxnx_tier.nxnx_vecmath.nx
imported by: nobody (leaf or entry point)
structs
| none |
consts
| 60 | const NX_MAGIC_1024: i64 = 1024 |
| 61 | const NX_MAGIC_16777216: i64 = 16777216 |
| 62 | const NX_MAGIC_1500: i64 = 1500 |
| 63 | const NX_MAGIC_12345: i64 = 12345 |
| 64 | const NX_MAGIC_1448: i64 = 1448 |
| 67 | const NX_WORLEY_Q: nx_int = 1024 |
| 71 | const NX_WORLEY_LCG_A: nx_int = 48271 |
| 72 | const NX_WORLEY_LCG_M: nx_int = 2147483647 |
| 77 | const NX_WORLEY_HASH_CX: nx_int = 2654435761 |
| 78 | const NX_WORLEY_HASH_CY: nx_int = 1597334677 |
| 84 | const NX_WORLEY_BAND_AT_FEATURE: nx_int = 0 // F1 < 64 (~0.06) |
| 85 | const NX_WORLEY_BAND_NEAR: nx_int = 1 // 64..255 |
| 86 | const NX_WORLEY_BAND_MID: nx_int = 2 // 256..639 |
| 87 | const NX_WORLEY_BAND_FAR: nx_int = 3 // 640..1023 |
| 88 | const NX_WORLEY_BAND_CORNER: nx_int = 4 // >= 1024 (cell-corner range) |
| 90 | const NX_WORLEY_THRESH_AT: nx_int = 64 |
| 91 | const NX_WORLEY_THRESH_NEAR: nx_int = 256 |
| 92 | const NX_WORLEY_THRESH_MID: nx_int = 640 |
| 93 | const NX_WORLEY_THRESH_FAR: nx_int = 1024 |
functions
| 96 | func nx_worley_noise_band_is_valid(b: nx_int) -> nx_int |
| 106 | func nx_worley_noise_classify(value_q10: nx_int) -> nx_int |
| 119 | func _isqrt(n: nx_int) -> nx_int { return vm_isqrt(n) } |
| 126 | func _hash_cell(cx: nx_int, cy: nx_int, seed: nx_int) -> nx_int |
| 141 | func _hash_to_x_offset(h: nx_int) -> nx_int |
| 145 | func _hash_to_y_offset(h: nx_int) -> nx_int |
| 151 | func _floor_div_q(n: nx_int) -> nx_int |
| 161 | func nx_worley_noise(x_q10: nx_int, y_q10: nx_int, seed: nx_int) -> nx_int |
| 199 | func main() -> i64 |