nx_world_shader_sky_private_20260910.nx source
↩ module page · 1009 lines · 112994 B
1// nx_world_shader_src.nx -- THE WORLD SHADER, WRITTEN ONCE (gameengine GE44 R-G, 2026-09-04).
2// The voxel world pass that nx_game_page_emit ships hand-written twice (a GLSL FSH for the WebGL2 door and a WGSL
3// module for the WebGPU door) is authored here ONCE as shader-IR builder calls and emitted to BOTH dialects by
4// nx_wgsl. Every function below is the hand WGSL, statement for statement (vx, h21, h31, pal9, sky, struct Hit,
5// march, shade, the fragment entry); the vertex entry is the backend's own fullscreen triangle (shsrc_fullscreen_tri).
6// Deliberate deltas from the hand text, all semantic no-ops: compound assignments are spelled x=(x+y); unsigned
7// constants are casts (u32(0) / uint(0)) because the GLSL backend spells a u32 literal without its suffix and a bare 0
8// beside a uint is a GLSL type error; the WebGPU top-left fragment origin is carried as the uniform `yflip` (1 on the
9// WebGPU door, 0 on WebGL2) instead of a per-dialect edit, so ONE source serves both doors. The uniform block is
10// declared ONCE here (ws_world_uniforms) and `nx_wgsl layout` derives its memory layout from it.
11// GE55 (2026-09-05): the world module now takes the sim's RAW state words as its uniform block (ws_world_uniforms_raw,
12// the same 40-word table as nx_wasm_craft UR_*) and derives every float in upk() into module-scope private state, so
13// the page packs nothing and computes nothing; ws_world_uniforms (the f32 block) stays as the R-F layout ruler fixture.
14// license_tier: ORIGINAL
15import "nx_shader_ir.nx"
16
17// ---- builder shorthands (one IR node per call; a node is never reused as two children) ----------------------
18func ws_f(m: *i64, s: *u8) -> i64 { return sir_lit(m, s, T_F32) }
19func ws_i(m: *i64, s: *u8) -> i64 { return sir_lit(m, s, T_I32) }
20// an unsigned constant as a cast of an int literal: `u32(0)` / `uint(0)`, the one spelling valid in both dialects
21func ws_u(m: *i64, s: *u8) -> i64 { return sir_cast(m, sir_lit(m, s, T_I32), T_U32) }
22func ws_id(m: *i64, n: *u8, ty: i64) -> i64 { return sir_ident(m, n, ty) }
23func ws_bin(m: *i64, op: *u8, a: i64, b: i64, ty: i64) -> i64 { return sir_bin(m, op, a, b, ty) }
24func ws_cmp(m: *i64, op: *u8, a: i64, b: i64) -> i64 { return sir_bin(m, op, a, b, T_BOOL) }
25func ws_and(m: *i64, a: i64, b: i64) -> i64 { return sir_bin(m, "&&" as *u8, a, b, T_BOOL) }
26func ws_or(m: *i64, a: i64, b: i64) -> i64 { return sir_bin(m, "||" as *u8, a, b, T_BOOL) }
27func ws_sw(m: *i64, a: i64, sel: *u8, ty: i64) -> i64 { return sir_swz(m, a, sel, ty) }
28// swizzle of a FRESH identifier (the common `name.x` read)
29func ws_sx(m: *i64, n: *u8, nty: i64, sel: *u8, ty: i64) -> i64 { return sir_swz(m, sir_ident(m, n, nty), sel, ty) }
30func ws_mem(m: *i64, a: i64, name: *u8, ty: i64) -> i64 { return sir_member_of(m, a, name, ty) }
31func 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 }
32func 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 }
33func 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 }
34func 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 }
35func 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 }
36func 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 }
37func ws_v1(m: *i64, ty: i64, a: i64) -> i64 { let c: i64 = sir_ctor(m, ty); sir_arg(m, c, a); return c }
38func 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 }
39func 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 }
40func ws_v2(m: *i64, a: i64, b: i64) -> i64 { return ws_vt2(m, T_V2F, a, b) }
41func ws_v3(m: *i64, a: i64, b: i64, c3: i64) -> i64 { return ws_vt3(m, T_V3F, a, b, c3) }
42func ws_v3i(m: *i64, a: i64, b: i64, c3: i64) -> i64 { return ws_vt3(m, T_V3I, a, b, c3) }
43func 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 }
44// vec2f(x,y) / vec3f(x,y,z) of three f32 literals
45func ws_v2f(m: *i64, a: *u8, b: *u8) -> i64 { return ws_v2(m, ws_f(m, a), ws_f(m, b)) }
46func 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)) }
47func ws_q2(m: *i64, a: i64, b: i64) -> i64 { return sir_seq(m, a, b) }
48func ws_q3(m: *i64, a: i64, b: i64, c: i64) -> i64 { return sir_seq(m, sir_seq(m, a, b), c) }
49func ws_q4(m: *i64, a: i64, b: i64, c: i64, d: i64) -> i64 { return sir_seq(m, ws_q3(m, a, b, c), d) }
50func 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) }
51func ws_set(m: *i64, lhs: i64, rhs: i64) -> i64 { return sir_assign(m, lhs, rhs) }
52// x = (x op y) -- the spelling of every compound assignment in the hand text
53func 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)) }
54// name.sel = (name.sel op y)
55func 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)) }
56func ws_if(m: *i64, c: i64, t: i64, e: i64) -> i64 { return sir_if(m, c, t, e) }
57func ws_ret(m: *i64, e: i64) -> i64 { return sir_return(m, e) }
58func ws_st(m: *i64, f: i64, s: i64) -> i64 { return sir_stmt(m, f, s) }
59
60// ---- the uniform block, declared ONCE (its layout is derived by `nx_wgsl layout`) ------------------------------
61// p0 of the hand packer is `yflip` here: the WebGPU door packs 1 (top-left origin), the WebGL2 door 0 (see fs).
62func ws_world_uniforms(m: *i64) -> i64 {
63 sir_uniform(m, "cam" as *u8, T_V3F, 0)
64 sir_uniform(m, "t" as *u8, T_F32, 0)
65 sir_uniform(m, "yp" as *u8, T_V4F, 0)
66 sir_uniform(m, "sund" as *u8, T_V3F, 0)
67 sir_uniform(m, "rain" as *u8, T_F32, 0)
68 sir_uniform(m, "skt" as *u8, T_V3F, 0)
69 sir_uniform(m, "sun" as *u8, T_F32, 0)
70 sir_uniform(m, "skh" as *u8, T_V3F, 0)
71 sir_uniform(m, "cld" as *u8, T_F32, 0)
72 sir_uniform(m, "res" as *u8, T_V2F, 0)
73 sir_uniform(m, "wmax" as *u8, T_F32, 0)
74 sir_uniform(m, "selb" as *u8, T_F32, 0)
75 sir_uniform(m, "hok" as *u8, T_F32, 0)
76 sir_uniform(m, "npct" as *u8, T_F32, 0)
77 sir_uniform(m, "yflip" as *u8, T_F32, 0)
78 sir_uniform(m, "p1" as *u8, T_F32, 0)
79 sir_uniform(m, "pal" as *u8, T_V4F, 12)
80 sir_uniform(m, "palf" as *u8, T_V4F, 5)
81 return 0
82}
83
84// ---- GE55 (2026-09-05): THE RAW UNIFORM BLOCK -- the sim's own state words, verbatim (nx_wasm_craft pack_uniforms) ----
85// 40 little-endian 32-bit words, 160 B; word index = byte offset / 4, the SAME table as UR_* in nx_wasm_craft.nx, and
86// `nx_wgsl layout` on this module is the one ruler both sides are pinned to. Signed state is i32, packed RGB words and
87// flags are u32. NOTHING here is a float: the wasm lane carries no f32 lowering, so every float the world pass needs is
88// derived in upk() below from these words -- the page packs no uniform and computes no arithmetic (the bridge is one
89// writeBuffer from the sim's memory). The derived values live in MODULE-SCOPE PRIVATE STATE (K_PRIVATE) under the
90// names every function body already reads (cam, t, yp, sund, rain, skt, sun, skh, cld, res, wmax, selb, hok, npct,
91// yflip, pal[12], palf[5]), so every function below stays byte-identical to the hand text it was proven against.
92func ws_ru(m: *i64, n: *u8, ty: i64) -> i64 { return sir_uniform(m, n, ty, 0) }
93func ws_world_uniforms_raw(m: *i64) -> i64 {
94 ws_ru(m, "r_camx" as *u8, T_I32); ws_ru(m, "r_camy" as *u8, T_I32); ws_ru(m, "r_camz" as *u8, T_I32); ws_ru(m, "r_tnow" as *u8, T_I32)
95 ws_ru(m, "r_yaw" as *u8, T_I32); ws_ru(m, "r_pitch" as *u8, T_I32); ws_ru(m, "r_sunel" as *u8, T_I32); ws_ru(m, "r_dayt" as *u8, T_I32)
96 ws_ru(m, "r_dlen" as *u8, T_I32); ws_ru(m, "r_rain" as *u8, T_I32); ws_ru(m, "r_skt" as *u8, T_U32); ws_ru(m, "r_skh" as *u8, T_U32)
97 ws_ru(m, "r_sun" as *u8, T_I32); ws_ru(m, "r_cld" as *u8, T_I32); ws_ru(m, "r_wmax" as *u8, T_I32); ws_ru(m, "r_selb" as *u8, T_I32)
98 ws_ru(m, "r_hok" as *u8, T_I32); ws_ru(m, "r_npct" as *u8, T_I32); ws_ru(m, "r_broken" as *u8, T_I32); ws_ru(m, "r_placed" as *u8, T_I32)
99 ws_ru(m, "r_pal0" as *u8, T_U32); ws_ru(m, "r_pal1" as *u8, T_U32); ws_ru(m, "r_pal2" as *u8, T_U32); ws_ru(m, "r_pal3" as *u8, T_U32)
100 ws_ru(m, "r_pal4" as *u8, T_U32); ws_ru(m, "r_pal5" as *u8, T_U32); ws_ru(m, "r_pal6" as *u8, T_U32); ws_ru(m, "r_pal7" as *u8, T_U32)
101 ws_ru(m, "r_pal8" as *u8, T_U32); ws_ru(m, "r_pal9" as *u8, T_U32); ws_ru(m, "r_pal10" as *u8, T_U32); ws_ru(m, "r_pal11" as *u8, T_U32)
102 ws_ru(m, "r_palf0" as *u8, T_U32); ws_ru(m, "r_palf1" as *u8, T_U32); ws_ru(m, "r_palf2" as *u8, T_U32); ws_ru(m, "r_palf3" as *u8, T_U32)
103 ws_ru(m, "r_palf4" as *u8, T_U32); ws_ru(m, "r_resw" as *u8, T_I32); ws_ru(m, "r_resh" as *u8, T_I32); ws_ru(m, "r_yflip" as *u8, T_I32)
104 ws_ru(m, "r_surf" as *u8, T_I32) // Continuous terrain and water; vegetation/objects still need separate geometry.
105 ws_ru(m, "r_water_q8" as *u8, T_I32) // Native UR_WATER_Q8, previously padding; block size is unchanged.
106 return 0
107}
108// the derived values, module-scope private state: `var<private>` in WGSL, a bare global in GLSL
109func ws_world_privates(m: *i64) -> i64 {
110 sir_private(m, "cam" as *u8, T_V3F, 0); sir_private(m, "t" as *u8, T_F32, 0); sir_private(m, "yp" as *u8, T_V4F, 0)
111 sir_private(m, "sund" as *u8, T_V3F, 0); sir_private(m, "rain" as *u8, T_F32, 0); sir_private(m, "skt" as *u8, T_V3F, 0)
112 sir_private(m, "sun" as *u8, T_F32, 0); sir_private(m, "skh" as *u8, T_V3F, 0); sir_private(m, "cld" as *u8, T_F32, 0)
113 sir_private(m, "res" as *u8, T_V2F, 0); sir_private(m, "wmax" as *u8, T_F32, 0); sir_private(m, "selb" as *u8, T_F32, 0)
114 sir_private(m, "hok" as *u8, T_F32, 0); sir_private(m, "npct" as *u8, T_F32, 0); sir_private(m, "yflip" as *u8, T_F32, 0)
115 sir_private(m, "pal" as *u8, T_V4F, 12); sir_private(m, "palf" as *u8, T_V4F, 5)
116 return 0
117}
118// f32(<raw i32 word>)
119func ws_fi(m: *i64, n: *u8) -> i64 { return sir_cast(m, sir_ident(m, n, T_I32), T_F32) }
120// fn rgb9(w:u32)->vec3f{return vec3f(f32(w&255u),f32((w>>8u)&255u),f32((w>>16u)&255u))/255.0;} -- the packed RGB word
121func ws_fn_rgb9(m: *i64) -> i64 {
122 let f: i64 = sir_func(m, "rgb9" as *u8, T_V3F)
123 sir_param(m, f, "w" as *u8, T_U32)
124 let r: i64 = sir_cast(m, ws_bin(m, "&" as *u8, ws_id(m, "w" as *u8, T_U32), ws_u(m, "255" as *u8), T_U32), T_F32)
125 let g: i64 = sir_cast(m, ws_bin(m, "&" as *u8, ws_bin(m, ">>" as *u8, ws_id(m, "w" as *u8, T_U32), ws_u(m, "8" as *u8), T_U32), ws_u(m, "255" as *u8), T_U32), T_F32)
126 let b: i64 = sir_cast(m, ws_bin(m, "&" as *u8, ws_bin(m, ">>" as *u8, ws_id(m, "w" as *u8, T_U32), ws_u(m, "16" as *u8), T_U32), ws_u(m, "255" as *u8), T_U32), T_F32)
127 ws_st(m, f, ws_ret(m, ws_bin(m, "/" as *u8, ws_v3(m, r, g, b), ws_f(m, "255.0" as *u8), T_V3F)))
128 return f
129}
130// <arr>[<k>]=vec4f(rgb9(<rn>)*dl2,0.0);
131func ws_pal(m: *i64, f: i64, arr: *u8, k: *u8, rn: *u8) -> i64 {
132 let c: i64 = ws_vt2(m, T_V4F, ws_bin(m, "*" as *u8, ws_c1(m, "rgb9" as *u8, ws_id(m, rn, T_U32), T_V3F), ws_id(m, "dl2" as *u8, T_F32), T_V3F), ws_f(m, "0.0" as *u8))
133 return ws_st(m, f, ws_set(m, sir_index(m, ws_id(m, arr, T_V4F), ws_i(m, k), T_V4F), c))
134}
135// fn upk(){ ... } -- every float the world pass reads, derived ONCE per fragment from the raw words. The arithmetic is
136// the retired JS packer's, line for line: cam/256, yaw and pitch Q12, df=max(0,sunel/4096), dl2=.22+.78*pow(df,.6),
137// nn=1-dl2, the sky words unpacked times dl2 plus nn*k, the sun disc only when the sim says sun AND df>.04, the sun
138// direction from the day fraction (az) and the elevation (el), and the 17 palette words times dl2.
139func ws_fn_upk(m: *i64) -> i64 {
140 let f: i64 = sir_func(m, "upk" as *u8, T_VOID)
141 ws_st(m, f, ws_set(m, ws_id(m, "cam" as *u8, T_V3F), ws_bin(m, "/" as *u8, ws_v3(m, ws_fi(m, "r_camx" as *u8), ws_fi(m, "r_camy" as *u8), ws_fi(m, "r_camz" as *u8)), ws_f(m, "256.0" as *u8), T_V3F)))
142 ws_st(m, f, ws_set(m, ws_id(m, "t" as *u8, T_F32), ws_fi(m, "r_tnow" as *u8)))
143 ws_st(m, f, sir_let(m, "ya" as *u8, T_F32, ws_bin(m, "/" as *u8, ws_fi(m, "r_yaw" as *u8), ws_f(m, "4096.0" as *u8), T_F32)))
144 ws_st(m, f, sir_let(m, "pa" as *u8, T_F32, ws_bin(m, "/" as *u8, ws_fi(m, "r_pitch" as *u8), ws_f(m, "4096.0" as *u8), T_F32)))
145 ws_st(m, f, ws_set(m, ws_id(m, "yp" as *u8, T_V4F), ws_v4(m, ws_c1(m, "sin" as *u8, ws_id(m, "ya" as *u8, T_F32), T_F32), ws_c1(m, "cos" as *u8, ws_id(m, "ya" as *u8, T_F32), T_F32), ws_c1(m, "sin" as *u8, ws_id(m, "pa" as *u8, T_F32), T_F32), ws_c1(m, "cos" as *u8, ws_id(m, "pa" as *u8, T_F32), T_F32))))
146 ws_st(m, f, sir_let(m, "sel" as *u8, T_F32, ws_bin(m, "/" as *u8, ws_fi(m, "r_sunel" as *u8), ws_f(m, "4096.0" as *u8), T_F32)))
147 ws_st(m, f, sir_let(m, "df" as *u8, T_F32, ws_c2(m, "max" as *u8, ws_f(m, "0.0" as *u8), ws_id(m, "sel" as *u8, T_F32), T_F32)))
148 ws_st(m, f, sir_let(m, "dl2" as *u8, T_F32, ws_bin(m, "+" as *u8, ws_f(m, "0.22" as *u8), ws_bin(m, "*" as *u8, ws_f(m, "0.78" as *u8), ws_c2(m, "pow" as *u8, ws_id(m, "df" as *u8, T_F32), ws_f(m, "0.6" as *u8), T_F32), T_F32), T_F32)))
149 ws_st(m, f, sir_let(m, "nn" as *u8, T_F32, ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_id(m, "dl2" as *u8, T_F32), T_F32)))
150 ws_st(m, f, sir_let(m, "dfr" as *u8, T_F32, ws_bin(m, "/" as *u8, ws_fi(m, "r_dayt" as *u8), ws_c2(m, "max" as *u8, ws_f(m, "1.0" as *u8), ws_fi(m, "r_dlen" as *u8), T_F32), T_F32)))
151 ws_st(m, f, sir_let(m, "az" as *u8, T_F32, ws_bin(m, "*" as *u8, ws_f(m, "3.14159265" as *u8), ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_bin(m, "*" as *u8, ws_id(m, "dfr" as *u8, T_F32), ws_f(m, "1.6" as *u8), T_F32), T_F32), T_F32)))
152 ws_st(m, f, sir_let(m, "el" as *u8, T_F32, ws_c1(m, "asin" as *u8, ws_c3(m, "clamp" as *u8, ws_id(m, "sel" as *u8, T_F32), ws_f(m, "-0.99" as *u8), ws_f(m, "0.99" as *u8), T_F32), T_F32)))
153 ws_st(m, f, sir_let(m, "sd" as *u8, T_V3F, ws_v3(m, ws_bin(m, "*" as *u8, ws_c1(m, "cos" as *u8, ws_id(m, "el" as *u8, T_F32), T_F32), ws_c1(m, "cos" as *u8, ws_id(m, "az" as *u8, T_F32), T_F32), T_F32), ws_c1(m, "sin" as *u8, ws_id(m, "el" as *u8, T_F32), T_F32), ws_bin(m, "*" as *u8, ws_c1(m, "cos" as *u8, ws_id(m, "el" as *u8, T_F32), T_F32), ws_f(m, "0.45" as *u8), T_F32))))
154 ws_st(m, f, sir_let(m, "sdl" as *u8, T_F32, ws_c1(m, "length" as *u8, ws_id(m, "sd" as *u8, T_V3F), T_F32)))
155 ws_st(m, f, ws_set(m, ws_id(m, "sund" as *u8, T_V3F), ws_bin(m, "/" as *u8, ws_id(m, "sd" as *u8, T_V3F), sir_select(m, ws_cmp(m, "==" as *u8, ws_id(m, "sdl" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_f(m, "1.0" as *u8), ws_id(m, "sdl" as *u8, T_F32), T_F32), T_V3F)))
156 ws_st(m, f, ws_set(m, ws_id(m, "rain" as *u8, T_F32), ws_fi(m, "r_rain" as *u8)))
157 ws_st(m, f, ws_set(m, ws_id(m, "skt" as *u8, T_V3F), ws_bin(m, "+" as *u8, ws_bin(m, "*" as *u8, ws_c1(m, "rgb9" as *u8, ws_id(m, "r_skt" as *u8, T_U32), T_V3F), ws_id(m, "dl2" as *u8, T_F32), T_V3F), ws_bin(m, "*" as *u8, ws_v3f(m, "0.02" as *u8, "0.03" as *u8, "0.10" as *u8), ws_id(m, "nn" as *u8, T_F32), T_V3F), T_V3F)))
158 ws_st(m, f, ws_set(m, ws_id(m, "skh" as *u8, T_V3F), ws_bin(m, "+" as *u8, ws_bin(m, "*" as *u8, ws_c1(m, "rgb9" as *u8, ws_id(m, "r_skh" as *u8, T_U32), T_V3F), ws_id(m, "dl2" as *u8, T_F32), T_V3F), ws_bin(m, "*" as *u8, ws_v3f(m, "0.04" as *u8, "0.05" as *u8, "0.12" as *u8), ws_id(m, "nn" as *u8, T_F32), T_V3F), T_V3F)))
159 ws_st(m, f, ws_set(m, ws_id(m, "sun" as *u8, T_F32), sir_select(m, ws_and(m, ws_cmp(m, "==" as *u8, ws_id(m, "r_sun" as *u8, T_I32), ws_i(m, "1" as *u8)), ws_cmp(m, ">" as *u8, ws_id(m, "df" as *u8, T_F32), ws_f(m, "0.04" as *u8))), ws_f(m, "1.0" as *u8), ws_f(m, "0.0" as *u8), T_F32)))
160 ws_st(m, f, ws_set(m, ws_id(m, "cld" as *u8, T_F32), ws_fi(m, "r_cld" as *u8)))
161 ws_st(m, f, ws_set(m, ws_id(m, "res" as *u8, T_V2F), ws_v2(m, ws_fi(m, "r_resw" as *u8), ws_fi(m, "r_resh" as *u8))))
162 ws_st(m, f, ws_set(m, ws_id(m, "wmax" as *u8, T_F32), ws_fi(m, "r_wmax" as *u8)))
163 ws_st(m, f, ws_set(m, ws_id(m, "selb" as *u8, T_F32), ws_fi(m, "r_selb" as *u8)))
164 ws_st(m, f, ws_set(m, ws_id(m, "hok" as *u8, T_F32), ws_fi(m, "r_hok" as *u8)))
165 ws_st(m, f, ws_set(m, ws_id(m, "npct" as *u8, T_F32), ws_fi(m, "r_npct" as *u8)))
166 ws_st(m, f, ws_set(m, ws_id(m, "yflip" as *u8, T_F32), ws_fi(m, "r_yflip" as *u8)))
167 ws_pal(m, f, "pal" as *u8, "0" as *u8, "r_pal0" as *u8); ws_pal(m, f, "pal" as *u8, "1" as *u8, "r_pal1" as *u8); ws_pal(m, f, "pal" as *u8, "2" as *u8, "r_pal2" as *u8)
168 ws_pal(m, f, "pal" as *u8, "3" as *u8, "r_pal3" as *u8); ws_pal(m, f, "pal" as *u8, "4" as *u8, "r_pal4" as *u8); ws_pal(m, f, "pal" as *u8, "5" as *u8, "r_pal5" as *u8)
169 ws_pal(m, f, "pal" as *u8, "6" as *u8, "r_pal6" as *u8); ws_pal(m, f, "pal" as *u8, "7" as *u8, "r_pal7" as *u8); ws_pal(m, f, "pal" as *u8, "8" as *u8, "r_pal8" as *u8)
170 ws_pal(m, f, "pal" as *u8, "9" as *u8, "r_pal9" as *u8); ws_pal(m, f, "pal" as *u8, "10" as *u8, "r_pal10" as *u8); ws_pal(m, f, "pal" as *u8, "11" as *u8, "r_pal11" as *u8)
171 ws_pal(m, f, "palf" as *u8, "0" as *u8, "r_palf0" as *u8); ws_pal(m, f, "palf" as *u8, "1" as *u8, "r_palf1" as *u8); ws_pal(m, f, "palf" as *u8, "2" as *u8, "r_palf2" as *u8)
172 ws_pal(m, f, "palf" as *u8, "3" as *u8, "r_palf3" as *u8); ws_pal(m, f, "palf" as *u8, "4" as *u8, "r_palf4" as *u8)
173 return f
174}
175
176// fn vx(c:vec3i)->u32{if(c.x<0||c.y<0||c.z<0||c.x>127||c.y>47||c.z>127){return 0u;}return textureLoad(tV,vec3i(c.x,c.z,c.y),0).r;}
177func ws_fn_vx(m: *i64) -> i64 {
178 let f: i64 = sir_func(m, "vx" as *u8, T_U32)
179 sir_param(m, f, "c" as *u8, T_V3I)
180 let c0: i64 = ws_or(m, ws_or(m, ws_or(m, ws_or(m, ws_or(m,
181 ws_cmp(m, "<" as *u8, ws_sx(m, "c" as *u8, T_V3I, "x" as *u8, T_I32), ws_i(m, "0" as *u8)),
182 ws_cmp(m, "<" as *u8, ws_sx(m, "c" as *u8, T_V3I, "y" as *u8, T_I32), ws_i(m, "0" as *u8))),
183 ws_cmp(m, "<" as *u8, ws_sx(m, "c" as *u8, T_V3I, "z" as *u8, T_I32), ws_i(m, "0" as *u8))),
184 ws_cmp(m, ">" as *u8, ws_sx(m, "c" as *u8, T_V3I, "x" as *u8, T_I32), ws_i(m, "127" as *u8))),
185 ws_cmp(m, ">" as *u8, ws_sx(m, "c" as *u8, T_V3I, "y" as *u8, T_I32), ws_i(m, "47" as *u8))),
186 ws_cmp(m, ">" as *u8, ws_sx(m, "c" as *u8, T_V3I, "z" as *u8, T_I32), ws_i(m, "127" as *u8)))
187 ws_st(m, f, ws_if(m, c0, ws_ret(m, ws_u(m, "0" as *u8)), 0))
188 let co: i64 = ws_v3i(m, ws_sx(m, "c" as *u8, T_V3I, "x" as *u8, T_I32), ws_sx(m, "c" as *u8, T_V3I, "z" as *u8, T_I32), ws_sx(m, "c" as *u8, T_V3I, "y" as *u8, T_I32))
189 let tl: i64 = sir_texload(m, ws_id(m, "tV" as *u8, T_TEX3U), co, ws_i(m, "0" as *u8))
190 ws_st(m, f, ws_ret(m, ws_sw(m, tl, "r" as *u8, T_U32)))
191 return f
192}
193
194// fn h21(p:vec2f)->f32{return fract(sin(dot(p,vec2f(127.1,311.7)))*43758.5453);}
195func ws_fn_h21(m: *i64) -> i64 {
196 let f: i64 = sir_func(m, "h21" as *u8, T_F32)
197 sir_param(m, f, "p" as *u8, T_V2F)
198 let d: i64 = ws_c2(m, "dot" as *u8, ws_id(m, "p" as *u8, T_V2F), ws_v2f(m, "127.1" as *u8, "311.7" as *u8), T_F32)
199 ws_st(m, f, ws_ret(m, ws_c1(m, "fract" as *u8, ws_bin(m, "*" as *u8, ws_c1(m, "sin" as *u8, d, T_F32), ws_f(m, "43758.5453" as *u8), T_F32), T_F32)))
200 return f
201}
202
203// fn h31(p:vec3f)->f32{return fract(sin(dot(p,vec3f(127.1,311.7,74.7)))*43758.5453);}
204func ws_fn_h31(m: *i64) -> i64 {
205 let f: i64 = sir_func(m, "h31" as *u8, T_F32)
206 sir_param(m, f, "p" as *u8, T_V3F)
207 let d: i64 = ws_c2(m, "dot" as *u8, ws_id(m, "p" as *u8, T_V3F), ws_v3f(m, "127.1" as *u8, "311.7" as *u8, "74.7" as *u8), T_F32)
208 ws_st(m, f, ws_ret(m, ws_c1(m, "fract" as *u8, ws_bin(m, "*" as *u8, ws_c1(m, "sin" as *u8, d, T_F32), ws_f(m, "43758.5453" as *u8), T_F32), T_F32)))
209 return f
210}
211
212// fn pal9(b:u32)->vec3f{var i:i32=i32(b);if(i<0){i=0;}if(i>16){i=16;}if(i<12){return u.pal[i].xyz;}return u.palf[i-12].xyz;}
213func ws_fn_pal9(m: *i64) -> i64 {
214 let f: i64 = sir_func(m, "pal9" as *u8, T_V3F)
215 sir_param(m, f, "b" as *u8, T_U32)
216 ws_st(m, f, sir_var(m, "i" as *u8, T_I32, sir_cast(m, ws_id(m, "b" as *u8, T_U32), T_I32)))
217 ws_st(m, f, ws_if(m, ws_cmp(m, "<" as *u8, ws_id(m, "i" as *u8, T_I32), ws_i(m, "0" as *u8)), ws_set(m, ws_id(m, "i" as *u8, T_I32), ws_i(m, "0" as *u8)), 0))
218 ws_st(m, f, ws_if(m, ws_cmp(m, ">" as *u8, ws_id(m, "i" as *u8, T_I32), ws_i(m, "16" as *u8)), ws_set(m, ws_id(m, "i" as *u8, T_I32), ws_i(m, "16" as *u8)), 0))
219 let pal: i64 = ws_sw(m, sir_index(m, ws_id(m, "pal" as *u8, T_V4F), ws_id(m, "i" as *u8, T_I32), T_V4F), "xyz" as *u8, T_V3F)
220 ws_st(m, f, ws_if(m, ws_cmp(m, "<" as *u8, ws_id(m, "i" as *u8, T_I32), ws_i(m, "12" as *u8)), ws_ret(m, pal), 0))
221 let palf: i64 = ws_sw(m, sir_index(m, ws_id(m, "palf" as *u8, T_V4F), ws_bin(m, "-" as *u8, ws_id(m, "i" as *u8, T_I32), ws_i(m, "12" as *u8), T_I32), T_V4F), "xyz" as *u8, T_V3F)
222 ws_st(m, f, ws_ret(m, palf))
223 return f
224}
225
226// the 2-octave hash noise used by sky: mix(mix(h21(i),h21(i+(1,0)),f.x),mix(h21(i+(0,1)),h21(i+(1,1)),f.x),f.y)
227func ws_noise2(m: *i64, iname: *u8, fname: *u8) -> i64 {
228 let a: i64 = ws_c1(m, "h21" as *u8, ws_id(m, iname, T_V2F), T_F32)
229 let b: i64 = ws_c1(m, "h21" as *u8, ws_bin(m, "+" as *u8, ws_id(m, iname, T_V2F), ws_v2f(m, "1.0" as *u8, "0.0" as *u8), T_V2F), T_F32)
230 let c: i64 = ws_c1(m, "h21" as *u8, ws_bin(m, "+" as *u8, ws_id(m, iname, T_V2F), ws_v2f(m, "0.0" as *u8, "1.0" as *u8), T_V2F), T_F32)
231 let d: i64 = ws_c1(m, "h21" as *u8, ws_bin(m, "+" as *u8, ws_id(m, iname, T_V2F), ws_v2f(m, "1.0" as *u8, "1.0" as *u8), T_V2F), T_F32)
232 let m1: i64 = ws_c3(m, "mix" as *u8, a, b, ws_sx(m, fname, T_V2F, "x" as *u8, T_F32), T_F32)
233 let m2: i64 = ws_c3(m, "mix" as *u8, c, d, ws_sx(m, fname, T_V2F, "x" as *u8, T_F32), T_F32)
234 return ws_c3(m, "mix" as *u8, m1, m2, ws_sx(m, fname, T_V2F, "y" as *u8, T_F32), T_F32)
235}
236
237// ---- PG22 (2026-09-06): THE VOLUMETRIC WEATHER FIELD ON THE GPU DOOR -- the sky's cloud is a 3D density RAYMARCHED,
238// never a sheet. This is nx_worldgen.wg_cloud_volume's law spoken in the shader dialect: 3D value noise on h31 (three
239// octaves), a vertical envelope between CB_BASE and CB_TOP, and a coverage threshold driven by the weather's cloud
240// param (cld); the CPU tier keeps drawing the sheet (nx_worldgen.wg_cloud_sheet) and nx_cloud_volume_gate proves the
241// volume follows the weather field. The march is one slab, entry to exit in CB_STEPS steps, front-to-back transmittance,
242// lit by a base-to-top gradient plus a silver term toward the sun. Every number is a named string const (a data hook
243// until the weather table carries it). The hand text, statement for statement:
244// fn vn3(q:vec3f)->f32{let i=floor(q);let f0=fract(q);let f=f0*f0*(3.0-f0*2.0);let a=h31(i);let b=h31(i+vec3f(1,0,0));...;let k=h31(i+vec3f(1,1,1));return mix(mix(mix(a,b,f.x),mix(c,d,f.x),f.y),mix(mix(e,g,f.x),mix(h,k,f.x),f.y),f.z);}
245// fn cvol(p:vec3f)->f32{let q=vec3f(p.x/CELL+t/DX,p.y/CELLY,p.z/CELL+t/DZ);let n=vn3(q)*0.5+vn3(q*2.0)*0.3+vn3(q*4.0)*0.2;let env=min((p.y-BASE)/RLO,1.0)*min((TOP-p.y)/RHI,1.0);let thr=THR0-THRK*clamp(cld,0.0,1.0);return clamp((n-thr)*GAIN,0.0,1.0)*max(env,0.0);}
246// fn cld3(rd:vec3f,s0:vec3f)->vec3f{if(cld<=0.5||rd.y<=0.04){return s0;}let t0=(BASE-cam.y)/rd.y;if(t0<=0.0){return s0;}let dt=((TOP-cam.y)/rd.y-t0)/STEPS;var tr=1.0;var acc=vec3f(0.0);for(var i=0;i<STEPS;i++){let p=cam+rd*(t0+(f32(i)+0.5)*dt);let dn=1.0-exp(0.0-cvol(p)*dt*SIGMA);let lit=LIT0+LIT1*(p.y-BASE)/(TOP-BASE)+SUNK*max(dot(rd,sund),0.0)*sun;acc=acc+vec3f(0.98,0.99,1.0)*(lit*dn*tr);tr=tr*(1.0-dn);}return s0*tr+acc;}
247const CB_BASE: *u8 = "56.0" // the incumbent sheet's height in blocks, now the slab base
248const CB_TOP: *u8 = "96.0"
249const CB_RLO: *u8 = "6.0" // density ramps in over this many blocks above the base
250const CB_RHI: *u8 = "16.0" // and out over this many below the top
251const CB_CELL: *u8 = "96.0" // one noise cell in blocks, horizontal
252const CB_CELLY: *u8 = "40.0" // and vertical (flatter cells read as stratus)
253const CB_DRIFT_X: *u8 = "240.0" // the incumbent sheet's drift divisors, kept so the motion does not change
254const CB_DRIFT_Z: *u8 = "540.0"
255const CB_THR0: *u8 = "0.78" // coverage threshold at cld=0
256const CB_THRK: *u8 = "0.30" // and how far cld=1 lowers it
257const CB_GAIN: *u8 = "4.0"
258const CB_STEPS: *u8 = "24"
259const CB_STEPS_F: *u8 = "24.0"
260const CB_SIGMA: *u8 = "0.09" // extinction per block of unit density
261const CB_LIT0: *u8 = "0.70" // ambient at the base
262const CB_LIT1: *u8 = "0.30" // brighter toward the top
263const CB_SUNK: *u8 = "0.15" // silver toward the sun
264
265// PRIVATE cloud profile: world-unit artistic defaults, not measured weather.
266// Six sun-ray samples follow the existing banked cloud contract; view/light budgets require device qualification.
267const CB_EROSION: *u8 = "0.22"
268const CB_SUN_Y_MIN: *u8 = "0.01"
269const CB_LIGHT_DISTANCE: *u8 = "160.0"
270const CB_LIGHT_STEPS: *u8 = "6"
271const CB_LIGHT_STEPS_F: *u8 = "6.0"
272const CB_VIEW_DISTANCE: *u8 = "1400.0"
273const CB_PHASE_G: *u8 = "0.35"
274const CB_AMBIENT: *u8 = "0.28"
275const CB_DIRECT: *u8 = "0.72"
276func ws_h31o(m: *i64, a: *u8, b: *u8, c: *u8) -> i64 {
277 return ws_c1(m, "h31" as *u8, ws_bin(m, "+" as *u8, ws_id(m, "i" as *u8, T_V3F), ws_v3f(m, a, b, c), T_V3F), T_F32)
278}
279func ws_fx(m: *i64, sel: *u8) -> i64 { return ws_sx(m, "f" as *u8, T_V3F, sel, T_F32) }
280func ws_py(m: *i64) -> i64 { return ws_sx(m, "p" as *u8, T_V3F, "y" as *u8, T_F32) }
281// fn vn3(q:vec3f)->f32 -- 3D value noise on h31, trilinear with a smoothstep fade (the shape of noise2 lifted one axis)
282func ws_fn_vn3(m: *i64) -> i64 {
283 let f: i64 = sir_func(m, "vn3" as *u8, T_F32)
284 sir_param(m, f, "q" as *u8, T_V3F)
285 ws_st(m, f, sir_let(m, "i" as *u8, T_V3F, ws_c1(m, "floor" as *u8, ws_id(m, "q" as *u8, T_V3F), T_V3F)))
286 ws_st(m, f, sir_let(m, "f0" as *u8, T_V3F, ws_c1(m, "fract" as *u8, ws_id(m, "q" as *u8, T_V3F), T_V3F)))
287 ws_st(m, f, sir_let(m, "f" as *u8, T_V3F, ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, ws_id(m, "f0" as *u8, T_V3F), ws_id(m, "f0" as *u8, T_V3F), T_V3F), ws_bin(m, "-" as *u8, ws_v1(m, T_V3F, ws_f(m, "3.0" as *u8)), ws_bin(m, "*" as *u8, ws_id(m, "f0" as *u8, T_V3F), ws_f(m, "2.0" as *u8), T_V3F), T_V3F), T_V3F)))
288 ws_st(m, f, sir_let(m, "a" as *u8, T_F32, ws_c1(m, "h31" as *u8, ws_id(m, "i" as *u8, T_V3F), T_F32)))
289 ws_st(m, f, sir_let(m, "b" as *u8, T_F32, ws_h31o(m, "1.0" as *u8, "0.0" as *u8, "0.0" as *u8)))
290 ws_st(m, f, sir_let(m, "c" as *u8, T_F32, ws_h31o(m, "0.0" as *u8, "1.0" as *u8, "0.0" as *u8)))
291 ws_st(m, f, sir_let(m, "d" as *u8, T_F32, ws_h31o(m, "1.0" as *u8, "1.0" as *u8, "0.0" as *u8)))
292 ws_st(m, f, sir_let(m, "e" as *u8, T_F32, ws_h31o(m, "0.0" as *u8, "0.0" as *u8, "1.0" as *u8)))
293 ws_st(m, f, sir_let(m, "g" as *u8, T_F32, ws_h31o(m, "1.0" as *u8, "0.0" as *u8, "1.0" as *u8)))
294 ws_st(m, f, sir_let(m, "h" as *u8, T_F32, ws_h31o(m, "0.0" as *u8, "1.0" as *u8, "1.0" as *u8)))
295 ws_st(m, f, sir_let(m, "k" as *u8, T_F32, ws_h31o(m, "1.0" as *u8, "1.0" as *u8, "1.0" as *u8)))
296 let x0: i64 = ws_c3(m, "mix" as *u8, ws_c3(m, "mix" as *u8, ws_id(m, "a" as *u8, T_F32), ws_id(m, "b" as *u8, T_F32), ws_fx(m, "x" as *u8), T_F32), ws_c3(m, "mix" as *u8, ws_id(m, "c" as *u8, T_F32), ws_id(m, "d" as *u8, T_F32), ws_fx(m, "x" as *u8), T_F32), ws_fx(m, "y" as *u8), T_F32)
297 let x1: i64 = ws_c3(m, "mix" as *u8, ws_c3(m, "mix" as *u8, ws_id(m, "e" as *u8, T_F32), ws_id(m, "g" as *u8, T_F32), ws_fx(m, "x" as *u8), T_F32), ws_c3(m, "mix" as *u8, ws_id(m, "h" as *u8, T_F32), ws_id(m, "k" as *u8, T_F32), ws_fx(m, "x" as *u8), T_F32), ws_fx(m, "y" as *u8), T_F32)
298 ws_st(m, f, ws_ret(m, ws_c3(m, "mix" as *u8, x0, x1, ws_fx(m, "z" as *u8), T_F32)))
299 return f
300}
301// fn cvol(p:vec3f)->f32 -- the cloud density at a world point: three octaves, the envelope, the coverage threshold
302func ws_fn_cvol(m: *i64) -> i64 {
303 let f: i64 = sir_func(m, "cvol" as *u8, T_F32)
304 sir_param(m, f, "p" as *u8, T_V3F)
305 ws_st(m, f, sir_let(m, "hf" as *u8, T_F32, ws_bin(m, "/" as *u8, ws_bin(m, "-" as *u8, ws_sx(m, "p" as *u8, T_V3F, "y" as *u8, T_F32), ws_f(m, CB_BASE), T_F32), ws_bin(m, "-" as *u8, ws_f(m, CB_TOP), ws_f(m, CB_BASE), T_F32), T_F32)))
306 ws_st(m, f, sir_let(m, "adv" as *u8, T_V3F, ws_v3(m, ws_bin(m, "/" as *u8, ws_id(m, "t" as *u8, T_F32), ws_f(m, CB_DRIFT_X), T_F32), ws_f(m, "0.0" as *u8), ws_bin(m, "/" as *u8, ws_id(m, "t" as *u8, T_F32), ws_f(m, CB_DRIFT_Z), T_F32))))
307 ws_st(m, f, sir_let(m, "q" as *u8, T_V3F, ws_bin(m, "+" as *u8, ws_bin(m, "/" as *u8, ws_id(m, "p" as *u8, T_V3F), ws_v3(m, ws_f(m, CB_CELL), ws_f(m, CB_CELLY), ws_f(m, CB_CELL)), T_V3F), ws_id(m, "adv" as *u8, T_V3F), T_V3F)))
308 ws_st(m, f, sir_let(m, "shape" as *u8, T_F32, ws_c1(m, "vn3" as *u8, ws_id(m, "q" as *u8, T_V3F), T_F32)))
309 ws_st(m, f, sir_let(m, "detail" as *u8, T_F32, ws_c1(m, "vn3" as *u8, ws_bin(m, "*" as *u8, ws_id(m, "q" as *u8, T_V3F), ws_f(m, "4.0" as *u8), T_V3F), T_F32)))
310 ws_st(m, f, sir_let(m, "env" as *u8, T_F32, ws_bin(m, "*" as *u8, ws_c3(m, "smoothstep" as *u8, ws_f(m, "0.0" as *u8), ws_bin(m, "/" as *u8, ws_f(m, CB_RLO), ws_bin(m, "-" as *u8, ws_f(m, CB_TOP), ws_f(m, CB_BASE), T_F32), T_F32), ws_id(m, "hf" as *u8, T_F32), T_F32), ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_c3(m, "smoothstep" as *u8, ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_bin(m, "/" as *u8, ws_f(m, CB_RHI), ws_bin(m, "-" as *u8, ws_f(m, CB_TOP), ws_f(m, CB_BASE), T_F32), T_F32), T_F32), ws_f(m, "1.0" as *u8), ws_id(m, "hf" as *u8, T_F32), T_F32), T_F32), T_F32)))
311 ws_st(m, f, sir_let(m, "thr" as *u8, T_F32, ws_bin(m, "-" as *u8, ws_f(m, CB_THR0), ws_bin(m, "*" as *u8, ws_f(m, CB_THRK), ws_c3(m, "clamp" as *u8, ws_id(m, "cld" as *u8, T_F32), ws_f(m, "0.0" as *u8), ws_f(m, "1.0" as *u8), T_F32), T_F32), T_F32)))
312 ws_st(m, f, sir_let(m, "body" as *u8, T_F32, ws_bin(m, "/" as *u8, ws_bin(m, "-" as *u8, ws_id(m, "shape" as *u8, T_F32), ws_id(m, "thr" as *u8, T_F32), T_F32), ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_id(m, "thr" as *u8, T_F32), T_F32), T_F32)))
313 ws_st(m, f, sir_let(m, "eroded" as *u8, T_F32, ws_bin(m, "-" as *u8, ws_id(m, "body" as *u8, T_F32), ws_bin(m, "*" as *u8, ws_id(m, "detail" as *u8, T_F32), ws_f(m, CB_EROSION), T_F32), T_F32)))
314 ws_st(m, f, ws_ret(m, ws_bin(m, "*" as *u8, ws_c3(m, "clamp" as *u8, ws_bin(m, "*" as *u8, ws_id(m, "eroded" as *u8, T_F32), ws_f(m, CB_GAIN), T_F32), ws_f(m, "0.0" as *u8), ws_f(m, "1.0" as *u8), T_F32), ws_id(m, "env" as *u8, T_F32), T_F32)))
315 return f
316}
317
318func ws_fn_csun(m: *i64) -> i64 {
319 let f: i64 = sir_func(m, "csun" as *u8, T_F32)
320 sir_param(m, f, "p" as *u8, T_V3F)
321 ws_st(m, f, sir_let(m, "dy" as *u8, T_F32, ws_c2(m, "max" as *u8, ws_sx(m, "sund" as *u8, T_V3F, "y" as *u8, T_F32), ws_f(m, CB_SUN_Y_MIN), T_F32)))
322 ws_st(m, f, sir_let(m, "ds" as *u8, T_F32, ws_bin(m, "/" as *u8, ws_c2(m, "min" as *u8, ws_bin(m, "/" as *u8, ws_c2(m, "max" as *u8, ws_bin(m, "-" as *u8, ws_f(m, CB_TOP), ws_sx(m, "p" as *u8, T_V3F, "y" as *u8, T_F32), T_F32), ws_f(m, "0.0" as *u8), T_F32), ws_id(m, "dy" as *u8, T_F32), T_F32), ws_f(m, CB_LIGHT_DISTANCE), T_F32), ws_f(m, CB_LIGHT_STEPS_F), T_F32)))
323 ws_st(m, f, sir_var(m, "tau" as *u8, T_F32, ws_f(m, "0.0" as *u8)))
324 let lp: i64 = sir_let(m, "lp" as *u8, T_V3F, ws_bin(m, "+" as *u8, ws_id(m, "p" as *u8, T_V3F), ws_bin(m, "*" as *u8, ws_id(m, "sund" as *u8, T_V3F), ws_bin(m, "*" as *u8, ws_bin(m, "+" as *u8, ws_fi(m, "j" as *u8), ws_f(m, "0.5" as *u8), T_F32), ws_id(m, "ds" as *u8, T_F32), T_F32), T_V3F), T_V3F))
325 let lt: i64 = ws_op(m, "tau" as *u8, T_F32, "+" as *u8, ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, ws_c1(m, "cvol" as *u8, ws_id(m, "lp" as *u8, T_V3F), T_F32), ws_id(m, "ds" as *u8, T_F32), T_F32), ws_f(m, CB_SIGMA), T_F32))
326 sir_for_until(m, f, sir_var(m, "j" as *u8, T_I32, ws_i(m, "0" as *u8)), ws_cmp(m, ">=" as *u8, ws_id(m, "j" as *u8, T_I32), ws_i(m, CB_LIGHT_STEPS)), ws_op(m, "j" as *u8, T_I32, "+" as *u8, ws_i(m, "1" as *u8)), ws_q2(m, lp, lt))
327 ws_st(m, f, ws_ret(m, ws_c1(m, "exp" as *u8, ws_bin(m, "-" as *u8, ws_f(m, "0.0" as *u8), ws_id(m, "tau" as *u8, T_F32), T_F32), T_F32)))
328 return f
329}
330// fn cld3(rd:vec3f,s0:vec3f)->vec3f -- the march: the sky colour s0 seen through the slab, front to back
331func ws_fn_cld3(m: *i64) -> i64 {
332 let f: i64 = sir_func(m, "cld3" as *u8, T_V3F)
333 sir_param(m, f, "rd" as *u8, T_V3F)
334 sir_param(m, f, "s0" as *u8, T_V3F)
335 ws_st(m, f, ws_if(m, ws_cmp(m, "<=" as *u8, ws_id(m, "cld" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_ret(m, ws_id(m, "s0" as *u8, T_V3F)), 0))
336 ws_st(m, f, sir_let(m, "dy" as *u8, T_F32, ws_sx(m, "rd" as *u8, T_V3F, "y" as *u8, T_F32)))
337 ws_st(m, f, ws_if(m, ws_cmp(m, "==" as *u8, ws_id(m, "dy" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_ret(m, ws_id(m, "s0" as *u8, T_V3F)), 0))
338 ws_st(m, f, sir_let(m, "a" as *u8, T_F32, ws_bin(m, "/" as *u8, ws_bin(m, "-" as *u8, ws_f(m, CB_BASE), ws_sx(m, "cam" as *u8, T_V3F, "y" as *u8, T_F32), T_F32), ws_id(m, "dy" as *u8, T_F32), T_F32)))
339 ws_st(m, f, sir_let(m, "b" as *u8, T_F32, ws_bin(m, "/" as *u8, ws_bin(m, "-" as *u8, ws_f(m, CB_TOP), ws_sx(m, "cam" as *u8, T_V3F, "y" as *u8, T_F32), T_F32), ws_id(m, "dy" as *u8, T_F32), T_F32)))
340 ws_st(m, f, sir_let(m, "t0" as *u8, T_F32, ws_c2(m, "max" as *u8, ws_c2(m, "min" as *u8, ws_id(m, "a" as *u8, T_F32), ws_id(m, "b" as *u8, T_F32), T_F32), ws_f(m, "0.0" as *u8), T_F32)))
341 ws_st(m, f, sir_let(m, "t1" as *u8, T_F32, ws_c2(m, "min" as *u8, ws_c2(m, "max" as *u8, ws_id(m, "a" as *u8, T_F32), ws_id(m, "b" as *u8, T_F32), T_F32), ws_f(m, CB_VIEW_DISTANCE), T_F32)))
342 ws_st(m, f, ws_if(m, ws_cmp(m, "<=" as *u8, ws_id(m, "t1" as *u8, T_F32), ws_id(m, "t0" as *u8, T_F32)), ws_ret(m, ws_id(m, "s0" as *u8, T_V3F)), 0))
343 ws_st(m, f, sir_let(m, "dt" as *u8, T_F32, ws_bin(m, "/" as *u8, ws_bin(m, "-" as *u8, ws_id(m, "t1" as *u8, T_F32), ws_id(m, "t0" as *u8, T_F32), T_F32), ws_f(m, CB_STEPS_F), T_F32)))
344 ws_st(m, f, sir_var(m, "tr" as *u8, T_F32, ws_f(m, "1.0" as *u8)))
345 ws_st(m, f, sir_var(m, "acc" as *u8, T_V3F, ws_v1(m, T_V3F, ws_f(m, "0.0" as *u8))))
346 ws_st(m, f, sir_let(m, "phase" as *u8, T_F32, ws_bin(m, "/" as *u8, ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_bin(m, "*" as *u8, ws_f(m, CB_PHASE_G), ws_f(m, CB_PHASE_G), T_F32), T_F32), ws_c2(m, "pow" as *u8, ws_bin(m, "-" as *u8, ws_bin(m, "+" as *u8, ws_f(m, "1.0" as *u8), ws_bin(m, "*" as *u8, ws_f(m, CB_PHASE_G), ws_f(m, CB_PHASE_G), T_F32), T_F32), ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, ws_f(m, "2.0" as *u8), ws_f(m, CB_PHASE_G), T_F32), ws_c2(m, "dot" as *u8, ws_id(m, "rd" as *u8, T_V3F), ws_id(m, "sund" as *u8, T_V3F), T_F32), T_F32), T_F32), ws_f(m, "1.5" as *u8), T_F32), T_F32)))
347 ws_st(m, f, sir_let(m, "ambient" as *u8, T_V3F, ws_bin(m, "*" as *u8, ws_id(m, "s0" as *u8, T_V3F), ws_f(m, CB_AMBIENT), T_V3F)))
348 let p0: i64 = sir_let(m, "p" as *u8, T_V3F, ws_bin(m, "+" as *u8, ws_id(m, "cam" as *u8, T_V3F), ws_bin(m, "*" as *u8, ws_id(m, "rd" as *u8, T_V3F), ws_bin(m, "+" as *u8, ws_id(m, "t0" as *u8, T_F32), ws_bin(m, "*" as *u8, ws_bin(m, "+" as *u8, ws_fi(m, "i" as *u8), ws_f(m, "0.5" as *u8), T_F32), ws_id(m, "dt" as *u8, T_F32), T_F32), T_F32), T_V3F), T_V3F))
349 let d0: i64 = sir_let(m, "density" as *u8, T_F32, ws_c1(m, "cvol" as *u8, ws_id(m, "p" as *u8, T_V3F), T_F32))
350 let a0: i64 = sir_let(m, "alpha" as *u8, T_F32, ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_c1(m, "exp" as *u8, ws_bin(m, "-" as *u8, ws_f(m, "0.0" as *u8), ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, ws_id(m, "density" as *u8, T_F32), ws_id(m, "dt" as *u8, T_F32), T_F32), ws_f(m, CB_SIGMA), T_F32), T_F32), T_F32), T_F32))
351 let l0: i64 = sir_let(m, "light" as *u8, T_V3F, ws_bin(m, "+" as *u8, ws_id(m, "ambient" as *u8, T_V3F), ws_v1(m, T_V3F, ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, ws_c1(m, "csun" as *u8, ws_id(m, "p" as *u8, T_V3F), T_F32), ws_id(m, "phase" as *u8, T_F32), T_F32), ws_f(m, CB_DIRECT), T_F32), ws_id(m, "sun" as *u8, T_F32), T_F32)), T_V3F))
352 let c0: i64 = ws_op(m, "acc" as *u8, T_V3F, "+" as *u8, ws_bin(m, "*" as *u8, ws_id(m, "light" as *u8, T_V3F), ws_bin(m, "*" as *u8, ws_id(m, "tr" as *u8, T_F32), ws_id(m, "alpha" as *u8, T_F32), T_F32), T_V3F))
353 let t0s: i64 = ws_op(m, "tr" as *u8, T_F32, "*" as *u8, ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_id(m, "alpha" as *u8, T_F32), T_F32))
354 let body: i64 = ws_q2(m, ws_q3(m, p0, d0, a0), ws_if(m, ws_cmp(m, ">" as *u8, ws_id(m, "density" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_q3(m, l0, c0, t0s), 0))
355 sir_for_until(m, f, sir_var(m, "i" as *u8, T_I32, ws_i(m, "0" as *u8)), ws_cmp(m, ">=" as *u8, ws_id(m, "i" as *u8, T_I32), ws_i(m, CB_STEPS)), ws_op(m, "i" as *u8, T_I32, "+" as *u8, ws_i(m, "1" as *u8)), body)
356 ws_st(m, f, ws_ret(m, ws_bin(m, "+" as *u8, ws_bin(m, "*" as *u8, ws_id(m, "s0" as *u8, T_V3F), ws_id(m, "tr" as *u8, T_F32), T_V3F), ws_id(m, "acc" as *u8, T_V3F), T_V3F)))
357 return f
358}
359
360// fn sky(rd:vec3f)->vec3f{ ... } -- the hand text, statement for statement
361func ws_fn_sky(m: *i64) -> i64 {
362 let f: i64 = sir_func(m, "sky" as *u8, T_V3F)
363 sir_param(m, f, "rd" as *u8, T_V3F)
364 // var s:vec3f=mix(u.skh,u.skt,clamp(rd.y*1.6+0.35,0.0,1.0));
365 let cl: i64 = ws_c3(m, "clamp" as *u8, ws_bin(m, "+" as *u8, ws_bin(m, "*" as *u8, ws_sx(m, "rd" as *u8, T_V3F, "y" as *u8, T_F32), ws_f(m, "1.6" as *u8), T_F32), ws_f(m, "0.35" as *u8), T_F32), ws_f(m, "0.0" as *u8), ws_f(m, "1.0" as *u8), T_F32)
366 ws_st(m, f, sir_var(m, "s" as *u8, T_V3F, ws_c3(m, "mix" as *u8, ws_id(m, "skh" as *u8, T_V3F), ws_id(m, "skt" as *u8, T_V3F), cl, T_V3F)))
367 // if(u.sun>0.5){let d=dot(rd,u.sund);if(d>0.9993){s=vec3f(1.0,0.98,0.88);}else if(d>0.985){s=mix(s,vec3f(1.0,0.98,0.88),(d-0.985)/0.015*0.6);}}
368 let dlet: i64 = sir_let(m, "d" as *u8, T_F32, ws_c2(m, "dot" as *u8, ws_id(m, "rd" as *u8, T_V3F), ws_id(m, "sund" as *u8, T_V3F), T_F32))
369 let sunc: i64 = ws_set(m, ws_id(m, "s" as *u8, T_V3F), ws_v3f(m, "1.0" as *u8, "0.98" as *u8, "0.88" as *u8))
370 let glow: i64 = ws_set(m, ws_id(m, "s" as *u8, T_V3F), ws_c3(m, "mix" as *u8, ws_id(m, "s" as *u8, T_V3F), ws_v3f(m, "1.0" as *u8, "0.98" as *u8, "0.88" as *u8), ws_bin(m, "*" as *u8, ws_bin(m, "/" as *u8, ws_bin(m, "-" as *u8, ws_id(m, "d" as *u8, T_F32), ws_f(m, "0.985" as *u8), T_F32), ws_f(m, "0.015" as *u8), T_F32), ws_f(m, "0.6" as *u8), T_F32), T_V3F))
371 let inner: i64 = ws_if(m, ws_cmp(m, ">" as *u8, ws_id(m, "d" as *u8, T_F32), ws_f(m, "0.9993" as *u8)), sunc, ws_if(m, ws_cmp(m, ">" as *u8, ws_id(m, "d" as *u8, T_F32), ws_f(m, "0.985" as *u8)), glow, 0))
372 ws_st(m, f, ws_if(m, ws_cmp(m, ">" as *u8, ws_id(m, "sun" as *u8, T_F32), ws_f(m, "0.5" as *u8)), ws_q2(m, dlet, inner), 0))
373 // PG22: s = cld3(rd, s) -- the cloud is a raymarched 3D density (vn3 / cvol / cld3 above), never the projected
374 // sheet this block used to draw; the cld>0.5 && rd.y>0.04 gate lives inside cld3 as its early return.
375 ws_st(m, f, ws_set(m, ws_id(m, "s" as *u8, T_V3F), ws_c2(m, "cld3" as *u8, ws_id(m, "rd" as *u8, T_V3F), ws_id(m, "s" as *u8, T_V3F), T_V3F)))
376 ws_st(m, f, ws_ret(m, ws_id(m, "s" as *u8, T_V3F)))
377 return f
378}
379
380// struct Hit{t:f32,c:vec3i,fce:i32,b:u32}
381func ws_struct_hit(m: *i64) -> i64 {
382 let st: i64 = sir_struct(m, "Hit" as *u8)
383 sir_member(m, st, "t" as *u8, T_F32)
384 sir_member(m, st, "c" as *u8, T_V3I)
385 sir_member(m, st, "fce" as *u8, T_I32)
386 sir_member(m, st, "b" as *u8, T_U32)
387 return st
388}
389
390// one DDA step: c.<a>=(c.<a>+st.<a>);t=tm.<a>;tm.<a>=(tm.<a>+dd.<a>);fce=select(<f>,<t>,st.<a>>0);
391func ws_dda_step(m: *i64, ax: *u8, fneg: *u8, fpos: *u8) -> i64 {
392 let s1: i64 = ws_opx(m, "c" as *u8, T_V3I, ax, T_I32, "+" as *u8, ws_sx(m, "st" as *u8, T_V3I, ax, T_I32))
393 let s2: i64 = ws_set(m, ws_id(m, "t" as *u8, T_F32), ws_sx(m, "tm" as *u8, T_V3F, ax, T_F32))
394 let s3: i64 = ws_opx(m, "tm" as *u8, T_V3F, ax, T_F32, "+" as *u8, ws_sx(m, "dd" as *u8, T_V3F, ax, T_F32))
395 let s4: i64 = ws_set(m, ws_id(m, "fce" as *u8, T_I32), sir_select(m, ws_cmp(m, ">" as *u8, ws_sx(m, "st" as *u8, T_V3I, ax, T_I32), ws_i(m, "0" as *u8)), ws_i(m, fpos), ws_i(m, fneg), T_I32))
396 return ws_q4(m, s1, s2, s3, s4)
397}
398
399// ---- GE53 THE SURFACE FIELD (WebGPU, emitted from this one source) ---------------------------------------
400// fn hq(x:i32,z:i32)->f32{ if(x<0||z<0||x>127||z>127){return -1.0;} return textureLoad(tH,vec2i(x,z),0).r; }
401// the column's Q height in blocks (the base of its top block), -1 off the window
402func ws_fn_hq(m: *i64) -> i64 {
403 let f: i64 = sir_func(m, "hq" as *u8, T_F32)
404 sir_param(m, f, "x" as *u8, T_I32)
405 sir_param(m, f, "z" as *u8, T_I32)
406 let oob: i64 = ws_or(m, ws_or(m, ws_or(m,
407 ws_cmp(m, "<" as *u8, ws_id(m, "x" as *u8, T_I32), ws_i(m, "0" as *u8)),
408 ws_cmp(m, "<" as *u8, ws_id(m, "z" as *u8, T_I32), ws_i(m, "0" as *u8))),
409 ws_cmp(m, ">" as *u8, ws_id(m, "x" as *u8, T_I32), ws_i(m, "127" as *u8))),
410 ws_cmp(m, ">" as *u8, ws_id(m, "z" as *u8, T_I32), ws_i(m, "127" as *u8)))
411 ws_st(m, f, ws_if(m, oob, ws_ret(m, ws_f(m, "-1.0" as *u8)), 0))
412 let tl: i64 = sir_texload(m, ws_id(m, "tH" as *u8, T_TEX2F), ws_vt2(m, T_V2I, ws_id(m, "x" as *u8, T_I32), ws_id(m, "z" as *u8, T_I32)), ws_i(m, "0" as *u8))
413 ws_st(m, f, ws_ret(m, ws_sw(m, tl, "r" as *u8, T_F32)))
414 return f
415}
416// fn surf(p:vec2f)->f32 -- the terrain SURFACE height at a world xz: bilinear between the four columns,
417// one block above the column base (the top of the ground). -1 when any corner is off the field.
418func ws_fn_surf(m: *i64) -> i64 {
419 let f: i64 = sir_func(m, "surf" as *u8, T_F32)
420 sir_param(m, f, "p" as *u8, T_V2F)
421 ws_st(m, f, sir_let(m, "ix" as *u8, T_I32, sir_cast(m, ws_c1(m, "floor" as *u8, ws_sx(m, "p" as *u8, T_V2F, "x" as *u8, T_F32), T_F32), T_I32)))
422 ws_st(m, f, sir_let(m, "iz" as *u8, T_I32, sir_cast(m, ws_c1(m, "floor" as *u8, ws_sx(m, "p" as *u8, T_V2F, "y" as *u8, T_F32), T_F32), T_I32)))
423 ws_st(m, f, sir_let(m, "fr" as *u8, T_V2F, ws_c1(m, "fract" as *u8, ws_id(m, "p" as *u8, T_V2F), T_V2F)))
424 ws_st(m, f, sir_let(m, "h00" as *u8, T_F32, ws_c2(m, "hq" as *u8, ws_id(m, "ix" as *u8, T_I32), ws_id(m, "iz" as *u8, T_I32), T_F32)))
425 ws_st(m, f, sir_let(m, "h10" as *u8, T_F32, ws_c2(m, "hq" as *u8, ws_bin(m, "+" as *u8, ws_id(m, "ix" as *u8, T_I32), ws_i(m, "1" as *u8), T_I32), ws_id(m, "iz" as *u8, T_I32), T_F32)))
426 ws_st(m, f, sir_let(m, "h01" as *u8, T_F32, ws_c2(m, "hq" as *u8, ws_id(m, "ix" as *u8, T_I32), ws_bin(m, "+" as *u8, ws_id(m, "iz" as *u8, T_I32), ws_i(m, "1" as *u8), T_I32), T_F32)))
427 ws_st(m, f, sir_let(m, "h11" as *u8, T_F32, ws_c2(m, "hq" as *u8, ws_bin(m, "+" as *u8, ws_id(m, "ix" as *u8, T_I32), ws_i(m, "1" as *u8), T_I32), ws_bin(m, "+" as *u8, ws_id(m, "iz" as *u8, T_I32), ws_i(m, "1" as *u8), T_I32), T_F32)))
428 let miss: i64 = ws_or(m, ws_or(m, ws_or(m,
429 ws_cmp(m, "<" as *u8, ws_id(m, "h00" as *u8, T_F32), ws_f(m, "0.0" as *u8)),
430 ws_cmp(m, "<" as *u8, ws_id(m, "h10" as *u8, T_F32), ws_f(m, "0.0" as *u8))),
431 ws_cmp(m, "<" as *u8, ws_id(m, "h01" as *u8, T_F32), ws_f(m, "0.0" as *u8))),
432 ws_cmp(m, "<" as *u8, ws_id(m, "h11" as *u8, T_F32), ws_f(m, "0.0" as *u8)))
433 ws_st(m, f, ws_if(m, miss, ws_ret(m, ws_f(m, "-1.0" as *u8)), 0))
434 let mx0: i64 = ws_c3(m, "mix" as *u8, ws_id(m, "h00" as *u8, T_F32), ws_id(m, "h10" as *u8, T_F32), ws_sx(m, "fr" as *u8, T_V2F, "x" as *u8, T_F32), T_F32)
435 let mx1: i64 = ws_c3(m, "mix" as *u8, ws_id(m, "h01" as *u8, T_F32), ws_id(m, "h11" as *u8, T_F32), ws_sx(m, "fr" as *u8, T_V2F, "x" as *u8, T_F32), T_F32)
436 ws_st(m, f, ws_ret(m, ws_bin(m, "+" as *u8, ws_c3(m, "mix" as *u8, mx0, mx1, ws_sx(m, "fr" as *u8, T_V2F, "y" as *u8, T_F32), T_F32), ws_f(m, "1.0" as *u8), T_F32)))
437 return f
438}
439// fn terrain(b:u32)->i32 -- the ground classes the field replaces; structures (wood, leaves, crops, water) stay cells
440func ws_fn_terrain(m: *i64) -> i64 {
441 let f: i64 = sir_func(m, "terrain" as *u8, T_I32)
442 sir_param(m, f, "b" as *u8, T_U32)
443 let tb: i64 = ws_or(m, ws_or(m, ws_or(m, ws_or(m, ws_or(m, ws_or(m, ws_or(m,
444 ws_beq(m, "1" as *u8), ws_beq(m, "2" as *u8)), ws_beq(m, "3" as *u8)), ws_beq(m, "5" as *u8)), ws_beq(m, "8" as *u8)), ws_beq(m, "9" as *u8)), ws_beq(m, "10" as *u8)), ws_beq(m, "11" as *u8))
445 ws_st(m, f, ws_if(m, tb, ws_ret(m, ws_i(m, "1" as *u8)), 0))
446 ws_st(m, f, ws_ret(m, ws_i(m, "0" as *u8)))
447 return f
448}
449// fn smarch(ro:vec3f,rd:vec3f,mx:i32)->f32 -- march the continuous surface: quarter-block steps (the field is
450// bilinear between columns, so a quarter block can never skip one), exit above the tallest column when climbing,
451// six bisections at the crossing. Returns t, or -1 for sky. The GPU twin of the sim's wray_surf.
452func ws_fn_smarch(m: *i64) -> i64 {
453 let f: i64 = sir_func(m, "smarch" as *u8, T_F32)
454 sir_param(m, f, "ro" as *u8, T_V3F)
455 sir_param(m, f, "rd" as *u8, T_V3F)
456 sir_param(m, f, "mx" as *u8, T_I32)
457 ws_st(m, f, sir_var(m, "t" as *u8, T_F32, ws_f(m, "0.0" as *u8)))
458 ws_st(m, f, sir_var(m, "tp" as *u8, T_F32, ws_f(m, "0.0" as *u8)))
459 ws_st(m, f, sir_var(m, "hit" as *u8, T_I32, ws_i(m, "0" as *u8)))
460 let s1: i64 = ws_op(m, "t" as *u8, T_F32, "+" as *u8, ws_f(m, "0.25" as *u8))
461 let s2: i64 = sir_let(m, "p" as *u8, T_V3F, ws_bin(m, "+" as *u8, ws_id(m, "ro" as *u8, T_V3F), ws_bin(m, "*" as *u8, ws_id(m, "rd" as *u8, T_V3F), ws_id(m, "t" as *u8, T_F32), T_V3F), T_V3F))
462 let s3: i64 = ws_if(m, ws_and(m, ws_cmp(m, ">" as *u8, ws_sx(m, "p" as *u8, T_V3F, "y" as *u8, T_F32), ws_bin(m, "+" as *u8, ws_id(m, "wmax" as *u8, T_F32), ws_f(m, "2.0" as *u8), T_F32)), ws_cmp(m, ">=" as *u8, ws_sx(m, "rd" as *u8, T_V3F, "y" as *u8, T_F32), ws_f(m, "0.0" as *u8))), ws_ret(m, ws_f(m, "-1.0" as *u8)), 0)
463 let oob: i64 = ws_or(m, ws_or(m, ws_or(m,
464 ws_cmp(m, "<" as *u8, ws_sx(m, "p" as *u8, T_V3F, "x" as *u8, T_F32), ws_f(m, "-8.0" as *u8)),
465 ws_cmp(m, ">" as *u8, ws_sx(m, "p" as *u8, T_V3F, "x" as *u8, T_F32), ws_f(m, "136.0" as *u8))),
466 ws_cmp(m, "<" as *u8, ws_sx(m, "p" as *u8, T_V3F, "z" as *u8, T_F32), ws_f(m, "-8.0" as *u8))),
467 ws_cmp(m, ">" as *u8, ws_sx(m, "p" as *u8, T_V3F, "z" as *u8, T_F32), ws_f(m, "136.0" as *u8)))
468 let s4: i64 = ws_if(m, oob, ws_ret(m, ws_f(m, "-1.0" as *u8)), 0)
469 let s5: i64 = sir_let(m, "hs" as *u8, T_F32, ws_c1(m, "surf" as *u8, ws_sx(m, "p" as *u8, T_V3F, "xz" as *u8, T_V2F), T_F32))
470 let s6: i64 = ws_if(m, ws_and(m, ws_cmp(m, ">=" as *u8, ws_id(m, "hs" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_cmp(m, "<=" as *u8, ws_sx(m, "p" as *u8, T_V3F, "y" as *u8, T_F32), ws_id(m, "hs" as *u8, T_F32))), ws_q2(m, ws_set(m, ws_id(m, "hit" as *u8, T_I32), ws_i(m, "1" as *u8)), sir_break(m)), 0)
471 let s7: i64 = ws_set(m, ws_id(m, "tp" as *u8, T_F32), ws_id(m, "t" as *u8, T_F32))
472 let body: i64 = ws_q4(m, ws_q3(m, s1, s2, s3), s4, s5, ws_q2(m, s6, s7))
473 sir_for_until(m, f, sir_var(m, "i" as *u8, T_I32, ws_i(m, "0" as *u8)), ws_cmp(m, ">=" as *u8, ws_id(m, "i" as *u8, T_I32), ws_bin(m, "*" as *u8, ws_id(m, "mx" as *u8, T_I32), ws_i(m, "4" as *u8), T_I32)), ws_op(m, "i" as *u8, T_I32, "+" as *u8, ws_i(m, "1" as *u8)), body)
474 ws_st(m, f, ws_if(m, ws_cmp(m, "==" as *u8, ws_id(m, "hit" as *u8, T_I32), ws_i(m, "0" as *u8)), ws_ret(m, ws_f(m, "-1.0" as *u8)), 0))
475 ws_st(m, f, sir_var(m, "lo" as *u8, T_F32, ws_id(m, "tp" as *u8, T_F32)))
476 ws_st(m, f, sir_var(m, "hi" as *u8, T_F32, ws_id(m, "t" as *u8, T_F32)))
477 let k1: i64 = sir_let(m, "md" as *u8, T_F32, ws_bin(m, "*" as *u8, ws_bin(m, "+" as *u8, ws_id(m, "lo" as *u8, T_F32), ws_id(m, "hi" as *u8, T_F32), T_F32), ws_f(m, "0.5" as *u8), T_F32))
478 let k2: i64 = sir_let(m, "q" as *u8, T_V3F, ws_bin(m, "+" as *u8, ws_id(m, "ro" as *u8, T_V3F), ws_bin(m, "*" as *u8, ws_id(m, "rd" as *u8, T_V3F), ws_id(m, "md" as *u8, T_F32), T_V3F), T_V3F))
479 let k3: i64 = sir_let(m, "h2" as *u8, T_F32, ws_c1(m, "surf" as *u8, ws_sx(m, "q" as *u8, T_V3F, "xz" as *u8, T_V2F), T_F32))
480 let k4: i64 = ws_if(m, ws_and(m, ws_cmp(m, ">=" as *u8, ws_id(m, "h2" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_cmp(m, "<=" as *u8, ws_sx(m, "q" as *u8, T_V3F, "y" as *u8, T_F32), ws_id(m, "h2" as *u8, T_F32))), ws_set(m, ws_id(m, "hi" as *u8, T_F32), ws_id(m, "md" as *u8, T_F32)), ws_set(m, ws_id(m, "lo" as *u8, T_F32), ws_id(m, "md" as *u8, T_F32)))
481 sir_for_until(m, f, sir_var(m, "k" as *u8, T_I32, ws_i(m, "0" as *u8)), ws_cmp(m, ">=" as *u8, ws_id(m, "k" as *u8, T_I32), ws_i(m, "6" as *u8)), ws_op(m, "k" as *u8, T_I32, "+" as *u8, ws_i(m, "1" as *u8)), ws_q4(m, k1, k2, k3, k4))
482 ws_st(m, f, ws_ret(m, ws_id(m, "hi" as *u8, T_F32)))
483 return f
484}
485// fn gnd(p:vec2f)->f32 -- the ground light from the field's own gradient (central differences a quarter block
486// apart), Lambert against the sun and NORMALISED TO LEVEL GROUND: level lights exactly as the shipped flat top
487// face (1.0), the lee side floors at the shipped darkest face (0.42) -- the same two values shade's six-way
488// face table carries, so a flat field is byte-identical in brightness to a flat block top.
489func ws_fn_gnd(m: *i64) -> i64 {
490 let f: i64 = sir_func(m, "gnd" as *u8, T_F32)
491 sir_param(m, f, "p" as *u8, T_V2F)
492 ws_st(m, f, sir_let(m, "hl" as *u8, T_F32, ws_c1(m, "surf" as *u8, ws_bin(m, "-" as *u8, ws_id(m, "p" as *u8, T_V2F), ws_v2f(m, "0.25" as *u8, "0.0" as *u8), T_V2F), T_F32)))
493 ws_st(m, f, sir_let(m, "hr" as *u8, T_F32, ws_c1(m, "surf" as *u8, ws_bin(m, "+" as *u8, ws_id(m, "p" as *u8, T_V2F), ws_v2f(m, "0.25" as *u8, "0.0" as *u8), T_V2F), T_F32)))
494 ws_st(m, f, sir_let(m, "hd" as *u8, T_F32, ws_c1(m, "surf" as *u8, ws_bin(m, "-" as *u8, ws_id(m, "p" as *u8, T_V2F), ws_v2f(m, "0.0" as *u8, "0.25" as *u8), T_V2F), T_F32)))
495 ws_st(m, f, sir_let(m, "hu" as *u8, T_F32, ws_c1(m, "surf" as *u8, ws_bin(m, "+" as *u8, ws_id(m, "p" as *u8, T_V2F), ws_v2f(m, "0.0" as *u8, "0.25" as *u8), T_V2F), T_F32)))
496 let miss: i64 = ws_or(m, ws_or(m, ws_or(m,
497 ws_cmp(m, "<" as *u8, ws_id(m, "hl" as *u8, T_F32), ws_f(m, "0.0" as *u8)),
498 ws_cmp(m, "<" as *u8, ws_id(m, "hr" as *u8, T_F32), ws_f(m, "0.0" as *u8))),
499 ws_cmp(m, "<" as *u8, ws_id(m, "hd" as *u8, T_F32), ws_f(m, "0.0" as *u8))),
500 ws_cmp(m, "<" as *u8, ws_id(m, "hu" as *u8, T_F32), ws_f(m, "0.0" as *u8)))
501 ws_st(m, f, ws_if(m, miss, ws_ret(m, ws_f(m, "1.0" as *u8)), 0))
502 let nx: i64 = ws_bin(m, "/" as *u8, ws_bin(m, "-" as *u8, ws_id(m, "hl" as *u8, T_F32), ws_id(m, "hr" as *u8, T_F32), T_F32), ws_f(m, "0.5" as *u8), T_F32)
503 let nz: i64 = ws_bin(m, "/" as *u8, ws_bin(m, "-" as *u8, ws_id(m, "hd" as *u8, T_F32), ws_id(m, "hu" as *u8, T_F32), T_F32), ws_f(m, "0.5" as *u8), T_F32)
504 ws_st(m, f, sir_let(m, "n9" as *u8, T_V3F, ws_c1(m, "normalize" as *u8, ws_v3(m, nx, ws_f(m, "1.0" as *u8), nz), T_V3F)))
505 ws_st(m, f, sir_let(m, "cp" as *u8, T_F32, ws_c2(m, "max" as *u8, ws_c2(m, "dot" as *u8, ws_id(m, "n9" as *u8, T_V3F), ws_id(m, "sund" as *u8, T_V3F), T_F32), ws_f(m, "0.0" as *u8), T_F32)))
506 ws_st(m, f, sir_let(m, "cf" as *u8, T_F32, ws_c2(m, "max" as *u8, ws_sx(m, "sund" as *u8, T_V3F, "y" as *u8, T_F32), ws_f(m, "0.001" as *u8), T_F32)))
507 let span: i64 = ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_f(m, "0.42" as *u8), T_F32)
508 ws_st(m, f, ws_ret(m, ws_c2(m, "min" as *u8, ws_bin(m, "+" as *u8, ws_f(m, "0.42" as *u8), ws_bin(m, "*" as *u8, span, ws_bin(m, "/" as *u8, ws_id(m, "cp" as *u8, T_F32), ws_id(m, "cf" as *u8, T_F32), T_F32), T_F32), T_F32), ws_f(m, "1.0" as *u8), T_F32)))
509 return f
510}
511
512// fn march(ro:vec3f,rd:vec3f,skipw:i32,mx:i32)->Hit{ ... }
513func ws_fn_march(m: *i64, hty: i64) -> i64 {
514 let f: i64 = sir_func(m, "march" as *u8, hty)
515 sir_param(m, f, "ro" as *u8, T_V3F)
516 sir_param(m, f, "rd" as *u8, T_V3F)
517 sir_param(m, f, "skipw" as *u8, T_I32)
518 sir_param(m, f, "mx" as *u8, T_I32)
519 sir_param(m, f, "skipt" as *u8, T_I32) // GE53: 1 = terrain cells are air (the field is the ground); callers pass u.r_surf
520 // var h:Hit;h.t=-1.0;h.fce=0;h.b=0u;h.c=vec3i(0);
521 ws_st(m, f, sir_var(m, "h" as *u8, hty, 0))
522 ws_st(m, f, ws_set(m, ws_mem(m, ws_id(m, "h" as *u8, hty), "t" as *u8, T_F32), ws_f(m, "-1.0" as *u8)))
523 ws_st(m, f, ws_set(m, ws_mem(m, ws_id(m, "h" as *u8, hty), "fce" as *u8, T_I32), ws_i(m, "0" as *u8)))
524 ws_st(m, f, ws_set(m, ws_mem(m, ws_id(m, "h" as *u8, hty), "b" as *u8, T_U32), ws_u(m, "0" as *u8)))
525 ws_st(m, f, ws_set(m, ws_mem(m, ws_id(m, "h" as *u8, hty), "c" as *u8, T_V3I), ws_v1(m, T_V3I, ws_i(m, "0" as *u8))))
526 // var c:vec3i=vec3i(floor(ro));let st=vec3i(sign(rd));
527 ws_st(m, f, sir_var(m, "c" as *u8, T_V3I, ws_v1(m, T_V3I, ws_c1(m, "floor" as *u8, ws_id(m, "ro" as *u8, T_V3F), T_V3F))))
528 ws_st(m, f, sir_let(m, "st" as *u8, T_V3I, ws_v1(m, T_V3I, ws_c1(m, "sign" as *u8, ws_id(m, "rd" as *u8, T_V3F), T_V3F))))
529 // let dd=abs(vec3f(1.0)/max(abs(rd),vec3f(1e-6)));
530 ws_st(m, f, sir_let(m, "dd" as *u8, T_V3F, ws_c1(m, "abs" as *u8, ws_bin(m, "/" as *u8, ws_v1(m, T_V3F, ws_f(m, "1.0" as *u8)), ws_c2(m, "max" as *u8, ws_c1(m, "abs" as *u8, ws_id(m, "rd" as *u8, T_V3F), T_V3F), ws_v1(m, T_V3F, ws_f(m, "1e-6" as *u8)), T_V3F), T_V3F), T_V3F)))
531 // var tm=(vec3f(st)*(vec3f(c)-ro)+vec3f(st)*0.5+vec3f(0.5))*dd;
532 let tm0: i64 = ws_bin(m, "*" as *u8, ws_v1(m, T_V3F, ws_id(m, "st" as *u8, T_V3I)), ws_bin(m, "-" as *u8, ws_v1(m, T_V3F, ws_id(m, "c" as *u8, T_V3I)), ws_id(m, "ro" as *u8, T_V3F), T_V3F), T_V3F)
533 let tm1: i64 = ws_bin(m, "+" as *u8, tm0, ws_bin(m, "*" as *u8, ws_v1(m, T_V3F, ws_id(m, "st" as *u8, T_V3I)), ws_f(m, "0.5" as *u8), T_V3F), T_V3F)
534 let tm2: i64 = ws_bin(m, "+" as *u8, tm1, ws_v1(m, T_V3F, ws_f(m, "0.5" as *u8)), T_V3F)
535 ws_st(m, f, sir_var(m, "tm" as *u8, T_V3F, ws_bin(m, "*" as *u8, tm2, ws_id(m, "dd" as *u8, T_V3F), T_V3F)))
536 ws_st(m, f, sir_var(m, "t" as *u8, T_F32, ws_f(m, "0.0" as *u8)))
537 ws_st(m, f, sir_var(m, "fce" as *u8, T_I32, ws_i(m, "0" as *u8)))
538 // for(var i:i32=0;i<200;i++){ ... }
539 let b1: i64 = ws_if(m, ws_cmp(m, ">=" as *u8, ws_id(m, "i" as *u8, T_I32), ws_id(m, "mx" as *u8, T_I32)), sir_break(m), 0)
540 let cx: i64 = ws_and(m, ws_cmp(m, "<" as *u8, ws_sx(m, "tm" as *u8, T_V3F, "x" as *u8, T_F32), ws_sx(m, "tm" as *u8, T_V3F, "y" as *u8, T_F32)), ws_cmp(m, "<" as *u8, ws_sx(m, "tm" as *u8, T_V3F, "x" as *u8, T_F32), ws_sx(m, "tm" as *u8, T_V3F, "z" as *u8, T_F32)))
541 let cy: i64 = ws_cmp(m, "<" as *u8, ws_sx(m, "tm" as *u8, T_V3F, "y" as *u8, T_F32), ws_sx(m, "tm" as *u8, T_V3F, "z" as *u8, T_F32))
542 let b2: i64 = ws_if(m, cx, ws_dda_step(m, "x" as *u8, "1" as *u8, "2" as *u8), ws_if(m, cy, ws_dda_step(m, "y" as *u8, "3" as *u8, "4" as *u8), ws_dda_step(m, "z" as *u8, "5" as *u8, "6" as *u8)))
543 // if(f32(c.y)>u.wmax&&rd.y>=0.0){return h;}if(c.y<0){return h;}
544 let b3: i64 = ws_if(m, ws_and(m, ws_cmp(m, ">" as *u8, sir_cast(m, ws_sx(m, "c" as *u8, T_V3I, "y" as *u8, T_I32), T_F32), ws_id(m, "wmax" as *u8, T_F32)), ws_cmp(m, ">=" as *u8, ws_sx(m, "rd" as *u8, T_V3F, "y" as *u8, T_F32), ws_f(m, "0.0" as *u8))), ws_ret(m, ws_id(m, "h" as *u8, hty)), 0)
545 let b4: i64 = ws_if(m, ws_cmp(m, "<" as *u8, ws_sx(m, "c" as *u8, T_V3I, "y" as *u8, T_I32), ws_i(m, "0" as *u8)), ws_ret(m, ws_id(m, "h" as *u8, hty)), 0)
546 // if(c.x< -8||c.x>135||c.z< -8||c.z>135){return h;}
547 let oob: i64 = ws_or(m, ws_or(m, ws_or(m, ws_cmp(m, "<" as *u8, ws_sx(m, "c" as *u8, T_V3I, "x" as *u8, T_I32), ws_i(m, "-8" as *u8)), ws_cmp(m, ">" as *u8, ws_sx(m, "c" as *u8, T_V3I, "x" as *u8, T_I32), ws_i(m, "135" as *u8))), ws_cmp(m, "<" as *u8, ws_sx(m, "c" as *u8, T_V3I, "z" as *u8, T_I32), ws_i(m, "-8" as *u8))), ws_cmp(m, ">" as *u8, ws_sx(m, "c" as *u8, T_V3I, "z" as *u8, T_I32), ws_i(m, "135" as *u8)))
548 let b5: i64 = ws_if(m, oob, ws_ret(m, ws_id(m, "h" as *u8, hty)), 0)
549 // var b=vx(c);if(skipw==1&&b==4u){b=0u;}
550 let b6: i64 = sir_var(m, "b" as *u8, T_U32, ws_c1(m, "vx" as *u8, ws_id(m, "c" as *u8, T_V3I), T_U32))
551 // GE53: under skipt the terrain classes are air too -- the field is the ground, only structures stay cells
552 let b7: i64 = ws_q2(m,
553 ws_if(m, ws_and(m, ws_cmp(m, "==" as *u8, ws_id(m, "skipw" as *u8, T_I32), ws_i(m, "1" as *u8)), ws_cmp(m, "==" as *u8, ws_id(m, "b" as *u8, T_U32), ws_u(m, "4" as *u8))), ws_set(m, ws_id(m, "b" as *u8, T_U32), ws_u(m, "0" as *u8)), 0),
554 ws_if(m, ws_and(m, ws_cmp(m, "==" as *u8, ws_id(m, "skipt" as *u8, T_I32), ws_i(m, "1" as *u8)), ws_cmp(m, "==" as *u8, ws_c1(m, "terrain" as *u8, ws_id(m, "b" as *u8, T_U32), T_I32), ws_i(m, "1" as *u8))), ws_set(m, ws_id(m, "b" as *u8, T_U32), ws_u(m, "0" as *u8)), 0))
555 // if(b!=0u){h.t=t;h.c=c;h.fce=fce;h.b=b;return h;}
556 let hit: i64 = ws_q5(m,
557 ws_set(m, ws_mem(m, ws_id(m, "h" as *u8, hty), "t" as *u8, T_F32), ws_id(m, "t" as *u8, T_F32)),
558 ws_set(m, ws_mem(m, ws_id(m, "h" as *u8, hty), "c" as *u8, T_V3I), ws_id(m, "c" as *u8, T_V3I)),
559 ws_set(m, ws_mem(m, ws_id(m, "h" as *u8, hty), "fce" as *u8, T_I32), ws_id(m, "fce" as *u8, T_I32)),
560 ws_set(m, ws_mem(m, ws_id(m, "h" as *u8, hty), "b" as *u8, T_U32), ws_id(m, "b" as *u8, T_U32)),
561 ws_ret(m, ws_id(m, "h" as *u8, hty)))
562 let b8: i64 = ws_if(m, ws_cmp(m, "!=" as *u8, ws_id(m, "b" as *u8, T_U32), ws_u(m, "0" as *u8)), hit, 0)
563 let body: i64 = ws_q4(m, ws_q4(m, b1, b2, b3, b4), b5, b6, ws_q2(m, b7, b8))
564 sir_for_until(m, f, sir_var(m, "i" as *u8, T_I32, ws_i(m, "0" as *u8)), ws_cmp(m, ">=" as *u8, ws_id(m, "i" as *u8, T_I32), ws_i(m, "200" as *u8)), ws_op(m, "i" as *u8, T_I32, "+" as *u8, ws_i(m, "1" as *u8)), body)
565 ws_st(m, f, ws_ret(m, ws_id(m, "h" as *u8, hty)))
566 return f
567}
568
569// one face arm of shade: uv=hp.<sw>;oc.<ax>=(oc.<ax><op>1);n=vec3f(<nx>,<ny>,<nz>);
570func ws_face(m: *i64, sw: *u8, ax: *u8, op: *u8, nx: *u8, ny: *u8, nz: *u8) -> i64 {
571 return ws_q3(m,
572 ws_set(m, ws_id(m, "uv" as *u8, T_V2F), ws_sx(m, "hp" as *u8, T_V3F, sw, T_V2F)),
573 ws_opx(m, "oc" as *u8, T_V3I, ax, T_I32, op, ws_i(m, "1" as *u8)),
574 ws_set(m, ws_id(m, "n" as *u8, T_V3F), ws_v3f(m, nx, ny, nz)))
575}
576// li=(li*<k>)
577func ws_li(m: *i64, k: *u8) -> i64 { return ws_op(m, "li" as *u8, T_F32, "*" as *u8, ws_f(m, k)) }
578// fce==<k>
579func 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)) }
580// b==<k>u
581func 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)) }
582// one AO probe: if(f.<fa> <cmp> <edge>){var nb=oc; <nudge>; if(vx(nb)!=0u&&vx(nb)!=4u){ao=(ao+(<gain>)*2.0);}}
583func ws_ao(m: *i64, fa: *u8, cmp: *u8, edge: *u8, nudge: i64, gain: i64) -> i64 {
584 let nbv: i64 = sir_var(m, "nb" as *u8, T_V3I, ws_id(m, "oc" as *u8, T_V3I))
585 let solid: i64 = ws_and(m, ws_cmp(m, "!=" as *u8, ws_c1(m, "vx" as *u8, ws_id(m, "nb" as *u8, T_V3I), T_U32), ws_u(m, "0" as *u8)), ws_cmp(m, "!=" as *u8, ws_c1(m, "vx" as *u8, ws_id(m, "nb" as *u8, T_V3I), T_U32), ws_u(m, "4" as *u8)))
586 let add: i64 = ws_op(m, "ao" as *u8, T_F32, "+" as *u8, ws_bin(m, "*" as *u8, gain, ws_f(m, "2.0" as *u8), T_F32))
587 return ws_if(m, ws_cmp(m, cmp, ws_sx(m, "f" as *u8, T_V2F, fa, T_F32), ws_f(m, edge)), ws_q3(m, nbv, nudge, ws_if(m, solid, add, 0)), 0)
588}
589// nb.<ax>=(nb.<ax><op>1)
590func 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)) }
591// fce==3||fce==4
592func ws_topbot(m: *i64) -> i64 { return ws_or(m, ws_fce(m, "3" as *u8), ws_fce(m, "4" as *u8)) }
593
594// fn shade(ro:vec3f,rd:vec3f,t:f32,c:vec3i,fce:i32,b:u32)->vec3f{ ... }
595// GE53 helpers -- each call builds a FRESH node tree (a node is never two children).
596// Terrain lighting belongs only to a field hit, never to water or an object top face.
597func ws_smooth(m: *i64) -> i64 {
598 let field: i64 = ws_and(m, ws_cmp(m, "==" as *u8, sir_ident(m, "r_surf" as *u8, T_I32), ws_i(m, "1" as *u8)), ws_fce(m, "3" as *u8))
599 return ws_and(m, field, ws_cmp(m, "==" as *u8, ws_c1(m, "terrain" as *u8, ws_id(m, "b" as *u8, T_U32), T_I32), ws_i(m, "1" as *u8)))
600}
601// The analytic plane has two sides; neither inherits the voxel material's cell decoration.
602func ws_cont_water(m: *i64) -> i64 {
603 return ws_and(m, ws_and(m, ws_cmp(m, "==" as *u8, sir_ident(m, "r_surf" as *u8, T_I32), ws_i(m, "1" as *u8)), ws_beq(m, "4" as *u8)), ws_topbot(m))
604}
605func ws_cont_surface(m: *i64) -> i64 { return ws_or(m, ws_smooth(m), ws_cont_water(m)) }
606// one step of the scan-down to the column's top solid cell: if(cy9>0&&vx(vec3i(cx9,cy9,cz9))==0u){cy9=cy9-1;}
607func ws_step_down(m: *i64) -> i64 {
608 return ws_if(m, ws_and(m, ws_cmp(m, ">" as *u8, ws_id(m, "cy9" as *u8, T_I32), ws_i(m, "0" as *u8)), ws_cmp(m, "==" as *u8, ws_c1(m, "vx" as *u8, ws_vt3(m, T_V3I, ws_id(m, "cx9" as *u8, T_I32), ws_id(m, "cy9" as *u8, T_I32), ws_id(m, "cz9" as *u8, T_I32)), T_U32), ws_u(m, "0" as *u8))), ws_op(m, "cy9" as *u8, T_I32, "-" as *u8, ws_i(m, "1" as *u8)), 0)
609}
610// ---- GR27 (2026-09-06): THE GROUND IS A MATERIAL, NOT A PAINT -----------------------------------------------
611// fn sand(hp:vec3f,c:vec3i,rd:vec3f,t:f32)->vec2f -- the field's ground material, all arithmetic on the surface
612// field and the voxel volume, no texture. x = the light multiplier: the gnd() Lambert (level 1.0, lee floor 0.42)
613// taken on the field normal TILTED by grain facets and wind ripples, then wet-darkened; y = the specular: a thin
614// water film inside the wet band (a Blinn lobe plus a Fresnel sky sheen) and dry quartz glints.
615// FOOTPRINT: one pixel spans 2/res.x world units per unit distance (sc = px/(res.x*0.5)), stretched by 1/|n.rd|
616// at grazing angles. A hash cannot be mip-averaged, so every detail whose period falls under TWO footprints
617// (the Nyquist bound) fades to zero instead of aliasing -- grains and ripples survive a grazing view by
618// fading, never by sparkling; beyond that range sand reads as its albedo, which is what sand does.
619// WET BAND: the volume is probed for water (class 4) on a ring of SD_RING_DIRS directions x SD_WET_R radii at
620// the column's top solid cell and one below it; the nearest water radius sets the wetness (adjacent 1, three
621// cells 1/3, beyond 0) and a water cell ABOVE the column means submerged (1). Wet sand darkens because pore
622// water index-matches the grains (albedo x SD_WET_DARK) and gains a film sheen; the swash erases ripples.
623// Every constant below is a data hook: the ripple heading is the wind row's heading and the grain scale the
624// recipe's sand grade; both become raw words when the material table lands, and are NAMED here until then.
625const SD_GRAIN_PER_BLOCK: *u8 = "32.0" // facets per block edge: 3 cm at a 1 m block, coarse beach sand
626const SD_GRAIN_SLOPE: *u8 = "1.2" // facet steepness as a normal slope
627const SD_RIPPLE_PER_BLOCK: *u8 = "9.0" // wind ripples per block: an 11 cm wavelength at a 1 m block
628const SD_RIPPLE_SLOPE: *u8 = "0.45" // crest slope
629const SD_RIPPLE_DX: *u8 = "0.8" // ripple normal heading (unit): the wind heading, a data hook
630const SD_RIPPLE_DZ: *u8 = "0.6"
631const SD_PATCH: *u8 = "0.25" // ripple phase jitter per 4-block patch so the field is not one sine
632const SD_TAU: *u8 = "6.2831853"
633const SD_QUARTER_TURN: *u8 = "1.5707963"
634const SD_EIGHTH_TURN: *u8 = "0.7853982"
635const SD_RING_DIRS: *u8 = "8"
636const SD_RING_STEPS: *u8 = "24" // SD_RING_DIRS x SD_WET_R
637const SD_WET_R: *u8 = "3.0" // wet band reach in cells
638const SD_WET_DRY: *u8 = "4.0" // SD_WET_R + 1: no water within reach
639const SD_WET_DARK: *u8 = "0.55" // wet albedo multiplier
640const SD_FILM_POW: *u8 = "48.0"
641const SD_FILM_GAIN: *u8 = "0.55"
642const SD_SHEEN_GAIN: *u8 = "0.10"
643const SD_GLINT_POW: *u8 = "96.0"
644const SD_GLINT_GAIN: *u8 = "0.35"
645const SD_GLINT_FRAC: *u8 = "0.9" // facets whose hash exceeds this are quartz glints
646const SD_NDV_FLOOR: *u8 = "0.15" // the footprint stretch floor at grazing angles
647const SD_SHADOW_SPEC: *u8 = "0.2" // in a block shadow the film keeps its sky sheen and loses the sun
648const SD_TWO: *u8 = "2.0"
649const SD_HALF: *u8 = "0.5"
650// helpers -- every call builds a FRESH node tree (a node is never two children)
651func ws_sd_pxz(m: *i64) -> i64 { return ws_sx(m, "hp" as *u8, T_V3F, "xz" as *u8, T_V2F) }
652func ws_sd_f(m: *i64, n: *u8) -> i64 { return ws_id(m, n, T_F32) }
653func ws_sd_v3(m: *i64, n: *u8) -> i64 { return ws_id(m, n, T_V3F) }
654// surf(hp.xz <op> (dx,dz))
655func 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) }
656// h21(gc + (dx,dz))
657func 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) }
658func 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)) }
659func 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) }
660// vx(c + vec3i(dx*k, <y>, dz*k)) == 4u
661func 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)) }
662// i32(floor(sin(a + <shift>) + 0.5)) -- the ring direction from the angle, sin only (the covered subset)
663func 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) }
664// clamp(1 - 2*fp*<freq>, 0, 1) -- the Nyquist fade of a detail with <freq> periods per block
665func 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) }
666// (a - b) * <k>
667func 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) }
668// <s> + gam*<g> - dry*rs*<rdk> -- one axis of the tilted normal
669func ws_sd_tilt(m: *i64, s: *u8, g: *u8, rdk: *u8) -> i64 {
670 let a: i64 = ws_bin(m, "+" as *u8, ws_sd_f(m, s), ws_bin(m, "*" as *u8, ws_sd_f(m, "gam" as *u8), ws_sd_f(m, g), T_F32), T_F32)
671 return ws_bin(m, "-" as *u8, a, ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, ws_sd_f(m, "dry" as *u8), ws_sd_f(m, "rs" as *u8), T_F32), ws_f(m, rdk), T_F32), T_F32)
672}
673// the sand classes: 1 the shore slot (SHORE repaints the grass slot as shore sand), 2 packed sand, 5 sand at and
674// below the waterline (nx_wasm_craft gencol) -- and ONLY under the field (ws_smooth), which today is the shore
675// world's ground; a per-class material word is the data hook owed before another world's field lands
676func 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)) }
677func ws_sandy(m: *i64) -> i64 { return ws_and(m, ws_smooth(m), ws_sandcls(m)) }
678// the block-shadow arm: li*=0.55 as shipped, and the film specular loses the sun (keeps its sky sheen)
679func 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))) }
680func ws_fn_sand(m: *i64) -> i64 {
681 let f: i64 = sir_func(m, "sand" as *u8, T_V2F)
682 sir_param(m, f, "hp" as *u8, T_V3F)
683 sir_param(m, f, "c" as *u8, T_V3I)
684 sir_param(m, f, "rd" as *u8, T_V3F)
685 sir_param(m, f, "t" as *u8, T_F32)
686 // the field normal from the same quarter-block central differences gnd uses; off the field = the flat answer
687 ws_st(m, f, sir_let(m, "hl" as *u8, T_F32, ws_sd_surf(m, "-" as *u8, "0.25" as *u8, "0.0" as *u8)))
688 ws_st(m, f, sir_let(m, "hr" as *u8, T_F32, ws_sd_surf(m, "+" as *u8, "0.25" as *u8, "0.0" as *u8)))
689 ws_st(m, f, sir_let(m, "hd" as *u8, T_F32, ws_sd_surf(m, "-" as *u8, "0.0" as *u8, "0.25" as *u8)))
690 ws_st(m, f, sir_let(m, "hu" as *u8, T_F32, ws_sd_surf(m, "+" as *u8, "0.0" as *u8, "0.25" as *u8)))
691 let miss: i64 = ws_or(m, ws_or(m, ws_or(m, ws_sd_lt0(m, "hl" as *u8), ws_sd_lt0(m, "hr" as *u8)), ws_sd_lt0(m, "hd" as *u8)), ws_sd_lt0(m, "hu" as *u8))
692 ws_st(m, f, ws_if(m, miss, ws_ret(m, ws_v2f(m, "1.0" as *u8, "0.0" as *u8)), 0))
693 ws_st(m, f, sir_let(m, "sx" as *u8, T_F32, ws_sd_dslope(m, "hl" as *u8, "hr" as *u8, SD_TWO)))
694 ws_st(m, f, sir_let(m, "sz" as *u8, T_F32, ws_sd_dslope(m, "hd" as *u8, "hu" as *u8, SD_TWO)))
695 ws_st(m, f, sir_let(m, "nrm" as *u8, T_V3F, ws_c1(m, "normalize" as *u8, ws_v3(m, ws_sd_f(m, "sx" as *u8), ws_f(m, "1.0" as *u8), ws_sd_f(m, "sz" as *u8)), T_V3F)))
696 // the pixel footprint at this hit, stretched by the grazing angle
697 ws_st(m, f, sir_let(m, "ndv" as *u8, T_F32, ws_c2(m, "max" as *u8, ws_c1(m, "abs" as *u8, ws_c2(m, "dot" as *u8, ws_sd_v3(m, "nrm" as *u8), ws_sd_v3(m, "rd" as *u8), T_F32), T_F32), ws_f(m, SD_NDV_FLOOR), T_F32)))
698 ws_st(m, f, sir_let(m, "fp" as *u8, T_F32, ws_bin(m, "/" as *u8, ws_bin(m, "*" as *u8, ws_sd_f(m, "t" as *u8), ws_bin(m, "/" as *u8, ws_f(m, SD_TWO), ws_sx(m, "res" as *u8, T_V2F, "x" as *u8, T_F32), T_F32), T_F32), ws_sd_f(m, "ndv" as *u8), T_F32)))
699 // grain facets: three hash taps a facet apart give the facet's two slopes; the amplitude fades at the Nyquist bound
700 ws_st(m, f, sir_let(m, "gc" as *u8, T_V2F, ws_c1(m, "floor" as *u8, ws_bin(m, "*" as *u8, ws_sd_pxz(m), ws_f(m, SD_GRAIN_PER_BLOCK), T_V2F), T_V2F)))
701 ws_st(m, f, sir_let(m, "g0" as *u8, T_F32, ws_sd_g(m, "0.0" as *u8, "0.0" as *u8)))
702 ws_st(m, f, sir_let(m, "g1" as *u8, T_F32, ws_sd_g(m, "1.0" as *u8, "0.0" as *u8)))
703 ws_st(m, f, sir_let(m, "g2" as *u8, T_F32, ws_sd_g(m, "0.0" as *u8, "1.0" as *u8)))
704 ws_st(m, f, sir_let(m, "gam" as *u8, T_F32, ws_sd_fade(m, SD_GRAIN_PER_BLOCK)))
705 ws_st(m, f, sir_let(m, "gx" as *u8, T_F32, ws_sd_dslope(m, "g0" as *u8, "g1" as *u8, SD_GRAIN_SLOPE)))
706 ws_st(m, f, sir_let(m, "gz" as *u8, T_F32, ws_sd_dslope(m, "g0" as *u8, "g2" as *u8, SD_GRAIN_SLOPE)))
707 // wind ripples: a crest slope along the wind heading, phase-jittered per patch, fading at its own Nyquist bound
708 let ph0: i64 = ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, ws_c2(m, "dot" as *u8, ws_sd_pxz(m), ws_v2f(m, SD_RIPPLE_DX, SD_RIPPLE_DZ), T_F32), ws_f(m, SD_RIPPLE_PER_BLOCK), T_F32), ws_f(m, SD_TAU), T_F32)
709 let ph1: i64 = ws_bin(m, "*" as *u8, ws_c1(m, "h21" as *u8, ws_c1(m, "floor" as *u8, ws_bin(m, "*" as *u8, ws_sd_pxz(m), ws_f(m, SD_PATCH), T_V2F), T_V2F), T_F32), ws_f(m, SD_TAU), T_F32)
710 ws_st(m, f, sir_let(m, "ph" as *u8, T_F32, ws_bin(m, "+" as *u8, ph0, ph1, T_F32)))
711 ws_st(m, f, sir_let(m, "ram" as *u8, T_F32, ws_sd_fade(m, SD_RIPPLE_PER_BLOCK)))
712 ws_st(m, f, sir_let(m, "rs" as *u8, T_F32, ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, ws_c1(m, "sin" as *u8, ws_bin(m, "+" as *u8, ws_sd_f(m, "ph" as *u8), ws_f(m, SD_QUARTER_TURN), T_F32), T_F32), ws_f(m, SD_RIPPLE_SLOPE), T_F32), ws_sd_f(m, "ram" as *u8), T_F32)))
713 // the wet band: the nearest water on the ring, at this cell's height and one below
714 ws_st(m, f, sir_var(m, "wd" as *u8, T_F32, ws_f(m, SD_WET_DRY)))
715 let kk: i64 = sir_let(m, "k" as *u8, T_I32, ws_bin(m, "+" as *u8, ws_bin(m, "/" as *u8, ws_id(m, "j" as *u8, T_I32), ws_i(m, SD_RING_DIRS), T_I32), ws_i(m, "1" as *u8), T_I32))
716 let dd: i64 = sir_let(m, "d" as *u8, T_I32, ws_bin(m, "-" as *u8, ws_id(m, "j" as *u8, T_I32), ws_bin(m, "*" as *u8, ws_bin(m, "/" as *u8, ws_id(m, "j" as *u8, T_I32), ws_i(m, SD_RING_DIRS), T_I32), ws_i(m, SD_RING_DIRS), T_I32), T_I32))
717 let aa: i64 = sir_let(m, "a" as *u8, T_F32, ws_bin(m, "*" as *u8, sir_cast(m, ws_id(m, "d" as *u8, T_I32), T_F32), ws_f(m, SD_EIGHTH_TURN), T_F32))
718 let dx: i64 = sir_let(m, "dx" as *u8, T_I32, ws_sd_dir(m, SD_QUARTER_TURN))
719 let dz: i64 = sir_let(m, "dz" as *u8, T_I32, ws_sd_dir(m, "0.0" as *u8))
720 let near: i64 = ws_if(m, ws_or(m, ws_sd_wat(m, "0" as *u8), ws_sd_wat(m, "-1" as *u8)), ws_set(m, ws_id(m, "wd" as *u8, T_F32), ws_c2(m, "min" as *u8, ws_id(m, "wd" as *u8, T_F32), sir_cast(m, ws_id(m, "k" as *u8, T_I32), T_F32), T_F32)), 0)
721 sir_for_until(m, f, sir_var(m, "j" as *u8, T_I32, ws_i(m, "0" as *u8)), ws_cmp(m, ">=" as *u8, ws_id(m, "j" as *u8, T_I32), ws_i(m, SD_RING_STEPS)), ws_op(m, "j" as *u8, T_I32, "+" as *u8, ws_i(m, "1" as *u8)), ws_q5(m, kk, dd, aa, ws_q2(m, dx, dz), near))
722 let sub: i64 = 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_i(m, "0" as *u8), ws_i(m, "1" as *u8), ws_i(m, "0" as *u8)), T_V3I), T_U32), ws_u(m, "4" as *u8))
723 ws_st(m, f, ws_if(m, sub, ws_set(m, ws_id(m, "wd" as *u8, T_F32), ws_f(m, "0.0" as *u8)), 0))
724 ws_st(m, f, sir_let(m, "wet" as *u8, T_F32, ws_c3(m, "clamp" as *u8, ws_bin(m, "/" as *u8, ws_bin(m, "-" as *u8, ws_f(m, SD_WET_DRY), ws_sd_f(m, "wd" as *u8), T_F32), ws_f(m, SD_WET_R), T_F32), ws_f(m, "0.0" as *u8), ws_f(m, "1.0" as *u8), T_F32)))
725 ws_st(m, f, sir_let(m, "dry" as *u8, T_F32, ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_sd_f(m, "wet" as *u8), T_F32)))
726 // the tilted normal: field slope + faded facets + the ripples the swash has not erased
727 ws_st(m, f, sir_let(m, "pn" as *u8, T_V3F, ws_c1(m, "normalize" as *u8, ws_v3(m, ws_sd_tilt(m, "sx" as *u8, "gx" as *u8, SD_RIPPLE_DX), ws_f(m, "1.0" as *u8), ws_sd_tilt(m, "sz" as *u8, "gz" as *u8, SD_RIPPLE_DZ)), T_V3F)))
728 // light: the gnd() Lambert on the tilted normal (level 1.0, lee floor 0.42), then wet darkening
729 ws_st(m, f, sir_let(m, "cp" as *u8, T_F32, ws_c2(m, "max" as *u8, ws_c2(m, "dot" as *u8, ws_sd_v3(m, "pn" as *u8), ws_sd_v3(m, "sund" as *u8), T_F32), ws_f(m, "0.0" as *u8), T_F32)))
730 ws_st(m, f, sir_let(m, "cf" as *u8, T_F32, ws_c2(m, "max" as *u8, ws_sx(m, "sund" as *u8, T_V3F, "y" as *u8, T_F32), ws_f(m, "0.001" as *u8), T_F32)))
731 let span: i64 = ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_f(m, "0.42" as *u8), T_F32)
732 ws_st(m, f, sir_let(m, "lp" as *u8, T_F32, ws_c2(m, "min" as *u8, ws_bin(m, "+" as *u8, ws_f(m, "0.42" as *u8), ws_bin(m, "*" as *u8, span, ws_bin(m, "/" as *u8, ws_sd_f(m, "cp" as *u8), ws_sd_f(m, "cf" as *u8), T_F32), T_F32), T_F32), ws_f(m, "1.0" as *u8), T_F32)))
733 ws_st(m, f, sir_let(m, "lw" as *u8, T_F32, ws_bin(m, "*" as *u8, ws_sd_f(m, "lp" as *u8), ws_c3(m, "mix" as *u8, ws_f(m, "1.0" as *u8), ws_f(m, SD_WET_DARK), ws_sd_f(m, "wet" as *u8), T_F32), T_F32)))
734 // specular: the film's Blinn lobe and Fresnel sky sheen inside the band, quartz glints on dry facets
735 ws_st(m, f, sir_let(m, "hv" as *u8, T_V3F, ws_c1(m, "normalize" as *u8, ws_bin(m, "-" as *u8, ws_sd_v3(m, "sund" as *u8), ws_sd_v3(m, "rd" as *u8), T_V3F), T_V3F)))
736 ws_st(m, f, sir_let(m, "fr" as *u8, T_F32, ws_c2(m, "pow" as *u8, ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_sd_f(m, "ndv" as *u8), T_F32), ws_f(m, "5.0" as *u8), T_F32)))
737 ws_st(m, f, sir_let(m, "film" as *u8, T_F32, ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, ws_sd_f(m, "wet" as *u8), ws_c2(m, "pow" as *u8, ws_c2(m, "max" as *u8, ws_c2(m, "dot" as *u8, ws_sd_v3(m, "pn" as *u8), ws_sd_v3(m, "hv" as *u8), T_F32), ws_f(m, "0.0" as *u8), T_F32), ws_f(m, SD_FILM_POW), T_F32), T_F32), ws_f(m, SD_FILM_GAIN), T_F32)))
738 ws_st(m, f, sir_let(m, "sheen" as *u8, T_F32, ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, ws_sd_f(m, "wet" as *u8), ws_sd_f(m, "fr" as *u8), T_F32), ws_f(m, SD_SHEEN_GAIN), T_F32)))
739 ws_st(m, f, sir_let(m, "gn" as *u8, T_V3F, ws_c1(m, "normalize" as *u8, ws_v3(m, ws_sd_f(m, "gx" as *u8), ws_f(m, "1.0" as *u8), ws_sd_f(m, "gz" as *u8)), T_V3F)))
740 ws_st(m, f, sir_var(m, "glint" as *u8, T_F32, ws_f(m, "0.0" as *u8)))
741 let gl: i64 = ws_set(m, ws_id(m, "glint" as *u8, T_F32), ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, ws_sd_f(m, "gam" as *u8), ws_c2(m, "pow" as *u8, ws_c2(m, "max" as *u8, ws_c2(m, "dot" as *u8, ws_sd_v3(m, "gn" as *u8), ws_sd_v3(m, "hv" as *u8), T_F32), ws_f(m, "0.0" as *u8), T_F32), ws_f(m, SD_GLINT_POW), T_F32), T_F32), ws_f(m, SD_GLINT_GAIN), T_F32))
742 ws_st(m, f, ws_if(m, ws_cmp(m, ">" as *u8, ws_sd_f(m, "g0" as *u8), ws_f(m, SD_GLINT_FRAC)), gl, 0))
743 // x = light, y = specular: the sun terms scaled by the sun flag, the sheen is the sky's and stays
744 let sunspec: i64 = ws_bin(m, "*" as *u8, ws_sd_f(m, "sun" as *u8), ws_bin(m, "+" as *u8, ws_sd_f(m, "film" as *u8), ws_sd_f(m, "glint" as *u8), T_F32), T_F32)
745 ws_st(m, f, ws_ret(m, ws_v2(m, ws_sd_f(m, "lw" as *u8), ws_bin(m, "+" as *u8, ws_sd_f(m, "sheen" as *u8), sunspec, T_F32))))
746 return f
747}
748func ws_fn_shade(m: *i64, hty: i64) -> i64 {
749 let f: i64 = sir_func(m, "shade" as *u8, T_V3F)
750 sir_param(m, f, "ro" as *u8, T_V3F)
751 sir_param(m, f, "rd" as *u8, T_V3F)
752 sir_param(m, f, "t" as *u8, T_F32)
753 sir_param(m, f, "c" as *u8, T_V3I)
754 sir_param(m, f, "fce" as *u8, T_I32)
755 sir_param(m, f, "b" as *u8, T_U32)
756 // let hp=ro+rd*t; var uv:vec2f; var oc:vec3i=c; var n:vec3f=vec3f(0.0);
757 ws_st(m, f, sir_let(m, "hp" as *u8, T_V3F, ws_bin(m, "+" as *u8, ws_id(m, "ro" as *u8, T_V3F), ws_bin(m, "*" as *u8, ws_id(m, "rd" as *u8, T_V3F), ws_id(m, "t" as *u8, T_F32), T_V3F), T_V3F)))
758 ws_st(m, f, sir_var(m, "uv" as *u8, T_V2F, 0))
759 ws_st(m, f, sir_var(m, "oc" as *u8, T_V3I, ws_id(m, "c" as *u8, T_V3I)))
760 ws_st(m, f, sir_var(m, "n" as *u8, T_V3F, ws_v1(m, T_V3F, ws_f(m, "0.0" as *u8))))
761 // the six faces
762 let f6: i64 = ws_face(m, "xy" as *u8, "z" as *u8, "-" as *u8, "0.0" as *u8, "0.0" as *u8, "-1.0" as *u8)
763 let f5: i64 = ws_if(m, ws_fce(m, "5" as *u8), ws_face(m, "xy" as *u8, "z" as *u8, "+" as *u8, "0.0" as *u8, "0.0" as *u8, "1.0" as *u8), f6)
764 let f4: i64 = ws_if(m, ws_fce(m, "4" as *u8), ws_face(m, "xz" as *u8, "y" as *u8, "-" as *u8, "0.0" as *u8, "-1.0" as *u8, "0.0" as *u8), f5)
765 let f3: i64 = ws_if(m, ws_fce(m, "3" as *u8), ws_face(m, "xz" as *u8, "y" as *u8, "+" as *u8, "0.0" as *u8, "1.0" as *u8, "0.0" as *u8), f4)
766 let f2: i64 = ws_if(m, ws_fce(m, "2" as *u8), ws_face(m, "zy" as *u8, "x" as *u8, "-" as *u8, "-1.0" as *u8, "0.0" as *u8, "0.0" as *u8), f3)
767 ws_st(m, f, ws_if(m, ws_fce(m, "1" as *u8), ws_face(m, "zy" as *u8, "x" as *u8, "+" as *u8, "1.0" as *u8, "0.0" as *u8, "0.0" as *u8), f2))
768 // let f=fract(uv); var bb:u32=b; if(b==1u&&fce!=3&&fce!=4){bb=2u;if(f.y>0.8){bb=1u;}}
769 ws_st(m, f, sir_let(m, "f" as *u8, T_V2F, ws_c1(m, "fract" as *u8, ws_id(m, "uv" as *u8, T_V2F), T_V2F)))
770 ws_st(m, f, sir_var(m, "bb" as *u8, T_U32, ws_id(m, "b" as *u8, T_U32)))
771 let grass: i64 = ws_q2(m, ws_set(m, ws_id(m, "bb" as *u8, T_U32), ws_u(m, "2" as *u8)), ws_if(m, ws_cmp(m, ">" as *u8, ws_sx(m, "f" as *u8, T_V2F, "y" as *u8, T_F32), ws_f(m, "0.8" as *u8)), ws_set(m, ws_id(m, "bb" as *u8, T_U32), ws_u(m, "1" as *u8)), 0))
772 ws_st(m, f, ws_if(m, ws_and(m, ws_and(m, ws_beq(m, "1" as *u8), ws_cmp(m, "!=" as *u8, ws_id(m, "fce" as *u8, T_I32), ws_i(m, "3" as *u8))), ws_cmp(m, "!=" as *u8, ws_id(m, "fce" as *u8, T_I32), ws_i(m, "4" as *u8))), grass, 0))
773 // var li:f32; the six-way face light
774 ws_st(m, f, sir_var(m, "li" as *u8, T_F32, 0))
775 let l6: i64 = ws_set(m, ws_id(m, "li" as *u8, T_F32), ws_f(m, "0.56" as *u8))
776 let l5: i64 = ws_if(m, ws_fce(m, "5" as *u8), ws_set(m, ws_id(m, "li" as *u8, T_F32), ws_f(m, "0.62" as *u8)), l6)
777 let l2: i64 = ws_if(m, ws_fce(m, "2" as *u8), ws_set(m, ws_id(m, "li" as *u8, T_F32), ws_f(m, "0.7" as *u8)), l5)
778 let l1: i64 = ws_if(m, ws_fce(m, "1" as *u8), ws_set(m, ws_id(m, "li" as *u8, T_F32), ws_f(m, "0.76" as *u8)), l2)
779 let l4: i64 = ws_if(m, ws_fce(m, "4" as *u8), ws_set(m, ws_id(m, "li" as *u8, T_F32), ws_f(m, "0.42" as *u8)), l1)
780 ws_st(m, f, ws_if(m, ws_fce(m, "3" as *u8), ws_set(m, ws_id(m, "li" as *u8, T_F32), ws_f(m, "1.0" as *u8)), l4))
781 // GE53: on the field the ground's own gradient lights the top face (level = the same 1.0, lee = the same 0.42 floor)
782 // GR27: on the field the sand classes are a MATERIAL -- sand() lights the tilted normal and returns the film specular
783 // in sp; every other class on the field keeps the bare gradient light
784 ws_st(m, f, sir_var(m, "sp" as *u8, T_F32, ws_f(m, "0.0" as *u8)))
785 let sm: i64 = ws_q3(m, sir_let(m, "sm" as *u8, T_V2F, ws_c4(m, "sand" as *u8, ws_id(m, "hp" as *u8, T_V3F), ws_id(m, "c" as *u8, T_V3I), ws_id(m, "rd" as *u8, T_V3F), ws_id(m, "t" as *u8, T_F32), T_V2F)), ws_set(m, ws_id(m, "li" as *u8, T_F32), ws_sx(m, "sm" as *u8, T_V2F, "x" as *u8, T_F32)), ws_set(m, ws_id(m, "sp" as *u8, T_F32), ws_sx(m, "sm" as *u8, T_V2F, "y" as *u8, T_F32)))
786 ws_st(m, f, ws_if(m, ws_smooth(m), ws_if(m, ws_sandcls(m), sm, ws_set(m, ws_id(m, "li" as *u8, T_F32), ws_c1(m, "gnd" as *u8, ws_sx(m, "hp" as *u8, T_V3F, "xz" as *u8, T_V2F), T_F32))), 0))
787 // if(u.sun>0.5){if(fce==1){li*=1.12;}if(fce==2){li*=0.92;}if(fce==5){li*=1.04;}}
788 ws_st(m, f, ws_if(m, ws_cmp(m, ">" as *u8, ws_id(m, "sun" as *u8, T_F32), ws_f(m, "0.5" as *u8)), ws_q3(m, ws_if(m, ws_fce(m, "1" as *u8), ws_li(m, "1.12" as *u8), 0), ws_if(m, ws_fce(m, "2" as *u8), ws_li(m, "0.92" as *u8), 0), ws_if(m, ws_fce(m, "5" as *u8), ws_li(m, "1.04" as *u8), 0)), 0))
789 // let sd3=floor(hp)*0.13; let bs=f32(b)*7.0;
790 ws_st(m, f, sir_let(m, "sd3" as *u8, T_V3F, ws_bin(m, "*" as *u8, ws_c1(m, "floor" as *u8, ws_id(m, "hp" as *u8, T_V3F), T_V3F), ws_f(m, "0.13" as *u8), T_V3F)))
791 ws_st(m, f, sir_let(m, "bs" as *u8, T_F32, ws_bin(m, "*" as *u8, sir_cast(m, ws_id(m, "b" as *u8, T_U32), T_F32), ws_f(m, "7.0" as *u8), T_F32)))
792 // t00 / t10 / t01 = h31(vec3f(floor(f*24.0 [+ offset]),bs)+sd3)
793 let f24a: i64 = ws_bin(m, "*" as *u8, ws_id(m, "f" as *u8, T_V2F), ws_f(m, "24.0" as *u8), T_V2F)
794 ws_st(m, f, sir_let(m, "t00" as *u8, T_F32, ws_c1(m, "h31" as *u8, ws_bin(m, "+" as *u8, ws_vt2(m, T_V3F, ws_c1(m, "floor" as *u8, f24a, T_V2F), ws_id(m, "bs" as *u8, T_F32)), ws_id(m, "sd3" as *u8, T_V3F), T_V3F), T_F32)))
795 let f24b: i64 = ws_bin(m, "+" as *u8, ws_bin(m, "*" as *u8, ws_id(m, "f" as *u8, T_V2F), ws_f(m, "24.0" as *u8), T_V2F), ws_v2f(m, "1.0" as *u8, "0.0" as *u8), T_V2F)
796 ws_st(m, f, sir_let(m, "t10" as *u8, T_F32, ws_c1(m, "h31" as *u8, ws_bin(m, "+" as *u8, ws_vt2(m, T_V3F, ws_c1(m, "floor" as *u8, f24b, T_V2F), ws_id(m, "bs" as *u8, T_F32)), ws_id(m, "sd3" as *u8, T_V3F), T_V3F), T_F32)))
797 let f24c: i64 = ws_bin(m, "+" as *u8, ws_bin(m, "*" as *u8, ws_id(m, "f" as *u8, T_V2F), ws_f(m, "24.0" as *u8), T_V2F), ws_v2f(m, "0.0" as *u8, "1.0" as *u8), T_V2F)
798 ws_st(m, f, sir_let(m, "t01" as *u8, T_F32, ws_c1(m, "h31" as *u8, ws_bin(m, "+" as *u8, ws_vt2(m, T_V3F, ws_c1(m, "floor" as *u8, f24c, T_V2F), ws_id(m, "bs" as *u8, T_F32)), ws_id(m, "sd3" as *u8, T_V3F), T_V3F), T_F32)))
799 // let bmp=(t10-t00)*0.6+(t01-t00)*0.45;
800 ws_st(m, f, sir_let(m, "bmp" as *u8, T_F32, ws_bin(m, "+" as *u8, ws_bin(m, "*" as *u8, ws_bin(m, "-" as *u8, ws_id(m, "t10" as *u8, T_F32), ws_id(m, "t00" as *u8, T_F32), T_F32), ws_f(m, "0.6" as *u8), T_F32), ws_bin(m, "*" as *u8, ws_bin(m, "-" as *u8, ws_id(m, "t01" as *u8, T_F32), ws_id(m, "t00" as *u8, T_F32), T_F32), ws_f(m, "0.45" as *u8), T_F32), T_F32)))
801 // var bamp:f32; the block-class relief amplitude
802 ws_st(m, f, sir_var(m, "bamp" as *u8, T_F32, 0))
803 let a4: i64 = ws_if(m, ws_beq(m, "4" as *u8), ws_set(m, ws_id(m, "bamp" as *u8, T_F32), ws_f(m, "0.25" as *u8)), ws_set(m, ws_id(m, "bamp" as *u8, T_F32), ws_f(m, "0.7" as *u8)))
804 let a7: i64 = ws_if(m, ws_beq(m, "7" as *u8), ws_set(m, ws_id(m, "bamp" as *u8, T_F32), ws_f(m, "1.3" as *u8)), a4)
805 let rough: i64 = ws_or(m, ws_or(m, ws_or(m, ws_or(m, ws_beq(m, "3" as *u8), ws_beq(m, "2" as *u8)), ws_beq(m, "9" as *u8)), ws_beq(m, "10" as *u8)), ws_beq(m, "11" as *u8))
806 ws_st(m, f, ws_if(m, rough, ws_set(m, ws_id(m, "bamp" as *u8, T_F32), ws_f(m, "1.0" as *u8)), a7))
807 ws_st(m, f, ws_if(m, ws_or(m, ws_sandy(m), ws_cont_water(m)), ws_set(m, ws_id(m, "bamp" as *u8, T_F32), ws_f(m, "0.0" as *u8)), 0)) // GR27: the per-cell hash relief IS the paint the material replaces
808 // let dfade=clamp(1.0-t/24.0,0.0,1.0); li*=clamp(1.0+bmp*bamp*dfade,0.55,1.45); li*=0.9+t00*0.2*dfade;
809 ws_st(m, f, sir_let(m, "dfade" as *u8, T_F32, ws_c3(m, "clamp" as *u8, ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_bin(m, "/" as *u8, ws_id(m, "t" as *u8, T_F32), ws_f(m, "24.0" as *u8), T_F32), T_F32), ws_f(m, "0.0" as *u8), ws_f(m, "1.0" as *u8), T_F32)))
810 ws_st(m, f, ws_op(m, "li" as *u8, T_F32, "*" as *u8, 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_id(m, "bmp" as *u8, T_F32), ws_id(m, "bamp" as *u8, T_F32), T_F32), ws_id(m, "dfade" as *u8, T_F32), T_F32), T_F32), ws_f(m, "0.55" as *u8), ws_f(m, "1.45" as *u8), T_F32)))
811 // The sand material owns its detail response; legacy voxel paint belongs to other surfaces.
812 ws_st(m, f, ws_if(m, sir_not(m, ws_or(m, ws_sandy(m), ws_cont_water(m))), ws_op(m, "li" as *u8, T_F32, "*" as *u8, ws_bin(m, "+" as *u8, ws_f(m, "0.9" as *u8), ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, ws_id(m, "t00" as *u8, T_F32), ws_f(m, "0.2" as *u8), T_F32), ws_id(m, "dfade" as *u8, T_F32), T_F32), T_F32)), 0))
813 // if(bb==1u&&fce==3&&t<24.0){let tf=h21(floor(f*38.0)+floor(hp.xz)*3.7);if(tf>0.82){li*=1.28;}else if(tf<0.14){li*=0.78;}}
814 let tf: i64 = sir_let(m, "tf" as *u8, T_F32, ws_c1(m, "h21" as *u8, ws_bin(m, "+" as *u8, ws_c1(m, "floor" as *u8, ws_bin(m, "*" as *u8, ws_id(m, "f" as *u8, T_V2F), ws_f(m, "38.0" as *u8), T_V2F), T_V2F), ws_bin(m, "*" as *u8, ws_c1(m, "floor" as *u8, ws_sx(m, "hp" as *u8, T_V3F, "xz" as *u8, T_V2F), T_V2F), ws_f(m, "3.7" as *u8), T_V2F), T_V2F), T_F32))
815 let tfi: i64 = ws_if(m, ws_cmp(m, ">" as *u8, ws_id(m, "tf" as *u8, T_F32), ws_f(m, "0.82" as *u8)), ws_li(m, "1.28" as *u8), ws_if(m, ws_cmp(m, "<" as *u8, ws_id(m, "tf" as *u8, T_F32), ws_f(m, "0.14" as *u8)), ws_li(m, "0.78" as *u8), 0))
816 ws_st(m, f, ws_if(m, ws_and(m, sir_not(m, ws_sandy(m)), ws_and(m, ws_and(m, ws_cmp(m, "==" as *u8, ws_id(m, "bb" as *u8, T_U32), ws_u(m, "1" as *u8)), ws_fce(m, "3" as *u8)), ws_cmp(m, "<" as *u8, ws_id(m, "t" as *u8, T_F32), ws_f(m, "24.0" as *u8)))), ws_q2(m, tf, tfi), 0))
817 // if(f.x<0.055||f.x>0.945||f.y<0.055||f.y>0.945){li*=0.82;}
818 let edge: i64 = ws_or(m, ws_or(m, ws_or(m, ws_cmp(m, "<" as *u8, ws_sx(m, "f" as *u8, T_V2F, "x" as *u8, T_F32), ws_f(m, "0.055" as *u8)), ws_cmp(m, ">" as *u8, ws_sx(m, "f" as *u8, T_V2F, "x" as *u8, T_F32), ws_f(m, "0.945" as *u8))), ws_cmp(m, "<" as *u8, ws_sx(m, "f" as *u8, T_V2F, "y" as *u8, T_F32), ws_f(m, "0.055" as *u8))), ws_cmp(m, ">" as *u8, ws_sx(m, "f" as *u8, T_V2F, "y" as *u8, T_F32), ws_f(m, "0.945" as *u8)))
819 ws_st(m, f, ws_if(m, ws_and(m, edge, sir_not(m, ws_cont_surface(m))), ws_li(m, "0.82" as *u8), 0)) // GE53: no cell-edge grid on the field
820 // var ao:f32=0.0; the four edge-AO probes
821 ws_st(m, f, sir_var(m, "ao" as *u8, T_F32, ws_f(m, "0.0" as *u8)))
822 let n1: i64 = ws_if(m, ws_topbot(m), ws_nb(m, "x" as *u8, "-" as *u8), ws_if(m, ws_cmp(m, "<" as *u8, ws_id(m, "fce" as *u8, T_I32), ws_i(m, "3" as *u8)), ws_nb(m, "z" as *u8, "-" as *u8), ws_nb(m, "x" as *u8, "-" as *u8)))
823 ws_st(m, f, ws_ao(m, "x" as *u8, "<" as *u8, "0.17" as *u8, n1, ws_bin(m, "-" as *u8, ws_f(m, "0.17" as *u8), ws_sx(m, "f" as *u8, T_V2F, "x" as *u8, T_F32), T_F32)))
824 let n2: i64 = ws_if(m, ws_topbot(m), ws_nb(m, "x" as *u8, "+" as *u8), ws_if(m, ws_cmp(m, "<" as *u8, ws_id(m, "fce" as *u8, T_I32), ws_i(m, "3" as *u8)), ws_nb(m, "z" as *u8, "+" as *u8), ws_nb(m, "x" as *u8, "+" as *u8)))
825 ws_st(m, f, ws_ao(m, "x" as *u8, ">" as *u8, "0.83" as *u8, n2, ws_bin(m, "-" as *u8, ws_sx(m, "f" as *u8, T_V2F, "x" as *u8, T_F32), ws_f(m, "0.83" as *u8), T_F32)))
826 let n3: i64 = ws_if(m, ws_topbot(m), ws_nb(m, "z" as *u8, "-" as *u8), ws_nb(m, "y" as *u8, "-" as *u8))
827 ws_st(m, f, ws_ao(m, "y" as *u8, "<" as *u8, "0.17" as *u8, n3, ws_bin(m, "-" as *u8, ws_f(m, "0.17" as *u8), ws_sx(m, "f" as *u8, T_V2F, "y" as *u8, T_F32), T_F32)))
828 let n4: i64 = ws_if(m, ws_topbot(m), ws_nb(m, "z" as *u8, "+" as *u8), ws_nb(m, "y" as *u8, "+" as *u8))
829 ws_st(m, f, ws_ao(m, "y" as *u8, ">" as *u8, "0.83" as *u8, n4, ws_bin(m, "-" as *u8, ws_sx(m, "f" as *u8, T_V2F, "y" as *u8, T_F32), ws_f(m, "0.83" as *u8), T_F32)))
830 // li*=1.0-min(ao,0.45);
831 ws_st(m, f, ws_if(m, sir_not(m, ws_cont_surface(m)), ws_op(m, "li" as *u8, T_F32, "*" as *u8, ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_c2(m, "min" as *u8, ws_id(m, "ao" as *u8, T_F32), ws_f(m, "0.45" as *u8), T_F32), T_F32)), 0)) // GE53: no cell-corner AO on the field
832 // if(u.sun>0.5){let sh=march(hp+n*0.02,u.sund,1,60);if(sh.t>0.0){li*=0.55;}}
833 let sh: i64 = sir_let(m, "sh" as *u8, hty, ws_c5(m, "march" as *u8, ws_bin(m, "+" as *u8, ws_id(m, "hp" as *u8, T_V3F), ws_bin(m, "*" as *u8, ws_id(m, "n" as *u8, T_V3F), ws_f(m, "0.02" as *u8), T_V3F), T_V3F), ws_id(m, "sund" as *u8, T_V3F), ws_i(m, "1" as *u8), ws_i(m, "60" as *u8), sir_ident(m, "r_surf" as *u8, T_I32), hty))
834 // GE53: on the field a cell march cannot shadow the ground (terrain cells are air to it), so the surface march does
835 let shs: i64 = ws_if(m, ws_and(m, ws_and(m, ws_cmp(m, "==" as *u8, sir_ident(m, "r_surf" as *u8, T_I32), ws_i(m, "1" as *u8)), ws_cmp(m, "<=" as *u8, ws_mem(m, ws_id(m, "sh" as *u8, hty), "t" as *u8, T_F32), ws_f(m, "0.0" as *u8))), ws_cmp(m, ">" as *u8, ws_c3(m, "smarch" as *u8, ws_bin(m, "+" as *u8, ws_id(m, "hp" as *u8, T_V3F), ws_bin(m, "*" as *u8, ws_id(m, "n" as *u8, T_V3F), ws_f(m, "0.02" as *u8), T_V3F), T_V3F), ws_id(m, "sund" as *u8, T_V3F), ws_i(m, "60" as *u8), T_F32), ws_f(m, "0.0" as *u8))), ws_shd(m), 0)
836 ws_st(m, f, ws_if(m, ws_cmp(m, ">" as *u8, ws_id(m, "sun" as *u8, T_F32), ws_f(m, "0.5" as *u8)), ws_q3(m, sh, ws_if(m, ws_cmp(m, ">" as *u8, ws_mem(m, ws_id(m, "sh" as *u8, hty), "t" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_shd(m), 0), shs), 0))
837 // let col=pal9(bb)*li; let fw9=vec3f(1.0)-exp(-vec3f(0.123,0.287,0.700)*t/168.0); return mix(col,sky(rd),fw9);
838 ws_st(m, f, sir_let(m, "col" as *u8, T_V3F, ws_bin(m, "+" as *u8, ws_bin(m, "*" as *u8, ws_c1(m, "pal9" as *u8, ws_id(m, "bb" as *u8, T_U32), T_V3F), ws_id(m, "li" as *u8, T_F32), T_V3F), ws_v1(m, T_V3F, ws_id(m, "sp" as *u8, T_F32)), T_V3F))) // GR27: + the film specular
839 let tau: i64 = ws_bin(m, "/" as *u8, ws_bin(m, "*" as *u8, sir_neg(m, ws_v3f(m, "0.123" as *u8, "0.287" as *u8, "0.700" as *u8), T_V3F), ws_id(m, "t" as *u8, T_F32), T_V3F), ws_f(m, "168.0" as *u8), T_V3F)
840 ws_st(m, f, sir_let(m, "fw9" as *u8, T_V3F, ws_bin(m, "-" as *u8, ws_v1(m, T_V3F, ws_f(m, "1.0" as *u8)), ws_c1(m, "exp" as *u8, tau, T_V3F), T_V3F)))
841 ws_st(m, f, ws_ret(m, ws_c3(m, "mix" as *u8, ws_id(m, "col" as *u8, T_V3F), ws_c1(m, "sky" as *u8, ws_id(m, "rd" as *u8, T_V3F), T_V3F), ws_id(m, "fw9" as *u8, T_V3F), T_V3F)))
842 return f
843}
844
845// the hotbar slot's block id: if(s2==0){bt=3;}else if(s2==1){bt=2;}...else{bt=13;}
846func ws_bt(m: *i64, k: *u8, v: *u8, els: i64) -> i64 {
847 return ws_if(m, ws_cmp(m, "==" as *u8, ws_id(m, "s2" as *u8, T_I32), ws_i(m, k)), ws_set(m, ws_id(m, "bt" as *u8, T_I32), ws_i(m, v)), els)
848}
849// px.<a> <op> (o.<a> + <e>) / px.<a> <op> (o.<a> + hbS - <e>)
850func 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)) }
851
852// the fragment entry: fs -- the world pass per pixel, the hand text statement for statement (yflip carries the
853// WebGPU top-left origin as a uniform so ONE source serves both doors)
854// One hit policy for visible geometry and geometry seen through water.
855// Continuous still-water intersection. Level is simulation data; no water voxel supplies geometry.
856func ws_fn_water_hit(m: *i64, hty: i64) -> i64 {
857 let f: i64 = sir_func(m, "water_hit" as *u8, hty)
858 sir_param(m, f, "ro" as *u8, T_V3F); sir_param(m, f, "rd" as *u8, T_V3F)
859 sir_param(m, f, "prior" as *u8, hty); sir_param(m, f, "mx" as *u8, T_I32)
860 ws_st(m, f, ws_if(m, ws_cmp(m, "==" as *u8, ws_sx(m, "rd" as *u8, T_V3F, "y" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_ret(m, ws_id(m, "prior" as *u8, hty)), 0))
861 ws_st(m, f, sir_let(m, "level" as *u8, T_F32, ws_bin(m, "/" as *u8, sir_cast(m, ws_id(m, "r_water_q8" as *u8, T_I32), T_F32), ws_f(m, "256.0" as *u8), T_F32)))
862 ws_st(m, f, sir_let(m, "wt" as *u8, T_F32, ws_bin(m, "/" as *u8, ws_bin(m, "-" as *u8, ws_id(m, "level" as *u8, T_F32), ws_sx(m, "ro" as *u8, T_V3F, "y" as *u8, T_F32), T_F32), ws_sx(m, "rd" as *u8, T_V3F, "y" as *u8, T_F32), T_F32)))
863 let outside: i64 = ws_or(m, ws_cmp(m, "<" as *u8, ws_id(m, "wt" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_cmp(m, ">" as *u8, ws_id(m, "wt" as *u8, T_F32), sir_cast(m, ws_id(m, "mx" as *u8, T_I32), T_F32)))
864 ws_st(m, f, ws_if(m, outside, ws_ret(m, ws_id(m, "prior" as *u8, hty)), 0))
865 let occluded: i64 = ws_and(m, ws_cmp(m, ">=" as *u8, ws_mem(m, ws_id(m, "prior" as *u8, hty), "t" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_cmp(m, ">=" as *u8, ws_id(m, "wt" as *u8, T_F32), ws_mem(m, ws_id(m, "prior" as *u8, hty), "t" as *u8, T_F32)))
866 ws_st(m, f, ws_if(m, occluded, ws_ret(m, ws_id(m, "prior" as *u8, hty)), 0))
867 ws_st(m, f, sir_let(m, "wp" as *u8, T_V3F, ws_bin(m, "+" as *u8, ws_id(m, "ro" as *u8, T_V3F), ws_bin(m, "*" as *u8, ws_id(m, "rd" as *u8, T_V3F), ws_id(m, "wt" as *u8, T_F32), T_V3F), T_V3F)))
868 ws_st(m, f, sir_let(m, "bed" as *u8, T_F32, ws_c1(m, "surf" as *u8, ws_sx(m, "wp" as *u8, T_V3F, "xz" as *u8, T_V2F), T_F32)))
869 let dry: i64 = ws_or(m, ws_cmp(m, "<" as *u8, ws_id(m, "bed" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_cmp(m, ">=" as *u8, ws_id(m, "bed" as *u8, T_F32), ws_id(m, "level" as *u8, T_F32)))
870 ws_st(m, f, ws_if(m, dry, ws_ret(m, ws_id(m, "prior" as *u8, hty)), 0))
871 ws_st(m, f, sir_var(m, "result" as *u8, hty, ws_id(m, "prior" as *u8, hty)))
872 ws_st(m, f, ws_set(m, ws_mem(m, ws_id(m, "result" as *u8, hty), "t" as *u8, T_F32), ws_id(m, "wt" as *u8, T_F32)))
873 ws_st(m, f, ws_set(m, ws_mem(m, ws_id(m, "result" as *u8, hty), "b" as *u8, T_U32), ws_u(m, "4" as *u8)))
874 ws_st(m, f, ws_set(m, ws_mem(m, ws_id(m, "result" as *u8, hty), "c" as *u8, T_V3I), ws_v1(m, T_V3I, ws_c1(m, "floor" as *u8, ws_id(m, "wp" as *u8, T_V3F), T_V3F))))
875 ws_st(m, f, ws_set(m, ws_mem(m, ws_id(m, "result" as *u8, hty), "fce" as *u8, T_I32), ws_i(m, "3" as *u8)))
876 ws_st(m, f, ws_if(m, ws_cmp(m, ">" as *u8, ws_sx(m, "rd" as *u8, T_V3F, "y" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_set(m, ws_mem(m, ws_id(m, "result" as *u8, hty), "fce" as *u8, T_I32), ws_i(m, "4" as *u8)), 0))
877 ws_st(m, f, ws_ret(m, ws_id(m, "result" as *u8, hty)))
878 return f
879}
880
881func ws_fn_scene_hit(m: *i64, hty: i64) -> i64 {
882 ws_fn_water_hit(m, hty)
883 let f: i64 = sir_func(m, "scene_hit" as *u8, hty)
884 sir_param(m, f, "ro" as *u8, T_V3F)
885 sir_param(m, f, "rd" as *u8, T_V3F)
886 sir_param(m, f, "skipw" as *u8, T_I32)
887 sir_param(m, f, "mx" as *u8, T_I32)
888 sir_param(m, f, "ts" as *u8, T_F32)
889 ws_st(m, f, sir_var(m, "h" as *u8, hty, ws_c5(m, "march" as *u8, ws_id(m, "ro" as *u8, T_V3F), ws_id(m, "rd" as *u8, T_V3F), ws_c2(m, "max" as *u8, ws_id(m, "skipw" as *u8, T_I32), ws_id(m, "r_surf" as *u8, T_I32), T_I32), ws_id(m, "mx" as *u8, T_I32), sir_ident(m, "r_surf" as *u8, T_I32), hty)))
890 // Both camera and transmitted-water rays resolve the same continuous ground.
891 let hp9: i64 = sir_let(m, "hp9" as *u8, T_V3F, ws_bin(m, "+" as *u8, ws_id(m, "ro" as *u8, T_V3F), ws_bin(m, "*" as *u8, ws_id(m, "rd" as *u8, T_V3F), ws_id(m, "ts" as *u8, T_F32), T_V3F), T_V3F))
892 let cx9: i64 = sir_let(m, "cx9" as *u8, T_I32, sir_cast(m, ws_c1(m, "floor" as *u8, ws_sx(m, "hp9" as *u8, T_V3F, "x" as *u8, T_F32), T_F32), T_I32))
893 let cz9: i64 = sir_let(m, "cz9" as *u8, T_I32, sir_cast(m, ws_c1(m, "floor" as *u8, ws_sx(m, "hp9" as *u8, T_V3F, "z" as *u8, T_F32), T_F32), T_I32))
894 let cy9: i64 = sir_var(m, "cy9" as *u8, T_I32, ws_c2(m, "min" as *u8, sir_cast(m, ws_c1(m, "floor" as *u8, ws_sx(m, "hp9" as *u8, T_V3F, "y" as *u8, T_F32), T_F32), T_I32), ws_i(m, "47" as *u8), T_I32))
895 // Search the actual column extent: water and air cannot supply the seabed material.
896 let ground_class: i64 = ws_c1(m, "terrain" as *u8, ws_c1(m, "vx" as *u8, ws_vt3(m, T_V3I, ws_id(m, "cx9" as *u8, T_I32), ws_id(m, "cy9" as *u8, T_I32), ws_id(m, "cz9" as *u8, T_I32)), T_U32), T_I32)
897 let stop_scan: i64 = ws_or(m, ws_cmp(m, "<=" as *u8, ws_id(m, "cy9" as *u8, T_I32), ws_i(m, "0" as *u8)), ws_cmp(m, "==" as *u8, ground_class, ws_i(m, "1" as *u8)))
898 let scan: i64 = sir_loop(m, ws_q2(m, ws_if(m, stop_scan, sir_break(m), 0), ws_op(m, "cy9" as *u8, T_I32, "-" as *u8, ws_i(m, "1" as *u8))))
899 let sett: i64 = ws_set(m, ws_mem(m, ws_id(m, "h" as *u8, hty), "t" as *u8, T_F32), ws_id(m, "ts" as *u8, T_F32))
900 let setf: i64 = ws_set(m, ws_mem(m, ws_id(m, "h" as *u8, hty), "fce" as *u8, T_I32), ws_i(m, "3" as *u8))
901 let setc: i64 = ws_set(m, ws_mem(m, ws_id(m, "h" as *u8, hty), "c" as *u8, T_V3I), ws_vt3(m, T_V3I, ws_id(m, "cx9" as *u8, T_I32), ws_id(m, "cy9" as *u8, T_I32), ws_id(m, "cz9" as *u8, T_I32)))
902 let setb: i64 = ws_set(m, ws_mem(m, ws_id(m, "h" as *u8, hty), "b" as *u8, T_U32), ws_c1(m, "vx" as *u8, ws_mem(m, ws_id(m, "h" as *u8, hty), "c" as *u8, T_V3I), T_U32))
903 let nearer: i64 = ws_and(m, ws_cmp(m, ">" as *u8, ws_id(m, "ts" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_or(m, ws_cmp(m, "<" as *u8, ws_mem(m, ws_id(m, "h" as *u8, hty), "t" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_cmp(m, "<" as *u8, ws_id(m, "ts" as *u8, T_F32), ws_mem(m, ws_id(m, "h" as *u8, hty), "t" as *u8, T_F32))))
904 let inner: i64 = ws_if(m, nearer, ws_q5(m, hp9, ws_q4(m, cx9, cz9, cy9, scan), sett, setf, ws_q2(m, setc, setb)), 0)
905 ws_st(m, f, ws_if(m, ws_cmp(m, "==" as *u8, sir_ident(m, "r_surf" as *u8, T_I32), ws_i(m, "1" as *u8)), inner, 0))
906 // Resolve water against the same field after ground/objects, preserving nearest-hit ordering.
907 let water_call: i64 = ws_c4(m, "water_hit" as *u8, ws_id(m, "ro" as *u8, T_V3F), ws_id(m, "rd" as *u8, T_V3F), ws_id(m, "h" as *u8, hty), ws_id(m, "mx" as *u8, T_I32), hty)
908 ws_st(m, f, ws_if(m, ws_and(m, ws_cmp(m, "==" as *u8, ws_id(m, "r_surf" as *u8, T_I32), ws_i(m, "1" as *u8)), ws_cmp(m, "==" as *u8, ws_id(m, "skipw" as *u8, T_I32), ws_i(m, "0" as *u8))), ws_set(m, ws_id(m, "h" as *u8, hty), water_call), 0))
909 ws_st(m, f, ws_ret(m, ws_id(m, "h" as *u8, hty)))
910 return f
911}
912
913func ws_fn_fs(m: *i64, hty: i64) -> i64 {
914 sir_fragout(m, "fc" as *u8, T_V4F, 0)
915 let f: i64 = sir_func(m, "main" as *u8, T_VOID)
916 sir_param_position(m, f, "pos" as *u8)
917 // upk(); -- GE55: derive every float from the raw words FIRST; every statement below reads the private state
918 ws_st(m, f, sir_expr(m, sir_call(m, "upk" as *u8, T_VOID)))
919 // let px=vec2f(pos.x,mix(pos.y,u.res.y-pos.y,u.yflip));
920 let flipped: i64 = ws_bin(m, "-" as *u8, ws_sx(m, "res" as *u8, T_V2F, "y" as *u8, T_F32), ws_sx(m, "pos" as *u8, T_V4F, "y" as *u8, T_F32), T_F32)
921 ws_st(m, f, sir_let(m, "px" as *u8, T_V2F, ws_v2(m, ws_sx(m, "pos" as *u8, T_V4F, "x" as *u8, T_F32), ws_c3(m, "mix" as *u8, ws_sx(m, "pos" as *u8, T_V4F, "y" as *u8, T_F32), flipped, ws_id(m, "yflip" as *u8, T_F32), T_F32))))
922 // let sc=(px-u.res*0.5)/(u.res.x*0.5);
923 ws_st(m, f, sir_let(m, "sc" as *u8, T_V2F, ws_bin(m, "/" as *u8, ws_bin(m, "-" as *u8, ws_id(m, "px" as *u8, T_V2F), ws_bin(m, "*" as *u8, ws_id(m, "res" as *u8, T_V2F), ws_f(m, "0.5" as *u8), T_V2F), T_V2F), ws_bin(m, "*" as *u8, ws_sx(m, "res" as *u8, T_V2F, "x" as *u8, T_F32), ws_f(m, "0.5" as *u8), T_F32), T_V2F)))
924 // let fw=vec3f(u.yp.x*u.yp.w,u.yp.z,u.yp.y*u.yp.w); let rt=vec3f(u.yp.y,0.0,-u.yp.x); let up=vec3f(-u.yp.x*u.yp.z,u.yp.w,-u.yp.y*u.yp.z);
925 ws_st(m, f, sir_let(m, "fw" as *u8, T_V3F, ws_v3(m, ws_bin(m, "*" as *u8, ws_sx(m, "yp" as *u8, T_V4F, "x" as *u8, T_F32), ws_sx(m, "yp" as *u8, T_V4F, "w" as *u8, T_F32), T_F32), ws_sx(m, "yp" as *u8, T_V4F, "z" as *u8, T_F32), ws_bin(m, "*" as *u8, ws_sx(m, "yp" as *u8, T_V4F, "y" as *u8, T_F32), ws_sx(m, "yp" as *u8, T_V4F, "w" as *u8, T_F32), T_F32))))
926 ws_st(m, f, sir_let(m, "rt" as *u8, T_V3F, ws_v3(m, ws_sx(m, "yp" as *u8, T_V4F, "y" as *u8, T_F32), ws_f(m, "0.0" as *u8), sir_neg(m, ws_sx(m, "yp" as *u8, T_V4F, "x" as *u8, T_F32), T_F32))))
927 ws_st(m, f, sir_let(m, "up" as *u8, T_V3F, ws_v3(m, ws_bin(m, "*" as *u8, sir_neg(m, ws_sx(m, "yp" as *u8, T_V4F, "x" as *u8, T_F32), T_F32), ws_sx(m, "yp" as *u8, T_V4F, "z" as *u8, T_F32), T_F32), ws_sx(m, "yp" as *u8, T_V4F, "w" as *u8, T_F32), ws_bin(m, "*" as *u8, sir_neg(m, ws_sx(m, "yp" as *u8, T_V4F, "y" as *u8, T_F32), T_F32), ws_sx(m, "yp" as *u8, T_V4F, "z" as *u8, T_F32), T_F32))))
928 // let rd=normalize(fw+rt*sc.x+up*sc.y); let ro=u.cam; let h=march(ro,rd,0,200);
929 ws_st(m, f, sir_let(m, "rd" as *u8, T_V3F, ws_c1(m, "normalize" as *u8, ws_bin(m, "+" as *u8, ws_bin(m, "+" as *u8, ws_id(m, "fw" as *u8, T_V3F), ws_bin(m, "*" as *u8, ws_id(m, "rt" as *u8, T_V3F), ws_sx(m, "sc" as *u8, T_V2F, "x" as *u8, T_F32), T_V3F), T_V3F), ws_bin(m, "*" as *u8, ws_id(m, "up" as *u8, T_V3F), ws_sx(m, "sc" as *u8, T_V2F, "y" as *u8, T_F32), T_V3F), T_V3F), T_V3F)))
930 ws_st(m, f, sir_let(m, "ro" as *u8, T_V3F, ws_id(m, "cam" as *u8, T_V3F)))
931 // Water and camera use this identical ray against the same immutable per-frame field.
932 ws_st(m, f, sir_var(m, "ground_t" as *u8, T_F32, ws_f(m, "-1.0" as *u8)))
933 ws_st(m, f, ws_if(m, ws_cmp(m, "==" as *u8, sir_ident(m, "r_surf" as *u8, T_I32), ws_i(m, "1" as *u8)), ws_set(m, ws_id(m, "ground_t" as *u8, T_F32), ws_c3(m, "smarch" as *u8, ws_id(m, "ro" as *u8, T_V3F), ws_id(m, "rd" as *u8, T_V3F), ws_i(m, "200" as *u8), T_F32)), 0))
934 ws_st(m, f, sir_let(m, "h" as *u8, hty, ws_c5(m, "scene_hit" as *u8, ws_id(m, "ro" as *u8, T_V3F), ws_id(m, "rd" as *u8, T_V3F), ws_i(m, "0" as *u8), ws_i(m, "200" as *u8), ws_id(m, "ground_t" as *u8, T_F32), hty)))
935 // var col:vec3f; if(h.t<0.0){col=sky(rd);}else{col=shade(...);if(h.b==4u){let h2=march(ro,rd,1,200);if(h2.t>0.0){col=col*0.58+shade(...h2...)*0.42;}}}
936 ws_st(m, f, sir_var(m, "col" as *u8, T_V3F, 0))
937 let sh1: i64 = ws_c6(m, "shade" as *u8, ws_id(m, "ro" as *u8, T_V3F), ws_id(m, "rd" as *u8, T_V3F), ws_mem(m, ws_id(m, "h" as *u8, hty), "t" as *u8, T_F32), ws_mem(m, ws_id(m, "h" as *u8, hty), "c" as *u8, T_V3I), ws_mem(m, ws_id(m, "h" as *u8, hty), "fce" as *u8, T_I32), ws_mem(m, ws_id(m, "h" as *u8, hty), "b" as *u8, T_U32), T_V3F)
938 let sh2: i64 = ws_c6(m, "shade" as *u8, ws_id(m, "ro" as *u8, T_V3F), ws_id(m, "rd" as *u8, T_V3F), ws_mem(m, ws_id(m, "h2" as *u8, hty), "t" as *u8, T_F32), ws_mem(m, ws_id(m, "h2" as *u8, hty), "c" as *u8, T_V3I), ws_mem(m, ws_id(m, "h2" as *u8, hty), "fce" as *u8, T_I32), ws_mem(m, ws_id(m, "h2" as *u8, hty), "b" as *u8, T_U32), T_V3F)
939 let blend: i64 = ws_set(m, ws_id(m, "col" as *u8, T_V3F), ws_bin(m, "+" as *u8, ws_bin(m, "*" as *u8, ws_id(m, "col" as *u8, T_V3F), ws_f(m, "0.58" as *u8), T_V3F), ws_bin(m, "*" as *u8, sh2, ws_f(m, "0.42" as *u8), T_V3F), T_V3F))
940 let h2: i64 = sir_let(m, "h2" as *u8, hty, ws_c5(m, "scene_hit" as *u8, ws_id(m, "ro" as *u8, T_V3F), ws_id(m, "rd" as *u8, T_V3F), ws_i(m, "1" as *u8), ws_i(m, "200" as *u8), ws_id(m, "ground_t" as *u8, T_F32), hty))
941 let water: i64 = ws_if(m, ws_cmp(m, "==" as *u8, ws_mem(m, ws_id(m, "h" as *u8, hty), "b" as *u8, T_U32), ws_u(m, "4" as *u8)), ws_q2(m, h2, ws_if(m, ws_cmp(m, ">" as *u8, ws_mem(m, ws_id(m, "h2" as *u8, hty), "t" as *u8, T_F32), ws_f(m, "0.0" as *u8)), blend, 0)), 0)
942 ws_st(m, f, ws_if(m, ws_cmp(m, "<" as *u8, ws_mem(m, ws_id(m, "h" as *u8, hty), "t" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_set(m, ws_id(m, "col" as *u8, T_V3F), ws_c1(m, "sky" as *u8, ws_id(m, "rd" as *u8, T_V3F), T_V3F)), ws_q2(m, ws_set(m, ws_id(m, "col" as *u8, T_V3F), sh1), water)))
943 // let ctr=u.res*0.5;
944 ws_st(m, f, sir_let(m, "ctr" as *u8, T_V2F, ws_bin(m, "*" as *u8, ws_id(m, "res" as *u8, T_V2F), ws_f(m, "0.5" as *u8), T_V2F)))
945 // if(u.rain>0.5){let rr=h21(vec2f(floor((px.x+px.y*0.35)/2.0),floor((px.y+u.t*13.0)/26.0)));if(rr>0.945){col=mix(col,vec3f(0.75,0.8,0.92),0.45);}col*=0.93;}
946 let rrx: i64 = ws_c1(m, "floor" as *u8, ws_bin(m, "/" as *u8, ws_bin(m, "+" as *u8, ws_sx(m, "px" as *u8, T_V2F, "x" as *u8, T_F32), ws_bin(m, "*" as *u8, ws_sx(m, "px" as *u8, T_V2F, "y" as *u8, T_F32), ws_f(m, "0.35" as *u8), T_F32), T_F32), ws_f(m, "2.0" as *u8), T_F32), T_F32)
947 let rry: i64 = ws_c1(m, "floor" as *u8, ws_bin(m, "/" as *u8, ws_bin(m, "+" as *u8, ws_sx(m, "px" as *u8, T_V2F, "y" as *u8, T_F32), ws_bin(m, "*" as *u8, ws_id(m, "t" as *u8, T_F32), ws_f(m, "13.0" as *u8), T_F32), T_F32), ws_f(m, "26.0" as *u8), T_F32), T_F32)
948 let rr: i64 = sir_let(m, "rr" as *u8, T_F32, ws_c1(m, "h21" as *u8, ws_v2(m, rrx, rry), T_F32))
949 let drops: i64 = ws_if(m, ws_cmp(m, ">" as *u8, ws_id(m, "rr" as *u8, T_F32), ws_f(m, "0.945" as *u8)), ws_set(m, ws_id(m, "col" as *u8, T_V3F), ws_c3(m, "mix" as *u8, ws_id(m, "col" as *u8, T_V3F), ws_v3f(m, "0.75" as *u8, "0.8" as *u8, "0.92" as *u8), ws_f(m, "0.45" as *u8), T_V3F)), 0)
950 ws_st(m, f, ws_if(m, ws_cmp(m, ">" as *u8, ws_id(m, "rain" as *u8, T_F32), ws_f(m, "0.5" as *u8)), ws_q3(m, rr, drops, ws_op(m, "col" as *u8, T_V3F, "*" as *u8, ws_f(m, "0.93" as *u8))), 0))
951 // the crosshair
952 let dx: i64 = ws_c1(m, "abs" as *u8, ws_bin(m, "-" as *u8, ws_sx(m, "px" as *u8, T_V2F, "x" as *u8, T_F32), ws_sx(m, "ctr" as *u8, T_V2F, "x" as *u8, T_F32), T_F32), T_F32)
953 let dy: i64 = ws_c1(m, "abs" as *u8, ws_bin(m, "-" as *u8, ws_sx(m, "px" as *u8, T_V2F, "y" as *u8, T_F32), ws_sx(m, "ctr" as *u8, T_V2F, "y" as *u8, T_F32), T_F32), T_F32)
954 let dx2: i64 = ws_c1(m, "abs" as *u8, ws_bin(m, "-" as *u8, ws_sx(m, "px" as *u8, T_V2F, "x" as *u8, T_F32), ws_sx(m, "ctr" as *u8, T_V2F, "x" as *u8, T_F32), T_F32), T_F32)
955 let dy2: i64 = ws_c1(m, "abs" as *u8, ws_bin(m, "-" as *u8, ws_sx(m, "px" as *u8, T_V2F, "y" as *u8, T_F32), ws_sx(m, "ctr" as *u8, T_V2F, "y" as *u8, T_F32), T_F32), T_F32)
956 let cross: i64 = ws_or(m, ws_and(m, ws_cmp(m, "<" as *u8, dx, ws_f(m, "8.0" as *u8)), ws_cmp(m, "<" as *u8, dy, ws_f(m, "1.5" as *u8))), ws_and(m, ws_cmp(m, "<" as *u8, dy2, ws_f(m, "8.0" as *u8)), ws_cmp(m, "<" as *u8, dx2, ws_f(m, "1.5" as *u8))))
957 let ccol: i64 = ws_if(m, ws_cmp(m, ">=" as *u8, ws_id(m, "npct" as *u8, T_F32), ws_f(m, "0.0" as *u8)), ws_set(m, ws_id(m, "col" as *u8, T_V3F), ws_v3f(m, "1.0" as *u8, "0.45" as *u8, "0.65" as *u8)), ws_if(m, ws_cmp(m, ">" as *u8, ws_id(m, "hok" as *u8, T_F32), ws_f(m, "0.5" as *u8)), ws_set(m, ws_id(m, "col" as *u8, T_V3F), ws_v3f(m, "1.0" as *u8, "0.82" as *u8, "0.35" as *u8)), ws_set(m, ws_id(m, "col" as *u8, T_V3F), ws_v1(m, T_V3F, ws_f(m, "1.0" as *u8)))))
958 ws_st(m, f, ws_if(m, cross, ccol, 0))
959 // let hbY=u.res.y*0.045;let hbS=u.res.x*0.018;
960 ws_st(m, f, sir_let(m, "hbY" as *u8, T_F32, ws_bin(m, "*" as *u8, ws_sx(m, "res" as *u8, T_V2F, "y" as *u8, T_F32), ws_f(m, "0.045" as *u8), T_F32)))
961 ws_st(m, f, sir_let(m, "hbS" as *u8, T_F32, ws_bin(m, "*" as *u8, ws_sx(m, "res" as *u8, T_V2F, "x" as *u8, T_F32), ws_f(m, "0.018" as *u8), T_F32)))
962 // for(var s2:i32=0;s2<7;s2++){let o=vec2f(u.res.x*0.02+f32(s2)*hbS*1.5,hbY); if(inside){var bt:i32; <bt chain>; if(s2<5){col=u.pal[bt-1].xyz;}else{col=u.palf[bt-12].xyz;} if(selected&&edge){col=vec3f(1.0);}}}
963 let ox: i64 = ws_bin(m, "+" as *u8, ws_bin(m, "*" as *u8, ws_sx(m, "res" as *u8, T_V2F, "x" as *u8, T_F32), ws_f(m, "0.02" as *u8), T_F32), ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, sir_cast(m, ws_id(m, "s2" as *u8, T_I32), T_F32), ws_id(m, "hbS" as *u8, T_F32), T_F32), ws_f(m, "1.5" as *u8), T_F32), T_F32)
964 let o: i64 = sir_let(m, "o" as *u8, T_V2F, ws_v2(m, ox, ws_id(m, "hbY" as *u8, T_F32)))
965 let inside: i64 = ws_and(m, ws_and(m, ws_and(m, ws_pxo(m, "x" as *u8, ">=" as *u8, ws_f(m, "0.0" as *u8)), ws_pxo(m, "x" as *u8, "<" as *u8, ws_id(m, "hbS" as *u8, T_F32))), ws_pxo(m, "y" as *u8, ">=" as *u8, ws_f(m, "0.0" as *u8))), ws_pxo(m, "y" as *u8, "<" as *u8, ws_id(m, "hbS" as *u8, T_F32)))
966 let btv: i64 = sir_var(m, "bt" as *u8, T_I32, 0)
967 let btc: i64 = ws_bt(m, "0" as *u8, "3" as *u8, ws_bt(m, "1" as *u8, "2" as *u8, ws_bt(m, "2" as *u8, "6" as *u8, ws_bt(m, "3" as *u8, "7" as *u8, ws_bt(m, "4" as *u8, "5" as *u8, ws_bt(m, "5" as *u8, "12" as *u8, ws_set(m, ws_id(m, "bt" as *u8, T_I32), ws_i(m, "13" as *u8))))))))
968 let pick: i64 = ws_if(m, ws_cmp(m, "<" as *u8, ws_id(m, "s2" as *u8, T_I32), ws_i(m, "5" as *u8)),
969 ws_set(m, ws_id(m, "col" as *u8, T_V3F), ws_sw(m, sir_index(m, ws_id(m, "pal" as *u8, T_V4F), ws_bin(m, "-" as *u8, ws_id(m, "bt" as *u8, T_I32), ws_i(m, "1" as *u8), T_I32), T_V4F), "xyz" as *u8, T_V3F)),
970 ws_set(m, ws_id(m, "col" as *u8, T_V3F), ws_sw(m, sir_index(m, ws_id(m, "palf" as *u8, T_V4F), ws_bin(m, "-" as *u8, ws_id(m, "bt" as *u8, T_I32), ws_i(m, "12" as *u8), T_I32), T_V4F), "xyz" as *u8, T_V3F)))
971 let rim: i64 = ws_or(m, ws_or(m, ws_or(m, ws_pxo(m, "x" as *u8, "<" as *u8, ws_f(m, "2.0" as *u8)), ws_cmp(m, ">" as *u8, ws_sx(m, "px" as *u8, T_V2F, "x" as *u8, T_F32), ws_bin(m, "-" as *u8, ws_bin(m, "+" as *u8, ws_sx(m, "o" as *u8, T_V2F, "x" as *u8, T_F32), ws_id(m, "hbS" as *u8, T_F32), T_F32), ws_f(m, "2.0" as *u8), T_F32))), ws_pxo(m, "y" as *u8, "<" as *u8, ws_f(m, "2.0" as *u8))), ws_cmp(m, ">" as *u8, ws_sx(m, "px" as *u8, T_V2F, "y" as *u8, T_F32), ws_bin(m, "-" as *u8, ws_bin(m, "+" as *u8, ws_sx(m, "o" as *u8, T_V2F, "y" as *u8, T_F32), ws_id(m, "hbS" as *u8, T_F32), T_F32), ws_f(m, "2.0" as *u8), T_F32)))
972 let selected: i64 = ws_if(m, ws_and(m, ws_cmp(m, "==" as *u8, ws_id(m, "bt" as *u8, T_I32), sir_cast(m, ws_id(m, "selb" as *u8, T_F32), T_I32)), rim), ws_set(m, ws_id(m, "col" as *u8, T_V3F), ws_v1(m, T_V3F, ws_f(m, "1.0" as *u8))), 0)
973 let slot: i64 = ws_if(m, inside, ws_q4(m, btv, btc, pick, selected), 0)
974 sir_for_until(m, f, sir_var(m, "s2" as *u8, T_I32, ws_i(m, "0" as *u8)), ws_cmp(m, ">=" as *u8, ws_id(m, "s2" as *u8, T_I32), ws_i(m, "7" as *u8)), ws_op(m, "s2" as *u8, T_I32, "+" as *u8, ws_i(m, "1" as *u8)), ws_q2(m, o, slot))
975 // return vec4f(vec3f(0.94)*pow(max(col,vec3f(0.0))*(1.0/0.94),vec3f(1.45)),1.0);
976 let graded: i64 = ws_bin(m, "*" as *u8, ws_v1(m, T_V3F, ws_f(m, "0.94" as *u8)), ws_c2(m, "pow" as *u8, ws_bin(m, "*" as *u8, ws_c2(m, "max" as *u8, ws_id(m, "col" as *u8, T_V3F), ws_v1(m, T_V3F, ws_f(m, "0.0" as *u8)), T_V3F), ws_bin(m, "/" as *u8, ws_f(m, "1.0" as *u8), ws_f(m, "0.94" as *u8), T_F32), T_V3F), ws_v1(m, T_V3F, ws_f(m, "1.45" as *u8)), T_V3F), T_V3F)
977 ws_st(m, f, ws_ret(m, ws_vt2(m, T_V4F, graded, ws_f(m, "1.0" as *u8))))
978 return f
979}
980
981// THE WORLD MODULE: uniforms, the voxel texture, struct Hit, every function, the fragment entry. Returns the entry.
982func shsrc_world(m: *i64) -> i64 {
983 ws_world_uniforms_raw(m)
984 ws_world_privates(m)
985 sir_texture(m, "tV" as *u8, T_TEX3U)
986 sir_texture(m, "tH" as *u8, T_TEX2F) // GE53: the surface field, one f32 height per column (r32float 128x128), uploaded from the sim's hq block
987 let hty: i64 = sir_struct_ty(ws_struct_hit(m))
988 ws_fn_rgb9(m)
989 ws_fn_upk(m)
990 ws_fn_vx(m)
991 ws_fn_h21(m)
992 ws_fn_h31(m)
993 ws_fn_vn3(m) // PG22: the cloud volume's noise, density and march -- after h31, before sky which calls cld3
994 ws_fn_cvol(m)
995 ws_fn_csun(m)
996 ws_fn_cld3(m)
997 ws_fn_pal9(m)
998 ws_fn_sky(m)
999 ws_fn_hq(m)
1000 ws_fn_surf(m)
1001 ws_fn_terrain(m)
1002 ws_fn_smarch(m)
1003 ws_fn_gnd(m)
1004 ws_fn_sand(m) // GR27: after surf, h21, vx and gnd (GLSL declares before use), before shade which calls it
1005 ws_fn_march(m, hty)
1006 ws_fn_scene_hit(m, hty)
1007 ws_fn_shade(m, hty)
1008 return ws_fn_fs(m, hty)
1009}