code wiki / (root) / nx_wasmcube.nx

nx_wasmcube.nx source

↩ module page · 152 lines · 6361 B

1// nx_wasmcube.nx -- the f32 renderer in the WASM/BROWSER memory model: a rotated shaded 3D cube drawn to a 2// framebuffer in fixed linear-memory offsets (NO sys_mmap -- wasm has no syscalls). f32 mat4 camera (the now- 3// wasm-capable __f32_*), painter-sorted faces, integer fill. JS passes cos/sin (it owns trig), reads the fb, 4// blits to <canvas>. Compiles via the SOVEREIGN nx_compile_wat -> nx_wat_compiler -> .wasm. license_tier: ORIGINAL 5import "nx_f32_hw.nx" 6const O_MAGIC_65536: i64 = 65536 7const O_MAGIC_16777216: i64 = 16777216 8 9const W: i64 = 128 10const H: i64 = 128 11const HWc: i64 = 64 12const HHc: i64 = 64 13const SCALE: i64 = 34 14const O_FB: i64 = 0 15const O_RY: i64 = 131072 16const O_RX: i64 = 131200 17const O_R: i64 = 131328 18const O_SX: i64 = 131456 19const O_SY: i64 = 131520 20const O_TZ: i64 = 131584 21const O_F: i64 = 131648 22const O_DRAWN: i64 = 132128 23const O_VTMP: i64 = 132176 24const O_OTMP: i64 = 132208 25 26func imin(a: i64, b: i64) -> i64 { if a < b { return a } return b } 27func imax(a: i64, b: i64) -> i64 { if a > b { return a } return b } 28func min3(a: i64, b: i64, c: i64) -> i64 { return imin(a, imin(b, c)) } 29func max3(a: i64, b: i64, c: i64) -> i64 { return imax(a, imax(b, c)) } 30func same_sign3(a: i64, b: i64, c: i64) -> i64 { 31 if a >= 0 { if b >= 0 { if c >= 0 { return 1 } } } 32 if a <= 0 { if b <= 0 { if c <= 0 { return 1 } } } 33 return 0 34} 35func fbp() -> *i64 { return (O_FB as i64) as *i64 } 36func fratio(num: i64, den: i64) -> i64 { return f32_div(f32_of(num), f32_of(den)) } 37func fill_tri(x0: i64, y0: i64, x1: i64, y1: i64, x2: i64, y2: i64, col: i64) -> i64 { 38 let fb: *i64 = fbp() 39 let area: i64 = (x1 - x0) * (y2 - y0) - (x2 - x0) * (y1 - y0) 40 if area == 0 { return 0 } 41 let minx: i64 = imax(0, min3(x0, x1, x2)) 42 let maxx: i64 = imin(W - 1, max3(x0, x1, x2)) 43 let miny: i64 = imax(0, min3(y0, y1, y2)) 44 let maxy: i64 = imin(H - 1, max3(y0, y1, y2)) 45 var py: i64 = miny 46 while py <= maxy { 47 var px: i64 = minx 48 while px <= maxx { 49 let e0: i64 = (x2 - x1) * (py - y1) - (y2 - y1) * (px - x1) 50 let e1: i64 = (x0 - x2) * (py - y2) - (y0 - y2) * (px - x2) 51 let e2: i64 = (x1 - x0) * (py - y0) - (y1 - y0) * (px - x0) 52 if same_sign3(e0, e1, e2) == 1 { fb[py * W + px] = col } 53 px = px + 1 54 } 55 py = py + 1 56 } 57 return 0 58} 59func rot_nz(R: *i64, lx: i64, ly: i64, lz: i64) -> i64 { 60 let v: *i64 = (O_VTMP as i64) as *i64 61 let o: *i64 = (O_OTMP as i64) as *i64 62 v[0] = lx; v[1] = ly; v[2] = lz; v[3] = f32_of(0) 63 m4_vec4(R, v, o) 64 return o[2] 65} 66func shade(nz: i64) -> i64 { 67 var z: i64 = nz 68 if (z & 0x80000000) != 0 { z = f32_of(0) } 69 return 55 + f32_int(f32_mul(z, f32_of(200))) 70} 71func packc(r: i64, g: i64, b: i64, br: i64) -> i64 { 72 let rr: i64 = (r * br) / 255 73 let gg: i64 = (g * br) / 255 74 let bb: i64 = (b * br) / 255 75 return rr + gg * 256 + bb * O_MAGIC_65536 + 255 * O_MAGIC_16777216 76} 77// render the cube. ycos/ysin/xcos/xsin are cos/sin * 1000 (JS owns trig). 78func render(ycos: i64, ysin: i64, xcos: i64, xsin: i64) -> i64 { 79 let fb: *i64 = fbp() 80 let bg: i64 = 28 + 32 * 256 + 44 * O_MAGIC_65536 + 255 * O_MAGIC_16777216 81 var i: i64 = 0 82 while i < W * H { fb[i] = bg; i = i + 1 } 83 let Ry: *i64 = (O_RY as i64) as *i64 84 let Rx: *i64 = (O_RX as i64) as *i64 85 let R: *i64 = (O_R as i64) as *i64 86 m4_roty(fratio(ycos, 1000), fratio(ysin, 1000), Ry) 87 m4_rotx(fratio(xcos, 1000), fratio(xsin, 1000), Rx) 88 m4_mul(Rx, Ry, R) 89 let sx: *i64 = (O_SX as i64) as *i64 90 let sy: *i64 = (O_SY as i64) as *i64 91 let tz: *i64 = (O_TZ as i64) as *i64 92 let one: i64 = f32_of(1) 93 let none: i64 = f32_neg(one) 94 var k: i64 = 0 95 while k < 8 { 96 var lx: i64 = none 97 if (k & 1) == 1 { lx = one } 98 var ly: i64 = none 99 if ((k >> 1) & 1) == 1 { ly = one } 100 var lz: i64 = none 101 if ((k >> 2) & 1) == 1 { lz = one } 102 let v: *i64 = (O_VTMP as i64) as *i64 103 let o: *i64 = (O_OTMP as i64) as *i64 104 v[0] = lx; v[1] = ly; v[2] = lz; v[3] = f32_of(0) 105 m4_vec4(R, v, o) 106 sx[k] = HWc + f32_int(f32_mul(o[0], f32_of(SCALE))) 107 sy[k] = HHc - f32_int(f32_mul(o[1], f32_of(SCALE))) 108 tz[k] = f32_int(f32_mul(o[2], f32_of(1000))) 109 k = k + 1 110 } 111 let F: *i64 = (O_F as i64) as *i64 112 F[0] = 4; F[1] = 5; F[2] = 7; F[3] = 6; F[4] = 90; F[5] = 150; F[6] = 235; F[7] = 0; F[8] = 0; F[9] = 1 113 F[10] = 0; F[11] = 1; F[12] = 3; F[13] = 2; F[14] = 70; F[15] = 110; F[16] = 180; F[17] = 0; F[18] = 0; F[19] = 0 - 1 114 F[20] = 1; F[21] = 5; F[22] = 7; F[23] = 3; F[24] = 230; F[25] = 85; F[26] = 80; F[27] = 1; F[28] = 0; F[29] = 0 115 F[30] = 0; F[31] = 4; F[32] = 6; F[33] = 2; F[34] = 170; F[35] = 60; F[36] = 58; F[37] = 0 - 1; F[38] = 0; F[39] = 0 116 F[40] = 2; F[41] = 3; F[42] = 7; F[43] = 6; F[44] = 95; F[45] = 205; F[46] = 110; F[47] = 0; F[48] = 1; F[49] = 0 117 F[50] = 0; F[51] = 1; F[52] = 5; F[53] = 4; F[54] = 70; F[55] = 150; F[56] = 82; F[57] = 0; F[58] = 0 - 1; F[59] = 0 118 let drawn: *i64 = (O_DRAWN as i64) as *i64 119 var df: i64 = 0 120 while df < 6 { drawn[df] = 0; df = df + 1 } 121 var pass: i64 = 0 122 while pass < 6 { 123 var best: i64 = 0 - 1 124 var bestz: i64 = 0 125 var fi: i64 = 0 126 while fi < 6 { 127 if drawn[fi] == 0 { 128 let cb: i64 = fi * 10 129 let cz: i64 = (tz[F[cb]] + tz[F[cb + 1]] + tz[F[cb + 2]] + tz[F[cb + 3]]) / 4 130 if best < 0 { best = fi; bestz = cz } else { if cz < bestz { best = fi; bestz = cz } } 131 } 132 fi = fi + 1 133 } 134 drawn[best] = 1 135 let base: i64 = best * 10 136 let i0: i64 = F[base] 137 let i1: i64 = F[base + 1] 138 let i2: i64 = F[base + 2] 139 let i3: i64 = F[base + 3] 140 let nz: i64 = rot_nz(R, f32_of(F[base + 7]), f32_of(F[base + 8]), f32_of(F[base + 9])) 141 let br: i64 = shade(nz) 142 let col: i64 = packc(F[base + 4], F[base + 5], F[base + 6], br) 143 fill_tri(sx[i0], sy[i0], sx[i1], sy[i1], sx[i2], sy[i2], col) 144 fill_tri(sx[i0], sy[i0], sx[i2], sy[i2], sx[i3], sy[i3], col) 145 pass = pass + 1 146 } 147 return 0 148} 149func fb_off() -> i64 { return O_FB } 150func ww() -> i64 { return W } 151func hh() -> i64 { return H } 152func main() -> i64 { return 0 }