nx_world_shader_sky_light_t154.nx source
↩ module page · 1016 lines · 114094 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 = "180.0" // the incumbent sheet's height in blocks, now the slab base
248const CB_TOP: *u8 = "300.0"
249const CB_RLO: *u8 = "24.0" // density ramps in over this many blocks above the base
250const CB_RHI: *u8 = "48.0" // and out over this many below the top
251const CB_CELL: *u8 = "180.0" // one noise cell in blocks, horizontal
252const CB_CELLY: *u8 = "120.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 = "1.4"
258const CB_STEPS: *u8 = "48"
259const CB_STEPS_F: *u8 = "48.0"
260const CB_SIGMA: *u8 = "0.04" // 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 (relative-energy approximation; normalized phase is not solar calibration): 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 = "480.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.85"
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_relative" 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, "phase" as *u8, T_F32, ws_bin(m, "/" as *u8, ws_id(m, "phase_relative" as *u8, T_F32), ws_f(m, "12.566370614359172" as *u8), T_F32)))
348 // Existing nx_atmosphere display convention is sqrt: decode before scattering, encode once after composite.
349 let sky_top: i64 = ws_bin(m, "*" as *u8, ws_id(m, "skt" as *u8, T_V3F), ws_id(m, "skt" as *u8, T_V3F), T_V3F)
350 let sky_horizon: i64 = ws_bin(m, "*" as *u8, ws_id(m, "skh" as *u8, T_V3F), ws_id(m, "skh" as *u8, T_V3F), T_V3F)
351 ws_st(m, f, sir_let(m, "ambient" as *u8, T_V3F, ws_bin(m, "*" as *u8, ws_bin(m, "+" as *u8, sky_top, sky_horizon, T_V3F), ws_bin(m, "*" as *u8, ws_f(m, CB_AMBIENT), ws_f(m, "0.5" as *u8), T_F32), T_V3F)))
352 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))
353 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))
354 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))
355 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))
356 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))
357 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))
358 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))
359 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)
360 let fog: i64 = ws_c3(m, "smoothstep" as *u8, ws_f(m, "0.0" as *u8), ws_f(m, CB_VIEW_DISTANCE), ws_id(m, "t0" as *u8, T_F32), T_F32)
361 let composite: i64 = ws_bin(m, "+" as *u8, ws_bin(m, "*" as *u8, ws_bin(m, "*" as *u8, ws_id(m, "s0" as *u8, T_V3F), ws_id(m, "s0" as *u8, T_V3F), T_V3F), ws_id(m, "tr" as *u8, T_F32), T_V3F), ws_id(m, "acc" as *u8, T_V3F), T_V3F)
362 let clear_linear: i64 = ws_bin(m, "*" as *u8, ws_id(m, "s0" as *u8, T_V3F), ws_id(m, "s0" as *u8, T_V3F), T_V3F)
363 ws_st(m, f, ws_ret(m, ws_c1(m, "sqrt" as *u8, ws_c3(m, "mix" as *u8, composite, clear_linear, fog, T_V3F), T_V3F)))
364 return f
365}
366
367// fn sky(rd:vec3f)->vec3f{ ... } -- the hand text, statement for statement
368func ws_fn_sky(m: *i64) -> i64 {
369 let f: i64 = sir_func(m, "sky" as *u8, T_V3F)
370 sir_param(m, f, "rd" as *u8, T_V3F)
371 // var s:vec3f=mix(u.skh,u.skt,clamp(rd.y*1.6+0.35,0.0,1.0));
372 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)
373 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)))
374 // 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);}}
375 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))
376 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))
377 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))
378 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))
379 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))
380 // PG22: s = cld3(rd, s) -- the cloud is a raymarched 3D density (vn3 / cvol / cld3 above), never the projected
381 // sheet this block used to draw; the cld>0.5 && rd.y>0.04 gate lives inside cld3 as its early return.
382 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)))
383 ws_st(m, f, ws_ret(m, ws_id(m, "s" as *u8, T_V3F)))
384 return f
385}
386
387// struct Hit{t:f32,c:vec3i,fce:i32,b:u32}
388func ws_struct_hit(m: *i64) -> i64 {
389 let st: i64 = sir_struct(m, "Hit" as *u8)
390 sir_member(m, st, "t" as *u8, T_F32)
391 sir_member(m, st, "c" as *u8, T_V3I)
392 sir_member(m, st, "fce" as *u8, T_I32)
393 sir_member(m, st, "b" as *u8, T_U32)
394 return st
395}
396
397// 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);
398func ws_dda_step(m: *i64, ax: *u8, fneg: *u8, fpos: *u8) -> i64 {
399 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))
400 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))
401 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))
402 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))
403 return ws_q4(m, s1, s2, s3, s4)
404}
405
406// ---- GE53 THE SURFACE FIELD (WebGPU, emitted from this one source) ---------------------------------------
407// 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; }
408// the column's Q height in blocks (the base of its top block), -1 off the window
409func ws_fn_hq(m: *i64) -> i64 {
410 let f: i64 = sir_func(m, "hq" as *u8, T_F32)
411 sir_param(m, f, "x" as *u8, T_I32)
412 sir_param(m, f, "z" as *u8, T_I32)
413 let oob: i64 = ws_or(m, ws_or(m, ws_or(m,
414 ws_cmp(m, "<" as *u8, ws_id(m, "x" as *u8, T_I32), ws_i(m, "0" as *u8)),
415 ws_cmp(m, "<" as *u8, ws_id(m, "z" as *u8, T_I32), ws_i(m, "0" as *u8))),
416 ws_cmp(m, ">" as *u8, ws_id(m, "x" as *u8, T_I32), ws_i(m, "127" as *u8))),
417 ws_cmp(m, ">" as *u8, ws_id(m, "z" as *u8, T_I32), ws_i(m, "127" as *u8)))
418 ws_st(m, f, ws_if(m, oob, ws_ret(m, ws_f(m, "-1.0" as *u8)), 0))
419 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))
420 ws_st(m, f, ws_ret(m, ws_sw(m, tl, "r" as *u8, T_F32)))
421 return f
422}
423// fn surf(p:vec2f)->f32 -- the terrain SURFACE height at a world xz: bilinear between the four columns,
424// one block above the column base (the top of the ground). -1 when any corner is off the field.
425func ws_fn_surf(m: *i64) -> i64 {
426 let f: i64 = sir_func(m, "surf" as *u8, T_F32)
427 sir_param(m, f, "p" as *u8, T_V2F)
428 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)))
429 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)))
430 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)))
431 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)))
432 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)))
433 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)))
434 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)))
435 let miss: i64 = ws_or(m, ws_or(m, ws_or(m,
436 ws_cmp(m, "<" as *u8, ws_id(m, "h00" as *u8, T_F32), ws_f(m, "0.0" as *u8)),
437 ws_cmp(m, "<" as *u8, ws_id(m, "h10" as *u8, T_F32), ws_f(m, "0.0" as *u8))),
438 ws_cmp(m, "<" as *u8, ws_id(m, "h01" as *u8, T_F32), ws_f(m, "0.0" as *u8))),
439 ws_cmp(m, "<" as *u8, ws_id(m, "h11" as *u8, T_F32), ws_f(m, "0.0" as *u8)))
440 ws_st(m, f, ws_if(m, miss, ws_ret(m, ws_f(m, "-1.0" as *u8)), 0))
441 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)
442 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)
443 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)))
444 return f
445}
446// fn terrain(b:u32)->i32 -- the ground classes the field replaces; structures (wood, leaves, crops, water) stay cells
447func ws_fn_terrain(m: *i64) -> i64 {
448 let f: i64 = sir_func(m, "terrain" as *u8, T_I32)
449 sir_param(m, f, "b" as *u8, T_U32)
450 let tb: i64 = ws_or(m, ws_or(m, ws_or(m, ws_or(m, ws_or(m, ws_or(m, ws_or(m,
451 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))
452 ws_st(m, f, ws_if(m, tb, ws_ret(m, ws_i(m, "1" as *u8)), 0))
453 ws_st(m, f, ws_ret(m, ws_i(m, "0" as *u8)))
454 return f
455}
456// fn smarch(ro:vec3f,rd:vec3f,mx:i32)->f32 -- march the continuous surface: quarter-block steps (the field is
457// bilinear between columns, so a quarter block can never skip one), exit above the tallest column when climbing,
458// six bisections at the crossing. Returns t, or -1 for sky. The GPU twin of the sim's wray_surf.
459func ws_fn_smarch(m: *i64) -> i64 {
460 let f: i64 = sir_func(m, "smarch" as *u8, T_F32)
461 sir_param(m, f, "ro" as *u8, T_V3F)
462 sir_param(m, f, "rd" as *u8, T_V3F)
463 sir_param(m, f, "mx" as *u8, T_I32)
464 ws_st(m, f, sir_var(m, "t" as *u8, T_F32, ws_f(m, "0.0" as *u8)))
465 ws_st(m, f, sir_var(m, "tp" as *u8, T_F32, ws_f(m, "0.0" as *u8)))
466 ws_st(m, f, sir_var(m, "hit" as *u8, T_I32, ws_i(m, "0" as *u8)))
467 let s1: i64 = ws_op(m, "t" as *u8, T_F32, "+" as *u8, ws_f(m, "0.25" as *u8))
468 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))
469 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)
470 let oob: i64 = ws_or(m, ws_or(m, ws_or(m,
471 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)),
472 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))),
473 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))),
474 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)))
475 let s4: i64 = ws_if(m, oob, ws_ret(m, ws_f(m, "-1.0" as *u8)), 0)
476 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))
477 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)
478 let s7: i64 = ws_set(m, ws_id(m, "tp" as *u8, T_F32), ws_id(m, "t" as *u8, T_F32))
479 let body: i64 = ws_q4(m, ws_q3(m, s1, s2, s3), s4, s5, ws_q2(m, s6, s7))
480 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)
481 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))
482 ws_st(m, f, sir_var(m, "lo" as *u8, T_F32, ws_id(m, "tp" as *u8, T_F32)))
483 ws_st(m, f, sir_var(m, "hi" as *u8, T_F32, ws_id(m, "t" as *u8, T_F32)))
484 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))
485 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))
486 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))
487 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)))
488 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))
489 ws_st(m, f, ws_ret(m, ws_id(m, "hi" as *u8, T_F32)))
490 return f
491}
492// fn gnd(p:vec2f)->f32 -- the ground light from the field's own gradient (central differences a quarter block
493// apart), Lambert against the sun and NORMALISED TO LEVEL GROUND: level lights exactly as the shipped flat top
494// face (1.0), the lee side floors at the shipped darkest face (0.42) -- the same two values shade's six-way
495// face table carries, so a flat field is byte-identical in brightness to a flat block top.
496func ws_fn_gnd(m: *i64) -> i64 {
497 let f: i64 = sir_func(m, "gnd" as *u8, T_F32)
498 sir_param(m, f, "p" as *u8, T_V2F)
499 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)))
500 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)))
501 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)))
502 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)))
503 let miss: i64 = ws_or(m, ws_or(m, ws_or(m,
504 ws_cmp(m, "<" as *u8, ws_id(m, "hl" as *u8, T_F32), ws_f(m, "0.0" as *u8)),
505 ws_cmp(m, "<" as *u8, ws_id(m, "hr" as *u8, T_F32), ws_f(m, "0.0" as *u8))),
506 ws_cmp(m, "<" as *u8, ws_id(m, "hd" as *u8, T_F32), ws_f(m, "0.0" as *u8))),
507 ws_cmp(m, "<" as *u8, ws_id(m, "hu" as *u8, T_F32), ws_f(m, "0.0" as *u8)))
508 ws_st(m, f, ws_if(m, miss, ws_ret(m, ws_f(m, "1.0" as *u8)), 0))
509 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)
510 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)
511 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)))
512 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)))
513 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)))
514 let span: i64 = ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_f(m, "0.42" as *u8), T_F32)
515 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)))
516 return f
517}
518
519// fn march(ro:vec3f,rd:vec3f,skipw:i32,mx:i32)->Hit{ ... }
520func ws_fn_march(m: *i64, hty: i64) -> i64 {
521 let f: i64 = sir_func(m, "march" as *u8, hty)
522 sir_param(m, f, "ro" as *u8, T_V3F)
523 sir_param(m, f, "rd" as *u8, T_V3F)
524 sir_param(m, f, "skipw" as *u8, T_I32)
525 sir_param(m, f, "mx" as *u8, T_I32)
526 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
527 // var h:Hit;h.t=-1.0;h.fce=0;h.b=0u;h.c=vec3i(0);
528 ws_st(m, f, sir_var(m, "h" as *u8, hty, 0))
529 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)))
530 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)))
531 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)))
532 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))))
533 // var c:vec3i=vec3i(floor(ro));let st=vec3i(sign(rd));
534 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))))
535 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))))
536 // let dd=abs(vec3f(1.0)/max(abs(rd),vec3f(1e-6)));
537 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)))
538 // var tm=(vec3f(st)*(vec3f(c)-ro)+vec3f(st)*0.5+vec3f(0.5))*dd;
539 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)
540 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)
541 let tm2: i64 = ws_bin(m, "+" as *u8, tm1, ws_v1(m, T_V3F, ws_f(m, "0.5" as *u8)), T_V3F)
542 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)))
543 ws_st(m, f, sir_var(m, "t" as *u8, T_F32, ws_f(m, "0.0" as *u8)))
544 ws_st(m, f, sir_var(m, "fce" as *u8, T_I32, ws_i(m, "0" as *u8)))
545 // for(var i:i32=0;i<200;i++){ ... }
546 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)
547 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)))
548 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))
549 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)))
550 // if(f32(c.y)>u.wmax&&rd.y>=0.0){return h;}if(c.y<0){return h;}
551 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)
552 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)
553 // if(c.x< -8||c.x>135||c.z< -8||c.z>135){return h;}
554 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)))
555 let b5: i64 = ws_if(m, oob, ws_ret(m, ws_id(m, "h" as *u8, hty)), 0)
556 // var b=vx(c);if(skipw==1&&b==4u){b=0u;}
557 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))
558 // GE53: under skipt the terrain classes are air too -- the field is the ground, only structures stay cells
559 let b7: i64 = ws_q2(m,
560 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),
561 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))
562 // if(b!=0u){h.t=t;h.c=c;h.fce=fce;h.b=b;return h;}
563 let hit: i64 = ws_q5(m,
564 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)),
565 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)),
566 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)),
567 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)),
568 ws_ret(m, ws_id(m, "h" as *u8, hty)))
569 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)
570 let body: i64 = ws_q4(m, ws_q4(m, b1, b2, b3, b4), b5, b6, ws_q2(m, b7, b8))
571 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)
572 ws_st(m, f, ws_ret(m, ws_id(m, "h" as *u8, hty)))
573 return f
574}
575
576// one face arm of shade: uv=hp.<sw>;oc.<ax>=(oc.<ax><op>1);n=vec3f(<nx>,<ny>,<nz>);
577func ws_face(m: *i64, sw: *u8, ax: *u8, op: *u8, nx: *u8, ny: *u8, nz: *u8) -> i64 {
578 return ws_q3(m,
579 ws_set(m, ws_id(m, "uv" as *u8, T_V2F), ws_sx(m, "hp" as *u8, T_V3F, sw, T_V2F)),
580 ws_opx(m, "oc" as *u8, T_V3I, ax, T_I32, op, ws_i(m, "1" as *u8)),
581 ws_set(m, ws_id(m, "n" as *u8, T_V3F), ws_v3f(m, nx, ny, nz)))
582}
583// li=(li*<k>)
584func ws_li(m: *i64, k: *u8) -> i64 { return ws_op(m, "li" as *u8, T_F32, "*" as *u8, ws_f(m, k)) }
585// fce==<k>
586func 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)) }
587// b==<k>u
588func 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)) }
589// one AO probe: if(f.<fa> <cmp> <edge>){var nb=oc; <nudge>; if(vx(nb)!=0u&&vx(nb)!=4u){ao=(ao+(<gain>)*2.0);}}
590func ws_ao(m: *i64, fa: *u8, cmp: *u8, edge: *u8, nudge: i64, gain: i64) -> i64 {
591 let nbv: i64 = sir_var(m, "nb" as *u8, T_V3I, ws_id(m, "oc" as *u8, T_V3I))
592 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)))
593 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))
594 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)
595}
596// nb.<ax>=(nb.<ax><op>1)
597func 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)) }
598// fce==3||fce==4
599func ws_topbot(m: *i64) -> i64 { return ws_or(m, ws_fce(m, "3" as *u8), ws_fce(m, "4" as *u8)) }
600
601// fn shade(ro:vec3f,rd:vec3f,t:f32,c:vec3i,fce:i32,b:u32)->vec3f{ ... }
602// GE53 helpers -- each call builds a FRESH node tree (a node is never two children).
603// Terrain lighting belongs only to a field hit, never to water or an object top face.
604func ws_smooth(m: *i64) -> i64 {
605 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))
606 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)))
607}
608// The analytic plane has two sides; neither inherits the voxel material's cell decoration.
609func ws_cont_water(m: *i64) -> i64 {
610 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))
611}
612func ws_cont_surface(m: *i64) -> i64 { return ws_or(m, ws_smooth(m), ws_cont_water(m)) }
613// 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;}
614func ws_step_down(m: *i64) -> i64 {
615 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)
616}
617// ---- GR27 (2026-09-06): THE GROUND IS A MATERIAL, NOT A PAINT -----------------------------------------------
618// fn sand(hp:vec3f,c:vec3i,rd:vec3f,t:f32)->vec2f -- the field's ground material, all arithmetic on the surface
619// field and the voxel volume, no texture. x = the light multiplier: the gnd() Lambert (level 1.0, lee floor 0.42)
620// taken on the field normal TILTED by grain facets and wind ripples, then wet-darkened; y = the specular: a thin
621// water film inside the wet band (a Blinn lobe plus a Fresnel sky sheen) and dry quartz glints.
622// FOOTPRINT: one pixel spans 2/res.x world units per unit distance (sc = px/(res.x*0.5)), stretched by 1/|n.rd|
623// at grazing angles. A hash cannot be mip-averaged, so every detail whose period falls under TWO footprints
624// (the Nyquist bound) fades to zero instead of aliasing -- grains and ripples survive a grazing view by
625// fading, never by sparkling; beyond that range sand reads as its albedo, which is what sand does.
626// WET BAND: the volume is probed for water (class 4) on a ring of SD_RING_DIRS directions x SD_WET_R radii at
627// the column's top solid cell and one below it; the nearest water radius sets the wetness (adjacent 1, three
628// cells 1/3, beyond 0) and a water cell ABOVE the column means submerged (1). Wet sand darkens because pore
629// water index-matches the grains (albedo x SD_WET_DARK) and gains a film sheen; the swash erases ripples.
630// Every constant below is a data hook: the ripple heading is the wind row's heading and the grain scale the
631// recipe's sand grade; both become raw words when the material table lands, and are NAMED here until then.
632const SD_GRAIN_PER_BLOCK: *u8 = "32.0" // facets per block edge: 3 cm at a 1 m block, coarse beach sand
633const SD_GRAIN_SLOPE: *u8 = "1.2" // facet steepness as a normal slope
634const SD_RIPPLE_PER_BLOCK: *u8 = "9.0" // wind ripples per block: an 11 cm wavelength at a 1 m block
635const SD_RIPPLE_SLOPE: *u8 = "0.45" // crest slope
636const SD_RIPPLE_DX: *u8 = "0.8" // ripple normal heading (unit): the wind heading, a data hook
637const SD_RIPPLE_DZ: *u8 = "0.6"
638const SD_PATCH: *u8 = "0.25" // ripple phase jitter per 4-block patch so the field is not one sine
639const SD_TAU: *u8 = "6.2831853"
640const SD_QUARTER_TURN: *u8 = "1.5707963"
641const SD_EIGHTH_TURN: *u8 = "0.7853982"
642const SD_RING_DIRS: *u8 = "8"
643const SD_RING_STEPS: *u8 = "24" // SD_RING_DIRS x SD_WET_R
644const SD_WET_R: *u8 = "3.0" // wet band reach in cells
645const SD_WET_DRY: *u8 = "4.0" // SD_WET_R + 1: no water within reach
646const SD_WET_DARK: *u8 = "0.55" // wet albedo multiplier
647const SD_FILM_POW: *u8 = "48.0"
648const SD_FILM_GAIN: *u8 = "0.55"
649const SD_SHEEN_GAIN: *u8 = "0.10"
650const SD_GLINT_POW: *u8 = "96.0"
651const SD_GLINT_GAIN: *u8 = "0.35"
652const SD_GLINT_FRAC: *u8 = "0.9" // facets whose hash exceeds this are quartz glints
653const SD_NDV_FLOOR: *u8 = "0.15" // the footprint stretch floor at grazing angles
654const SD_SHADOW_SPEC: *u8 = "0.2" // in a block shadow the film keeps its sky sheen and loses the sun
655const SD_TWO: *u8 = "2.0"
656const SD_HALF: *u8 = "0.5"
657// helpers -- every call builds a FRESH node tree (a node is never two children)
658func ws_sd_pxz(m: *i64) -> i64 { return ws_sx(m, "hp" as *u8, T_V3F, "xz" as *u8, T_V2F) }
659func ws_sd_f(m: *i64, n: *u8) -> i64 { return ws_id(m, n, T_F32) }
660func ws_sd_v3(m: *i64, n: *u8) -> i64 { return ws_id(m, n, T_V3F) }
661// surf(hp.xz <op> (dx,dz))
662func 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) }
663// h21(gc + (dx,dz))
664func 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) }
665func 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)) }
666func 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) }
667// vx(c + vec3i(dx*k, <y>, dz*k)) == 4u
668func 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)) }
669// i32(floor(sin(a + <shift>) + 0.5)) -- the ring direction from the angle, sin only (the covered subset)
670func 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) }
671// clamp(1 - 2*fp*<freq>, 0, 1) -- the Nyquist fade of a detail with <freq> periods per block
672func 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) }
673// (a - b) * <k>
674func 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) }
675// <s> + gam*<g> - dry*rs*<rdk> -- one axis of the tilted normal
676func ws_sd_tilt(m: *i64, s: *u8, g: *u8, rdk: *u8) -> i64 {
677 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)
678 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)
679}
680// the sand classes: 1 the shore slot (SHORE repaints the grass slot as shore sand), 2 packed sand, 5 sand at and
681// below the waterline (nx_wasm_craft gencol) -- and ONLY under the field (ws_smooth), which today is the shore
682// world's ground; a per-class material word is the data hook owed before another world's field lands
683func 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)) }
684func ws_sandy(m: *i64) -> i64 { return ws_and(m, ws_smooth(m), ws_sandcls(m)) }
685// the block-shadow arm: li*=0.55 as shipped, and the film specular loses the sun (keeps its sky sheen)
686func 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))) }
687func ws_fn_sand(m: *i64) -> i64 {
688 let f: i64 = sir_func(m, "sand" as *u8, T_V2F)
689 sir_param(m, f, "hp" as *u8, T_V3F)
690 sir_param(m, f, "c" as *u8, T_V3I)
691 sir_param(m, f, "rd" as *u8, T_V3F)
692 sir_param(m, f, "t" as *u8, T_F32)
693 // the field normal from the same quarter-block central differences gnd uses; off the field = the flat answer
694 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)))
695 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)))
696 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)))
697 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)))
698 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))
699 ws_st(m, f, ws_if(m, miss, ws_ret(m, ws_v2f(m, "1.0" as *u8, "0.0" as *u8)), 0))
700 ws_st(m, f, sir_let(m, "sx" as *u8, T_F32, ws_sd_dslope(m, "hl" as *u8, "hr" as *u8, SD_TWO)))
701 ws_st(m, f, sir_let(m, "sz" as *u8, T_F32, ws_sd_dslope(m, "hd" as *u8, "hu" as *u8, SD_TWO)))
702 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)))
703 // the pixel footprint at this hit, stretched by the grazing angle
704 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)))
705 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)))
706 // grain facets: three hash taps a facet apart give the facet's two slopes; the amplitude fades at the Nyquist bound
707 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)))
708 ws_st(m, f, sir_let(m, "g0" as *u8, T_F32, ws_sd_g(m, "0.0" as *u8, "0.0" as *u8)))
709 ws_st(m, f, sir_let(m, "g1" as *u8, T_F32, ws_sd_g(m, "1.0" as *u8, "0.0" as *u8)))
710 ws_st(m, f, sir_let(m, "g2" as *u8, T_F32, ws_sd_g(m, "0.0" as *u8, "1.0" as *u8)))
711 ws_st(m, f, sir_let(m, "gam" as *u8, T_F32, ws_sd_fade(m, SD_GRAIN_PER_BLOCK)))
712 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)))
713 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)))
714 // wind ripples: a crest slope along the wind heading, phase-jittered per patch, fading at its own Nyquist bound
715 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)
716 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)
717 ws_st(m, f, sir_let(m, "ph" as *u8, T_F32, ws_bin(m, "+" as *u8, ph0, ph1, T_F32)))
718 ws_st(m, f, sir_let(m, "ram" as *u8, T_F32, ws_sd_fade(m, SD_RIPPLE_PER_BLOCK)))
719 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)))
720 // the wet band: the nearest water on the ring, at this cell's height and one below
721 ws_st(m, f, sir_var(m, "wd" as *u8, T_F32, ws_f(m, SD_WET_DRY)))
722 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))
723 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))
724 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))
725 let dx: i64 = sir_let(m, "dx" as *u8, T_I32, ws_sd_dir(m, SD_QUARTER_TURN))
726 let dz: i64 = sir_let(m, "dz" as *u8, T_I32, ws_sd_dir(m, "0.0" as *u8))
727 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)
728 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))
729 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))
730 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))
731 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)))
732 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)))
733 // the tilted normal: field slope + faded facets + the ripples the swash has not erased
734 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)))
735 // light: the gnd() Lambert on the tilted normal (level 1.0, lee floor 0.42), then wet darkening
736 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)))
737 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)))
738 let span: i64 = ws_bin(m, "-" as *u8, ws_f(m, "1.0" as *u8), ws_f(m, "0.42" as *u8), T_F32)
739 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)))
740 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)))
741 // specular: the film's Blinn lobe and Fresnel sky sheen inside the band, quartz glints on dry facets
742 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)))
743 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)))
744 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)))
745 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)))
746 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)))
747 ws_st(m, f, sir_var(m, "glint" as *u8, T_F32, ws_f(m, "0.0" as *u8)))
748 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))
749 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))
750 // x = light, y = specular: the sun terms scaled by the sun flag, the sheen is the sky's and stays
751 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)
752 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))))
753 return f
754}
755func ws_fn_shade(m: *i64, hty: i64) -> i64 {
756 let f: i64 = sir_func(m, "shade" as *u8, T_V3F)
757 sir_param(m, f, "ro" as *u8, T_V3F)
758 sir_param(m, f, "rd" as *u8, T_V3F)
759 sir_param(m, f, "t" as *u8, T_F32)
760 sir_param(m, f, "c" as *u8, T_V3I)
761 sir_param(m, f, "fce" as *u8, T_I32)
762 sir_param(m, f, "b" as *u8, T_U32)
763 // let hp=ro+rd*t; var uv:vec2f; var oc:vec3i=c; var n:vec3f=vec3f(0.0);
764 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)))
765 ws_st(m, f, sir_var(m, "uv" as *u8, T_V2F, 0))
766 ws_st(m, f, sir_var(m, "oc" as *u8, T_V3I, ws_id(m, "c" as *u8, T_V3I)))
767 ws_st(m, f, sir_var(m, "n" as *u8, T_V3F, ws_v1(m, T_V3F, ws_f(m, "0.0" as *u8))))
768 // the six faces
769 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)
770 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)
771 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)
772 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)
773 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)
774 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))
775 // let f=fract(uv); var bb:u32=b; if(b==1u&&fce!=3&&fce!=4){bb=2u;if(f.y>0.8){bb=1u;}}
776 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)))
777 ws_st(m, f, sir_var(m, "bb" as *u8, T_U32, ws_id(m, "b" as *u8, T_U32)))
778 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))
779 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))
780 // var li:f32; the six-way face light
781 ws_st(m, f, sir_var(m, "li" as *u8, T_F32, 0))
782 let l6: i64 = ws_set(m, ws_id(m, "li" as *u8, T_F32), ws_f(m, "0.56" as *u8))
783 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)
784 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)
785 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)
786 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)
787 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))
788 // GE53: on the field the ground's own gradient lights the top face (level = the same 1.0, lee = the same 0.42 floor)
789 // GR27: on the field the sand classes are a MATERIAL -- sand() lights the tilted normal and returns the film specular
790 // in sp; every other class on the field keeps the bare gradient light
791 ws_st(m, f, sir_var(m, "sp" as *u8, T_F32, ws_f(m, "0.0" as *u8)))
792 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)))
793 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))
794 // if(u.sun>0.5){if(fce==1){li*=1.12;}if(fce==2){li*=0.92;}if(fce==5){li*=1.04;}}
795 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))
796 // let sd3=floor(hp)*0.13; let bs=f32(b)*7.0;
797 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)))
798 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)))
799 // t00 / t10 / t01 = h31(vec3f(floor(f*24.0 [+ offset]),bs)+sd3)
800 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)
801 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)))
802 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)
803 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)))
804 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)
805 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)))
806 // let bmp=(t10-t00)*0.6+(t01-t00)*0.45;
807 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)))
808 // var bamp:f32; the block-class relief amplitude
809 ws_st(m, f, sir_var(m, "bamp" as *u8, T_F32, 0))
810 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)))
811 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)
812 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))
813 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))
814 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
815 // 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;
816 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)))
817 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)))
818 // The sand material owns its detail response; legacy voxel paint belongs to other surfaces.
819 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))
820 // 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;}}
821 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))
822 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))
823 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))
824 // if(f.x<0.055||f.x>0.945||f.y<0.055||f.y>0.945){li*=0.82;}
825 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)))
826 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
827 // var ao:f32=0.0; the four edge-AO probes
828 ws_st(m, f, sir_var(m, "ao" as *u8, T_F32, ws_f(m, "0.0" as *u8)))
829 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)))
830 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)))
831 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)))
832 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)))
833 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))
834 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)))
835 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))
836 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)))
837 // li*=1.0-min(ao,0.45);
838 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
839 // if(u.sun>0.5){let sh=march(hp+n*0.02,u.sund,1,60);if(sh.t>0.0){li*=0.55;}}
840 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))
841 // GE53: on the field a cell march cannot shadow the ground (terrain cells are air to it), so the surface march does
842 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)
843 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))
844 // 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);
845 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
846 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)
847 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)))
848 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)))
849 return f
850}
851
852// the hotbar slot's block id: if(s2==0){bt=3;}else if(s2==1){bt=2;}...else{bt=13;}
853func ws_bt(m: *i64, k: *u8, v: *u8, els: i64) -> i64 {
854 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)
855}
856// px.<a> <op> (o.<a> + <e>) / px.<a> <op> (o.<a> + hbS - <e>)
857func 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)) }
858
859// the fragment entry: fs -- the world pass per pixel, the hand text statement for statement (yflip carries the
860// WebGPU top-left origin as a uniform so ONE source serves both doors)
861// One hit policy for visible geometry and geometry seen through water.
862// Continuous still-water intersection. Level is simulation data; no water voxel supplies geometry.
863func ws_fn_water_hit(m: *i64, hty: i64) -> i64 {
864 let f: i64 = sir_func(m, "water_hit" as *u8, hty)
865 sir_param(m, f, "ro" as *u8, T_V3F); sir_param(m, f, "rd" as *u8, T_V3F)
866 sir_param(m, f, "prior" as *u8, hty); sir_param(m, f, "mx" as *u8, T_I32)
867 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))
868 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)))
869 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)))
870 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)))
871 ws_st(m, f, ws_if(m, outside, ws_ret(m, ws_id(m, "prior" as *u8, hty)), 0))
872 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)))
873 ws_st(m, f, ws_if(m, occluded, ws_ret(m, ws_id(m, "prior" as *u8, hty)), 0))
874 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)))
875 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)))
876 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)))
877 ws_st(m, f, ws_if(m, dry, ws_ret(m, ws_id(m, "prior" as *u8, hty)), 0))
878 ws_st(m, f, sir_var(m, "result" as *u8, hty, ws_id(m, "prior" as *u8, hty)))
879 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)))
880 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)))
881 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))))
882 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)))
883 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))
884 ws_st(m, f, ws_ret(m, ws_id(m, "result" as *u8, hty)))
885 return f
886}
887
888func ws_fn_scene_hit(m: *i64, hty: i64) -> i64 {
889 ws_fn_water_hit(m, hty)
890 let f: i64 = sir_func(m, "scene_hit" as *u8, hty)
891 sir_param(m, f, "ro" as *u8, T_V3F)
892 sir_param(m, f, "rd" as *u8, T_V3F)
893 sir_param(m, f, "skipw" as *u8, T_I32)
894 sir_param(m, f, "mx" as *u8, T_I32)
895 sir_param(m, f, "ts" as *u8, T_F32)
896 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)))
897 // Both camera and transmitted-water rays resolve the same continuous ground.
898 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))
899 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))
900 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))
901 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))
902 // Search the actual column extent: water and air cannot supply the seabed material.
903 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)
904 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)))
905 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))))
906 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))
907 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))
908 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)))
909 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))
910 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))))
911 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)
912 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))
913 // Resolve water against the same field after ground/objects, preserving nearest-hit ordering.
914 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)
915 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))
916 ws_st(m, f, ws_ret(m, ws_id(m, "h" as *u8, hty)))
917 return f
918}
919
920func ws_fn_fs(m: *i64, hty: i64) -> i64 {
921 sir_fragout(m, "fc" as *u8, T_V4F, 0)
922 let f: i64 = sir_func(m, "main" as *u8, T_VOID)
923 sir_param_position(m, f, "pos" as *u8)
924 // upk(); -- GE55: derive every float from the raw words FIRST; every statement below reads the private state
925 ws_st(m, f, sir_expr(m, sir_call(m, "upk" as *u8, T_VOID)))
926 // let px=vec2f(pos.x,mix(pos.y,u.res.y-pos.y,u.yflip));
927 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)
928 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))))
929 // let sc=(px-u.res*0.5)/(u.res.x*0.5);
930 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)))
931 // 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);
932 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))))
933 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))))
934 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))))
935 // let rd=normalize(fw+rt*sc.x+up*sc.y); let ro=u.cam; let h=march(ro,rd,0,200);
936 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)))
937 ws_st(m, f, sir_let(m, "ro" as *u8, T_V3F, ws_id(m, "cam" as *u8, T_V3F)))
938 // Water and camera use this identical ray against the same immutable per-frame field.
939 ws_st(m, f, sir_var(m, "ground_t" as *u8, T_F32, ws_f(m, "-1.0" as *u8)))
940 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))
941 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)))
942 // 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;}}}
943 ws_st(m, f, sir_var(m, "col" as *u8, T_V3F, 0))
944 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)
945 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)
946 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))
947 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))
948 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)
949 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)))
950 // let ctr=u.res*0.5;
951 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)))
952 // 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;}
953 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)
954 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)
955 let rr: i64 = sir_let(m, "rr" as *u8, T_F32, ws_c1(m, "h21" as *u8, ws_v2(m, rrx, rry), T_F32))
956 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)
957 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))
958 // the crosshair
959 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)
960 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)
961 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)
962 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)
963 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))))
964 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)))))
965 ws_st(m, f, ws_if(m, cross, ccol, 0))
966 // let hbY=u.res.y*0.045;let hbS=u.res.x*0.018;
967 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)))
968 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)))
969 // 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);}}}
970 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)
971 let o: i64 = sir_let(m, "o" as *u8, T_V2F, ws_v2(m, ox, ws_id(m, "hbY" as *u8, T_F32)))
972 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)))
973 let btv: i64 = sir_var(m, "bt" as *u8, T_I32, 0)
974 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))))))))
975 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)),
976 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)),
977 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)))
978 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)))
979 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)
980 let slot: i64 = ws_if(m, inside, ws_q4(m, btv, btc, pick, selected), 0)
981 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))
982 // return vec4f(vec3f(0.94)*pow(max(col,vec3f(0.0))*(1.0/0.94),vec3f(1.45)),1.0);
983 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)
984 ws_st(m, f, ws_ret(m, ws_vt2(m, T_V4F, graded, ws_f(m, "1.0" as *u8))))
985 return f
986}
987
988// THE WORLD MODULE: uniforms, the voxel texture, struct Hit, every function, the fragment entry. Returns the entry.
989func shsrc_world(m: *i64) -> i64 {
990 ws_world_uniforms_raw(m)
991 ws_world_privates(m)
992 sir_texture(m, "tV" as *u8, T_TEX3U)
993 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
994 let hty: i64 = sir_struct_ty(ws_struct_hit(m))
995 ws_fn_rgb9(m)
996 ws_fn_upk(m)
997 ws_fn_vx(m)
998 ws_fn_h21(m)
999 ws_fn_h31(m)
1000 ws_fn_vn3(m) // PG22: the cloud volume's noise, density and march -- after h31, before sky which calls cld3
1001 ws_fn_cvol(m)
1002 ws_fn_csun(m)
1003 ws_fn_cld3(m)
1004 ws_fn_pal9(m)
1005 ws_fn_sky(m)
1006 ws_fn_hq(m)
1007 ws_fn_surf(m)
1008 ws_fn_terrain(m)
1009 ws_fn_smarch(m)
1010 ws_fn_gnd(m)
1011 ws_fn_sand(m) // GR27: after surf, h21, vx and gnd (GLSL declares before use), before shade which calls it
1012 ws_fn_march(m, hty)
1013 ws_fn_scene_hit(m, hty)
1014 ws_fn_shade(m, hty)
1015 return ws_fn_fs(m, hty)
1016}