code wiki / _hdl_build / nx_f32_raster_gate.nx

nx_f32_raster_gate.nx source

↩ module page · 222 lines · 8003 B

1// nx_f32_raster_gate.nx -- R4: the FIRST visible hardware-f32 3D artifact. Renders a rotated, 2// directionally-shaded cube using nx_f32_hw f32 math (mat4 rotation + orthographic projection), 3// painter-sorted faces, integer barycentric fill, and writes a 24-bit BMP to web_assets/_game_build. 4// Proves the hardware-f32 stack drives a REAL raster image -- off the 1970s ASCII floor. 5// exit 0 = rendered (center pixel != background); the BMP is the artifact. license_tier: ORIGINAL 6import "nx_syscalls.nx" 7import "nx_f32_hw.nx" 8 9const W: i64 = 256 10const H: i64 = 256 11const SCALE: i64 = 64 12 13func imin(a: i64, b: i64) -> i64 { if a < b { return a } return b } 14func imax(a: i64, b: i64) -> i64 { if a > b { return a } return b } 15func min3(a: i64, b: i64, c: i64) -> i64 { return imin(a, imin(b, c)) } 16func max3(a: i64, b: i64, c: i64) -> i64 { return imax(a, imax(b, c)) } 17func same_sign3(a: i64, b: i64, c: i64) -> i64 { 18 if a >= 0 { if b >= 0 { if c >= 0 { return 1 } } } 19 if a <= 0 { if b <= 0 { if c <= 0 { return 1 } } } 20 return 0 21} 22// flat-fill a screen-space triangle (integer barycentric; winding-agnostic). 23func fill_tri(fb: *i64, x0: i64, y0: i64, x1: i64, y1: i64, x2: i64, y2: i64, col: i64) -> i64 { 24 let area: i64 = (x1 - x0) * (y2 - y0) - (x2 - x0) * (y1 - y0) 25 if area == 0 { return 0 } 26 let minx: i64 = imax(0, min3(x0, x1, x2)) 27 let maxx: i64 = imin(W - 1, max3(x0, x1, x2)) 28 let miny: i64 = imax(0, min3(y0, y1, y2)) 29 let maxy: i64 = imin(H - 1, max3(y0, y1, y2)) 30 var py: i64 = miny 31 while py <= maxy { 32 var px: i64 = minx 33 while px <= maxx { 34 let e0: i64 = (x2 - x1) * (py - y1) - (y2 - y1) * (px - x1) 35 let e1: i64 = (x0 - x2) * (py - y2) - (y0 - y2) * (px - x2) 36 let e2: i64 = (x1 - x0) * (py - y0) - (y1 - y0) * (px - x0) 37 if same_sign3(e0, e1, e2) == 1 { fb[py * W + px] = col } 38 px = px + 1 39 } 40 py = py + 1 41 } 42 return 0 43} 44func put_u32le(b: *u8, o: i64, v: i64) -> i64 { 45 b[o] = (v & 0xff) as u8 46 b[o + 1] = ((v >> 8) & 0xff) as u8 47 b[o + 2] = ((v >> 16) & 0xff) as u8 48 b[o + 3] = ((v >> 24) & 0xff) as u8 49 return 0 50} 51// 24-bit BMP (bottom-up, BGR). packed colour convention: c = R + G*256 + B*65536. 52func write_bmp(fb: *i64, path: *u8) -> i64 { 53 let pix: i64 = W * H * 3 54 let total: i64 = 54 + pix 55 let b: *u8 = sys_mmap(total) as *u8 56 b[0] = 66 as u8 57 b[1] = 77 as u8 58 put_u32le(b, 2, total) 59 put_u32le(b, 10, 54) 60 put_u32le(b, 14, 40) 61 put_u32le(b, 18, W) 62 put_u32le(b, 22, H) 63 b[26] = 1 as u8 64 b[28] = 24 as u8 65 put_u32le(b, 34, pix) 66 var o: i64 = 54 67 var ry: i64 = 0 68 while ry < H { 69 let sy: i64 = H - 1 - ry 70 var x: i64 = 0 71 while x < W { 72 let c: i64 = fb[sy * W + x] 73 b[o] = ((c >> 16) & 0xff) as u8 74 b[o + 1] = ((c >> 8) & 0xff) as u8 75 b[o + 2] = (c & 0xff) as u8 76 o = o + 3 77 x = x + 1 78 } 79 ry = ry + 1 80 } 81 let fd: i64 = sys_openat_wr(path, 0x1a4) 82 if fd < 0 { return 0 - 1 } 83 sys_write(fd, b, total) 84 sys_close(fd) 85 return 0 86} 87func fratio(num: i64, den: i64) -> i64 { return f32_div(f32_of(num), f32_of(den)) } 88// rotate a local direction by R, return its z-component (f32 carrier). 89func rot_nz(R: *i64, lx: i64, ly: i64, lz: i64) -> i64 { 90 let v: *i64 = sys_mmap(32) as *i64 91 let o: *i64 = sys_mmap(32) as *i64 92 v[0] = lx 93 v[1] = ly 94 v[2] = lz 95 v[3] = f32_of(0) 96 m4_vec4(R, v, o) 97 return o[2] 98} 99// directional brightness 55..255 from a rotated normal's z (front-facing = bright). 100func shade(nz: i64) -> i64 { 101 var z: i64 = nz 102 if (z & 0x80000000) != 0 { z = f32_of(0) } 103 return 55 + f32_int(f32_mul(z, f32_of(200))) 104} 105func packc(r: i64, g: i64, b: i64, br: i64) -> i64 { 106 let rr: i64 = (r * br) / 255 107 let gg: i64 = (g * br) / 255 108 let bb: i64 = (b * br) / 255 109 return rr + gg * 256 + bb * 65536 110} 111 112func main() -> i64 { 113 let fb: *i64 = sys_mmap(W * H * 8) as *i64 114 let bg: i64 = 28 + 32 * 256 + 44 * 65536 115 var i: i64 = 0 116 while i < W * H { 117 fb[i] = bg 118 i = i + 1 119 } 120 121 // R = Rx(22deg) * Ry(34deg), built from hardcoded f32 sin/cos ratios (no trig lib yet). 122 let cy: i64 = fratio(829, 1000) 123 let sy: i64 = fratio(559, 1000) 124 let cx: i64 = fratio(927, 1000) 125 let sx: i64 = fratio(375, 1000) 126 let Ry: *i64 = sys_mmap(128) as *i64 127 m4_identity(Ry) 128 Ry[0] = cy 129 Ry[2] = sy 130 Ry[8] = f32_neg(sy) 131 Ry[10] = cy 132 let Rx: *i64 = sys_mmap(128) as *i64 133 m4_identity(Rx) 134 Rx[5] = cx 135 Rx[6] = f32_neg(sx) 136 Rx[9] = sx 137 Rx[10] = cx 138 let R: *i64 = sys_mmap(128) as *i64 139 m4_mul(Rx, Ry, R) 140 141 // transform + orthographic-project the 8 cube vertices (local +-1). 142 let sxk: *i64 = sys_mmap(8 * 8) as *i64 143 let syk: *i64 = sys_mmap(8 * 8) as *i64 144 let tzi: *i64 = sys_mmap(8 * 8) as *i64 145 let one: i64 = f32_of(1) 146 let none: i64 = f32_neg(one) 147 var k: i64 = 0 148 while k < 8 { 149 var lx: i64 = none 150 if (k & 1) == 1 { lx = one } 151 var ly: i64 = none 152 if (k & 2) == 2 { ly = one } 153 var lz: i64 = none 154 if (k & 4) == 4 { lz = one } 155 let v: *i64 = sys_mmap(32) as *i64 156 let o: *i64 = sys_mmap(32) as *i64 157 v[0] = lx 158 v[1] = ly 159 v[2] = lz 160 v[3] = f32_of(0) 161 m4_vec4(R, v, o) 162 sxk[k] = (W / 2) + f32_int(f32_mul(o[0], f32_of(SCALE))) 163 syk[k] = (H / 2) - f32_int(f32_mul(o[1], f32_of(SCALE))) 164 tzi[k] = f32_int(f32_mul(o[2], f32_of(1000))) 165 k = k + 1 166 } 167 168 // 6 faces, 10 ints each: i0 i1 i2 i3 r g b lnx lny lnz 169 let F: *i64 = sys_mmap(60 * 8) as *i64 170 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 171 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 172 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 173 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 174 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 175 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 176 177 // painter's: draw faces far->near (ascending centroid z; +z is toward the viewer). 178 let drawn: *i64 = sys_mmap(6 * 8) as *i64 179 var df: i64 = 0 180 while df < 6 { 181 drawn[df] = 0 182 df = df + 1 183 } 184 var pass: i64 = 0 185 while pass < 6 { 186 var best: i64 = 0 - 1 187 var bestz: i64 = 0 188 var fi: i64 = 0 189 while fi < 6 { 190 if drawn[fi] == 0 { 191 let cb: i64 = fi * 10 192 let cz: i64 = (tzi[F[cb]] + tzi[F[cb + 1]] + tzi[F[cb + 2]] + tzi[F[cb + 3]]) / 4 193 if best < 0 { 194 best = fi 195 bestz = cz 196 } else { 197 if cz < bestz { 198 best = fi 199 bestz = cz 200 } 201 } 202 } 203 fi = fi + 1 204 } 205 drawn[best] = 1 206 let base: i64 = best * 10 207 let i0: i64 = F[base] 208 let i1: i64 = F[base + 1] 209 let i2: i64 = F[base + 2] 210 let i3: i64 = F[base + 3] 211 let nz: i64 = rot_nz(R, f32_of(F[base + 7]), f32_of(F[base + 8]), f32_of(F[base + 9])) 212 let br: i64 = shade(nz) 213 let col: i64 = packc(F[base + 4], F[base + 5], F[base + 6], br) 214 fill_tri(fb, sxk[i0], syk[i0], sxk[i1], syk[i1], sxk[i2], syk[i2], col) 215 fill_tri(fb, sxk[i0], syk[i0], sxk[i2], syk[i2], sxk[i3], syk[i3], col) 216 pass = pass + 1 217 } 218 219 write_bmp(fb, "web_assets/_game_build/f32cube.bmp" as *u8) 220 if fb[(H / 2) * W + (W / 2)] == bg { return 1 } 221 return 0 222}