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 }