nx_world_shader_cumulus_canonical_t156.nx
buildroot/runtime/nx_world_shader_cumulus_canonical_t156.nx
about
nx_world_shader_src.nx -- THE WORLD SHADER, WRITTEN ONCE (gameengine GE44 R-G, 2026-09-04).
The voxel world pass that nx_game_page_emit ships hand-written twice (a GLSL FSH for the WebGL2 door and a WGSL
module for the WebGPU door) is authored here ONCE as shader-IR builder calls and emitted to BOTH dialects by
nx_wgsl. Every function below is the hand WGSL, statement for statement (vx, h21, h31, pal9, sky, struct Hit,
march, shade, the fragment entry); the vertex entry is the backend's own fullscreen triangle (shsrc_fullscreen_tri).
Deliberate deltas from the hand text, all semantic no-ops: compound assignments are spelled x=(x+y); unsigned
constants are casts (u32(0) / uint(0)) because the GLSL backend spells a u32 literal without its suffix and a bare 0
beside a uint is a GLSL type error; the WebGPU top-left fragment origin is carried as the uniform `yflip` (1 on the
WebGPU door, 0 on WebGL2) instead of a per-dialect edit, so ONE source serves both doors. The uniform block is
declared ONCE here (ws_world_uniforms) and `nx_wgsl layout` derives its memory layout from it.
GE55 (2026-09-05): the world module now takes the sim's RAW state words as its uniform block (ws_world_uniforms_raw,
the same 40-word table as nx_wasm_craft UR_*) and derives every float in upk() into module-scope private state, so
the page packs nothing and computes nothing; ws_world_uniforms (the f32 block) stays as the R-F layout ruler fixture.
license_tier: ORIGINAL
dependencies 1 imports · 0 importers
imports: nx_shader_ir.nx
imported by: nobody (leaf or entry point)
structs
| none |
consts
| 246 | const CC_BODY_XZ: *u8 = "64.0" |
| 247 | const CC_BODY_Y: *u8 = "48.0" |
| 248 | const CC_DETAIL_XZ: *u8 = "8.0" |
| 249 | const CC_DETAIL_Y: *u8 = "8.0" |
| 250 | const CC_OCTAVE_LACUNARITY: *u8 = "2.0" |
| 251 | const CC_OCTAVE_PERSISTENCE: *u8 = "0.5" |
| 253 | const CB_BASE: *u8 = "180.0" // the incumbent sheet's height in blocks, now the slab base |
| 254 | const CB_TOP: *u8 = "300.0" |
| 255 | const CB_RLO: *u8 = "24.0" // density ramps in over this many blocks above the base |
| 256 | const CB_RHI: *u8 = "48.0" // and out over this many below the top |
| 257 | const CB_CELL: *u8 = "180.0" // one noise cell in blocks, horizontal |
| 258 | const CB_CELLY: *u8 = "120.0" // and vertical (flatter cells read as stratus) |
| 259 | const CB_DRIFT_X: *u8 = "240.0" // the incumbent sheet's drift divisors, kept so the motion does not change |
| 260 | const CB_DRIFT_Z: *u8 = "540.0" |
| 261 | const CB_THR0: *u8 = "0.78" // coverage threshold at cld=0 |
| 262 | const CB_THRK: *u8 = "0.30" // and how far cld=1 lowers it |
| 263 | const CB_GAIN: *u8 = "1.4" |
| 264 | const CB_STEPS: *u8 = "48" |
| 265 | const CB_STEPS_F: *u8 = "48.0" |
| 266 | const CB_SIGMA: *u8 = "0.04" // extinction per block of unit density |
| 267 | const CB_LIT0: *u8 = "0.70" // ambient at the base |
| 268 | const CB_LIT1: *u8 = "0.30" // brighter toward the top |
| 269 | const CB_SUNK: *u8 = "0.15" // silver toward the sun |
| 273 | const CB_EROSION: *u8 = "0.22" |
| 274 | const CB_SUN_Y_MIN: *u8 = "0.01" |
| 275 | const CB_LIGHT_DISTANCE: *u8 = "480.0" |
| 276 | const CB_LIGHT_STEPS: *u8 = "6" |
| 277 | const CB_LIGHT_STEPS_F: *u8 = "6.0" |
| 278 | const CB_VIEW_DISTANCE: *u8 = "1400.0" |
| 279 | const CB_PHASE_G: *u8 = "0.35" |
| 280 | const CB_AMBIENT: *u8 = "0.85" |
| 281 | const CB_DIRECT: *u8 = "0.72" |
| 686 | const SD_GRAIN_PER_BLOCK: *u8 = "32.0" // facets per block edge: 3 cm at a 1 m block, coarse beach sand |
| 687 | const SD_GRAIN_SLOPE: *u8 = "1.2" // facet steepness as a normal slope |
| 688 | const SD_RIPPLE_PER_BLOCK: *u8 = "9.0" // wind ripples per block: an 11 cm wavelength at a 1 m block |
| 689 | const SD_RIPPLE_SLOPE: *u8 = "0.45" // crest slope |
| 690 | const SD_RIPPLE_DX: *u8 = "0.8" // ripple normal heading (unit): the wind heading, a data hook |
| 691 | const SD_RIPPLE_DZ: *u8 = "0.6" |
| 692 | const SD_PATCH: *u8 = "0.25" // ripple phase jitter per 4-block patch so the field is not one sine |
| 693 | const SD_TAU: *u8 = "6.2831853" |
| 694 | const SD_QUARTER_TURN: *u8 = "1.5707963" |
| 695 | const SD_EIGHTH_TURN: *u8 = "0.7853982" |
| 696 | const SD_RING_DIRS: *u8 = "8" |
| 697 | const SD_RING_STEPS: *u8 = "24" // SD_RING_DIRS x SD_WET_R |
| 698 | const SD_WET_R: *u8 = "3.0" // wet band reach in cells |
| 699 | const SD_WET_DRY: *u8 = "4.0" // SD_WET_R + 1: no water within reach |
| 700 | const SD_WET_DARK: *u8 = "0.55" // wet albedo multiplier |
| 701 | const SD_FILM_POW: *u8 = "48.0" |
| 702 | const SD_FILM_GAIN: *u8 = "0.55" |
| 703 | const SD_SHEEN_GAIN: *u8 = "0.10" |
| 704 | const SD_GLINT_POW: *u8 = "96.0" |
| 705 | const SD_GLINT_GAIN: *u8 = "0.35" |
| 706 | const SD_GLINT_FRAC: *u8 = "0.9" // facets whose hash exceeds this are quartz glints |
| 707 | const SD_NDV_FLOOR: *u8 = "0.15" // the footprint stretch floor at grazing angles |
| 708 | const SD_SHADOW_SPEC: *u8 = "0.2" // in a block shadow the film keeps its sky sheen and loses the sun |
| 709 | const SD_TWO: *u8 = "2.0" |
| 710 | const SD_HALF: *u8 = "0.5" |
functions
| 18 | func ws_f(m: *i64, s: *u8) -> i64 { return sir_lit(m, s, T_F32) } |
| 19 | func ws_i(m: *i64, s: *u8) -> i64 { return sir_lit(m, s, T_I32) } |
| 21 | func ws_u(m: *i64, s: *u8) -> i64 { return sir_cast(m, sir_lit(m, s, T_I32), T_U32) } |
| 22 | func ws_id(m: *i64, n: *u8, ty: i64) -> i64 { return sir_ident(m, n, ty) } |
| 23 | func ws_bin(m: *i64, op: *u8, a: i64, b: i64, ty: i64) -> i64 { return sir_bin(m, op, a, b, ty) } |
| 24 | func ws_cmp(m: *i64, op: *u8, a: i64, b: i64) -> i64 { return sir_bin(m, op, a, b, T_BOOL) } |
| 25 | func ws_and(m: *i64, a: i64, b: i64) -> i64 { return sir_bin(m, "&&" as *u8, a, b, T_BOOL) } |
| 26 | func ws_or(m: *i64, a: i64, b: i64) -> i64 { return sir_bin(m, "||" as *u8, a, b, T_BOOL) } |
| 27 | func ws_sw(m: *i64, a: i64, sel: *u8, ty: i64) -> i64 { return sir_swz(m, a, sel, ty) } |
| 29 | func ws_sx(m: *i64, n: *u8, nty: i64, sel: *u8, ty: i64) -> i64 { return sir_swz(m, sir_ident(m, n, nty), sel, ty) } |
| 30 | func ws_mem(m: *i64, a: i64, name: *u8, ty: i64) -> i64 { return sir_member_of(m, a, name, ty) } |
| 31 | func ws_c1(m: *i64, name: *u8, a: i64, ty: i64) -> i64 { let c: i64 = sir_call(m, name, ty); sir_arg(m, c, a); return c } |
| 32 | func ws_c2(m: *i64, name: *u8, a: i64, b: i64, ty: i64) -> i64 { let c: i64 = sir_call(m, name, ty); sir_arg(m, c, a); sir_arg(m, c, b); return c } |
| 33 | func ws_c3(m: *i64, name: *u8, a: i64, b: i64, c3: i64, ty: i64) -> i64 { let c: i64 = sir_call(m, name, ty); sir_arg(m, c, a); sir_arg(m, c, b); sir_arg(m, c, c3); return c } |
| 34 | func ws_c4(m: *i64, name: *u8, a: i64, b: i64, c3: i64, d: i64, ty: i64) -> i64 { let c: i64 = sir_call(m, name, ty); sir_arg(m, c, a); sir_arg(m, c, b); sir_arg(m, c, c3); sir_arg(m, c, d); return c } |
| 35 | func ws_c5(m: *i64, name: *u8, a: i64, b: i64, c3: i64, d: i64, e: i64, ty: i64) -> i64 { let c: i64 = sir_call(m, name, ty); sir_arg(m, c, a); sir_arg(m, c, b); sir_arg(m, c, c3); sir_arg(m, c, d); sir_arg(m, c, e); return c } |
| 36 | func ws_c6(m: *i64, name: *u8, a: i64, b: i64, c3: i64, d: i64, e: i64, g: i64, ty: i64) -> i64 { let c: i64 = sir_call(m, name, ty); sir_arg(m, c, a); sir_arg(m, c, b); sir_arg(m, c, c3); sir_arg(m, c, d); sir_arg(m, c, e); sir_arg(m, c, g); return c } |
| 37 | func ws_v1(m: *i64, ty: i64, a: i64) -> i64 { let c: i64 = sir_ctor(m, ty); sir_arg(m, c, a); return c } |
| 38 | func ws_vt2(m: *i64, ty: i64, a: i64, b: i64) -> i64 { let c: i64 = sir_ctor(m, ty); sir_arg(m, c, a); sir_arg(m, c, b); return c } |
| 39 | func ws_vt3(m: *i64, ty: i64, a: i64, b: i64, c3: i64) -> i64 { let c: i64 = sir_ctor(m, ty); sir_arg(m, c, a); sir_arg(m, c, b); sir_arg(m, c, c3); return c } |
| 40 | func ws_v2(m: *i64, a: i64, b: i64) -> i64 { return ws_vt2(m, T_V2F, a, b) } |
| 41 | func ws_v3(m: *i64, a: i64, b: i64, c3: i64) -> i64 { return ws_vt3(m, T_V3F, a, b, c3) } |
| 42 | func ws_v3i(m: *i64, a: i64, b: i64, c3: i64) -> i64 { return ws_vt3(m, T_V3I, a, b, c3) } |
| 43 | func ws_v4(m: *i64, a: i64, b: i64, c3: i64, d: i64) -> i64 { let c: i64 = sir_ctor(m, T_V4F); sir_arg(m, c, a); sir_arg(m, c, b); sir_arg(m, c, c3); sir_arg(m, c, d); return c } |
| 45 | func ws_v2f(m: *i64, a: *u8, b: *u8) -> i64 { return ws_v2(m, ws_f(m, a), ws_f(m, b)) } |
| 46 | func ws_v3f(m: *i64, a: *u8, b: *u8, c3: *u8) -> i64 { return ws_v3(m, ws_f(m, a), ws_f(m, b), ws_f(m, c3)) } |
| 47 | func ws_q2(m: *i64, a: i64, b: i64) -> i64 { return sir_seq(m, a, b) } |
| 48 | func ws_q3(m: *i64, a: i64, b: i64, c: i64) -> i64 { return sir_seq(m, sir_seq(m, a, b), c) } |
| 49 | func ws_q4(m: *i64, a: i64, b: i64, c: i64, d: i64) -> i64 { return sir_seq(m, ws_q3(m, a, b, c), d) } |
| 50 | func ws_q5(m: *i64, a: i64, b: i64, c: i64, d: i64, e: i64) -> i64 { return sir_seq(m, ws_q4(m, a, b, c, d), e) } |
| 51 | func ws_set(m: *i64, lhs: i64, rhs: i64) -> i64 { return sir_assign(m, lhs, rhs) } |
| 53 | func ws_op(m: *i64, name: *u8, ty: i64, op: *u8, rhs: i64) -> i64 { return sir_assign(m, sir_ident(m, name, ty), sir_bin(m, op, sir_ident(m, name, ty), rhs, ty)) } |
| 55 | func ws_opx(m: *i64, name: *u8, nty: i64, sel: *u8, ty: i64, op: *u8, rhs: i64) -> i64 { return sir_assign(m, ws_sx(m, name, nty, sel, ty), sir_bin(m, op, ws_sx(m, name, nty, sel, ty), rhs, ty)) } |
| 56 | func ws_if(m: *i64, c: i64, t: i64, e: i64) -> i64 { return sir_if(m, c, t, e) } |
| 57 | func ws_ret(m: *i64, e: i64) -> i64 { return sir_return(m, e) } |
| 58 | func ws_st(m: *i64, f: i64, s: i64) -> i64 { return sir_stmt(m, f, s) } |
| 62 | func ws_world_uniforms(m: *i64) -> i64 |
| 92 | func ws_ru(m: *i64, n: *u8, ty: i64) -> i64 { return sir_uniform(m, n, ty, 0) } |
| 93 | func ws_world_uniforms_raw(m: *i64) -> i64 |
| 109 | func ws_world_privates(m: *i64) -> i64 |
| 119 | func ws_fi(m: *i64, n: *u8) -> i64 { return sir_cast(m, sir_ident(m, n, T_I32), T_F32) } |
| 121 | func ws_fn_rgb9(m: *i64) -> i64 |
| 131 | func ws_pal(m: *i64, f: i64, arr: *u8, k: *u8, rn: *u8) -> i64 |
| 139 | func ws_fn_upk(m: *i64) -> i64 |
| 177 | func ws_fn_vx(m: *i64) -> i64 |
| 195 | func ws_fn_h21(m: *i64) -> i64 |
| 204 | func ws_fn_h31(m: *i64) -> i64 |
| 213 | func ws_fn_pal9(m: *i64) -> i64 |
| 227 | func ws_noise2(m: *i64, iname: *u8, fname: *u8) -> i64 |
| 282 | func ws_h31o(m: *i64, a: *u8, b: *u8, c: *u8) -> i64 |
| 285 | func ws_fx(m: *i64, sel: *u8) -> i64 { return ws_sx(m, "f" as *u8, T_V3F, sel, T_F32) } |
| 286 | func ws_py(m: *i64) -> i64 { return ws_sx(m, "p" as *u8, T_V3F, "y" as *u8, T_F32) } |
| 288 | func ws_fn_vn3(m: *i64) -> i64 |
| 308 | func ws_fn_cvol(m: *i64) -> i64 |
| 329 | func ws_fn_csun(m: *i64) -> i64 |
| 347 | func ws_fn_cloud_decode(m: *i64) -> i64 |
| 358 | func ws_fn_cloud_encode(m: *i64) -> i64 |
| 367 | func ws_fn_cloud_phase(m: *i64) -> i64 |
| 374 | func ws_fn_cloud_incident(m: *i64) -> i64 |
| 391 | func ws_fn_cld3(m: *i64) -> i64 |
| 422 | func ws_fn_sky(m: *i64) -> i64 |
| 442 | func ws_struct_hit(m: *i64) -> i64 |
| 452 | func ws_dda_step(m: *i64, ax: *u8, fneg: *u8, fpos: *u8) -> i64 |
| 463 | func ws_fn_hq(m: *i64) -> i64 |
| 479 | func ws_fn_surf(m: *i64) -> i64 |
| 501 | func ws_fn_terrain(m: *i64) -> i64 |
| 513 | func ws_fn_smarch(m: *i64) -> i64 |
| 550 | func ws_fn_gnd(m: *i64) -> i64 |
| 574 | func ws_fn_march(m: *i64, hty: i64) -> i64 |
| 631 | func ws_face(m: *i64, sw: *u8, ax: *u8, op: *u8, nx: *u8, ny: *u8, nz: *u8) -> i64 |
| 638 | func ws_li(m: *i64, k: *u8) -> i64 { return ws_op(m, "li" as *u8, T_F32, "*" as *u8, ws_f(m, k)) } |
| 640 | func ws_fce(m: *i64, k: *u8) -> i64 { return ws_cmp(m, "==" as *u8, ws_id(m, "fce" as *u8, T_I32), ws_i(m, k)) } |
| 642 | func ws_beq(m: *i64, k: *u8) -> i64 { return ws_cmp(m, "==" as *u8, ws_id(m, "b" as *u8, T_U32), ws_u(m, k)) } |
| 644 | func ws_ao(m: *i64, fa: *u8, cmp: *u8, edge: *u8, nudge: i64, gain: i64) -> i64 |
| 651 | func ws_nb(m: *i64, ax: *u8, op: *u8) -> i64 { return ws_opx(m, "nb" as *u8, T_V3I, ax, T_I32, op, ws_i(m, "1" as *u8)) } |
| 653 | func ws_topbot(m: *i64) -> i64 { return ws_or(m, ws_fce(m, "3" as *u8), ws_fce(m, "4" as *u8)) } |
| 658 | func ws_smooth(m: *i64) -> i64 |
| 663 | func ws_cont_water(m: *i64) -> i64 |
| 666 | func ws_cont_surface(m: *i64) -> i64 { return ws_or(m, ws_smooth(m), ws_cont_water(m)) } |
| 668 | func ws_step_down(m: *i64) -> i64 |
| 712 | func ws_sd_pxz(m: *i64) -> i64 { return ws_sx(m, "hp" as *u8, T_V3F, "xz" as *u8, T_V2F) } |
| 713 | func ws_sd_f(m: *i64, n: *u8) -> i64 { return ws_id(m, n, T_F32) } |
| 714 | func ws_sd_v3(m: *i64, n: *u8) -> i64 { return ws_id(m, n, T_V3F) } |
| 716 | func ws_sd_surf(m: *i64, op: *u8, dx: *u8, dz: *u8) -> i64 { return ws_c1(m, "surf" as *u8, ws_bin(m, op, ws_sd_pxz(m), ws_v2f(m, dx, dz), T_V2F), T_F32) } |
| 718 | func ws_sd_g(m: *i64, dx: *u8, dz: *u8) -> i64 { return ws_c1(m, "h21" as *u8, ws_bin(m, "+" as *u8, ws_id(m, "gc" as *u8, T_V2F), ws_v2f(m, dx, dz), T_V2F), T_F32) } |
| 719 | func ws_sd_lt0(m: *i64, n: *u8) -> i64 { return ws_cmp(m, "<" as *u8, ws_id(m, n, T_F32), ws_f(m, "0.0" as *u8)) } |
| 720 | func ws_sd_dk(m: *i64, n: *u8) -> i64 { return ws_bin(m, "*" as *u8, ws_id(m, n, T_I32), ws_id(m, "k" as *u8, T_I32), T_I32) } |
| 722 | func ws_sd_wat(m: *i64, y: *u8) -> i64 { return ws_cmp(m, "==" as *u8, ws_c1(m, "vx" as *u8, ws_bin(m, "+" as *u8, ws_id(m, "c" as *u8, T_V3I), ws_vt3(m, T_V3I, ws_sd_dk(m, "dx" as *u8), ws_i(m, y), ws_sd_dk(m, "dz" as *u8)), T_V3I), T_U32), ws_u(m, "4" as *u8)) } |
| 724 | func ws_sd_dir(m: *i64, shift: *u8) -> i64 { return sir_cast(m, ws_c1(m, "floor" as *u8, ws_bin(m, "+" as *u8, ws_c1(m, "sin" as *u8, ws_bin(m, "+" as *u8, ws_id(m, "a" as *u8, T_F32), ws_f(m, shift), T_F32), T_F32), ws_f(m, SD_HALF), T_F32), T_F32), T_I32) } |
| 726 | func ws_sd_fade(m: *i64, freq: *u8) -> i64 { return ws_c3(m, "clamp" as *u8, ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, ws_f(m, SD_TWO), ws_sd_f(m, "fp" as *u8), T_F32), ws_f(m, freq), T_F32), T_F32), ws_f(m, "0.0" as *u8), ws_f(m, "1.0" as *u8), T_F32) } |
| 728 | func ws_sd_dslope(m: *i64, a: *u8, b: *u8, k: *u8) -> i64 { return ws_bin(m, "*" as *u8, ws_bin(m, "-" as *u8, ws_sd_f(m, a), ws_sd_f(m, b), T_F32), ws_f(m, k), T_F32) } |
| 730 | func ws_sd_tilt(m: *i64, s: *u8, g: *u8, rdk: *u8) -> i64 |
| 737 | func ws_sandcls(m: *i64) -> i64 { return ws_or(m, ws_or(m, ws_beq(m, "1" as *u8), ws_beq(m, "2" as *u8)), ws_beq(m, "5" as *u8)) } |
| 738 | func ws_sandy(m: *i64) -> i64 { return ws_and(m, ws_smooth(m), ws_sandcls(m)) } |
| 740 | func ws_shd(m: *i64) -> i64 { return ws_q2(m, ws_li(m, "0.55" as *u8), ws_op(m, "sp" as *u8, T_F32, "*" as *u8, ws_f(m, SD_SHADOW_SPEC))) } |
| 741 | func ws_fn_sand(m: *i64) -> i64 |
| 809 | func ws_fn_shade(m: *i64, hty: i64) -> i64 |
| 907 | func ws_bt(m: *i64, k: *u8, v: *u8, els: i64) -> i64 |
| 911 | func ws_pxo(m: *i64, a: *u8, op: *u8, e: i64) -> i64 { return ws_cmp(m, op, ws_sx(m, "px" as *u8, T_V2F, a, T_F32), ws_bin(m, "+" as *u8, ws_sx(m, "o" as *u8, T_V2F, a, T_F32), e, T_F32)) } |
| 917 | func ws_fn_water_hit(m: *i64, hty: i64) -> i64 |
| 942 | func ws_fn_scene_hit(m: *i64, hty: i64) -> i64 |
| 974 | func ws_fn_fs(m: *i64, hty: i64) -> i64 |
| 1043 | func shsrc_world(m: *i64) -> i64 |