code wiki / (root) / nx_nishios_raster.nx

nx_nishios_raster.nx source

↩ module page · 123 lines · 7663 B

1// nx_nishios_raster.nx -- GOAL-GPU-NATIVE rung-1: a sovereign SOFTWARE RASTERIZER (seed of the 3D stack). 2// First concrete rung toward native gaming (No Man's Sky-class, the north star): real triangles drawn 3// into the nx_fb framebuffer via EDGE FUNCTIONS (per-pixel inside test), BARYCENTRIC GOURAUD shading 4// (per-vertex colour interpolation), and a Z-BUFFER (per-pixel depth). The z-buffer is what makes it 5// 3D, not 2D: a NEAR triangle must occlude a FAR one regardless of DRAW ORDER. Scene: a far gradient 6// triangle, a near solid-yellow triangle over it, then a far cyan triangle drawn LAST over the near one 7// -- the depth test must REJECT the late far triangle so the near yellow survives. 8// KAT: triangles rasterize (substantial coverage, corner is background); Z-BUFFER correct (every pixel 9// the near triangle owns stays near-yellow even though a far triangle was drawn over it afterward); 10// Gouraud shading produces real colour variation; BMP exported. All integer math, fully sovereign. 11// HONEST SCOPE: flat per-triangle depth + 2D screen-space tris (the raster core); 3D transform/clip/ 12// perspective + a sovereign GPU to run it fast = the rungs above, toward measured-vs-DirectX. 13// No hw writes (Rule 26). expect_exit: 0 license_tier: ORIGINAL 14import "nx_fb.nx" 15const K_MAGIC_1500: i64 = 1500 16 17func rs_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 18func rs_num(v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 } 19func rs_edge(ax: i64, ay: i64, bx: i64, by: i64, px: i64, py: i64) -> i64 { return (bx-ax)*(py-ay) - (by-ay)*(px-ax) } 20func rs_min3(a: i64, b: i64, c: i64) -> i64 { var m: i64=a; if b<m {m=b} if c<m {m=c} return m } 21func rs_max3(a: i64, b: i64, c: i64) -> i64 { var m: i64=a; if b>m {m=b} if c>m {m=c} return m } 22func rs_clamp(v: i64, lo: i64, hi: i64) -> i64 { if v<lo {return lo} if v>hi {return hi} return v } 23 24// rasterize one triangle. v=[x0,y0,x1,y1,x2,y2], z=depth (smaller=nearer), col=[r0,g0,b0,r1,g1,b1,r2,g2,b2] 25func raster_tri(fb: *u8, zbuf: *i64, W: i64, H: i64, v: *i64, z: i64, col: *i64) -> i64 { 26 let x0: i64=v[0]; let y0: i64=v[1]; let x1: i64=v[2]; let y1: i64=v[3]; let x2: i64=v[4]; let y2: i64=v[5] 27 let area: i64 = rs_edge(x0,y0,x1,y1,x2,y2) 28 if area==0 { return 0 } 29 let minx: i64 = rs_clamp(rs_min3(x0,x1,x2), 0, W-1) 30 let maxx: i64 = rs_clamp(rs_max3(x0,x1,x2), 0, W-1) 31 let miny: i64 = rs_clamp(rs_min3(y0,y1,y2), 0, H-1) 32 let maxy: i64 = rs_clamp(rs_max3(y0,y1,y2), 0, H-1) 33 var py: i64=miny 34 while py<=maxy { 35 var px: i64=minx 36 while px<=maxx { 37 let w0: i64 = rs_edge(x1,y1,x2,y2,px,py) 38 let w1: i64 = rs_edge(x2,y2,x0,y0,px,py) 39 let w2: i64 = rs_edge(x0,y0,x1,y1,px,py) 40 var inside: i64=0 41 if area>0 { if w0>=0 { if w1>=0 { if w2>=0 { inside=1 } } } } else { if w0<=0 { if w1<=0 { if w2<=0 { inside=1 } } } } 42 if inside==1 { 43 let idx: i64 = py*W+px 44 if z < zbuf[idx] { 45 zbuf[idx]=z 46 let r: i64 = (w0*col[0]+w1*col[3]+w2*col[6])/area 47 let g: i64 = (w0*col[1]+w1*col[4]+w2*col[7])/area 48 let b: i64 = (w0*col[2]+w1*col[5]+w2*col[8])/area 49 fb_setpx(fb,W,H,px,py,r,g,b) 50 } 51 } 52 px=px+1 53 } 54 py=py+1 55 } 56 return 0 57} 58 59func main() -> i64 { 60 rs_puts("GOAL-GPU-NATIVE rung-1: sovereign SOFTWARE RASTERIZER (edge-function tris + Gouraud + Z-buffer)\n" as *u8) 61 let W: i64=160 62 let H: i64=120 63 let fb: *u8 = sys_mmap(W*H*3) 64 let zbuf: *i64 = sys_mmap(W*H*8) as *i64 65 let FAR: i64 = 1<<30 66 var i: i64=0 67 while i<W*H { zbuf[i]=FAR; i=i+1 } 68 fb_rect(fb,W,H, 0,0, W,H, 20,20,30) // background 69 70 let v: *i64 = sys_mmap(8*6) as *i64 71 let col: *i64 = sys_mmap(8*9) as *i64 72 73 // T_far (z=100): gradient R/G/B triangle 74 v[0]=18; v[1]=14; v[2]=150; v[3]=34; v[4]=38; v[5]=112 75 col[0]=220; col[1]=40; col[2]=40; col[3]=40; col[4]=220; col[5]=40; col[6]=40; col[7]=40; col[8]=220 76 raster_tri(fb, zbuf, W, H, v, 100, col) 77 // T_near (z=40): solid yellow, over the far triangle 78 v[0]=70; v[1]=30; v[2]=156; v[3]=86; v[4]=64; v[5]=106 79 col[0]=230; col[1]=210; col[2]=50; col[3]=230; col[4]=210; col[5]=50; col[6]=230; col[7]=210; col[8]=50 80 raster_tri(fb, zbuf, W, H, v, 40, col) 81 // T_far2 (z=100): cyan, drawn LAST over the near region -> depth test must REJECT it where near owns 82 v[0]=74; v[1]=40; v[2]=140; v[3]=80; v[4]=68; v[5]=100 83 col[0]=40; col[1]=200; col[2]=200; col[3]=40; col[4]=200; col[5]=200; col[6]=40; col[7]=200; col[8]=200 84 raster_tri(fb, zbuf, W, H, v, 100, col) 85 86 // analyse the result 87 var covered: i64=0 88 var near_px: i64=0 89 var near_yellow: i64=0 90 var minr: i64=999 91 var maxr: i64=0-1 92 var p: i64=0 93 while p<W*H { 94 if zbuf[p]<FAR { 95 covered=covered+1 96 let r: i64=fb[p*3] as i64 97 if r<minr { minr=r } 98 if r>maxr { maxr=r } 99 } 100 if zbuf[p]==40 { 101 near_px=near_px+1 102 if (fb[p*3] as i64)==230 { if (fb[p*3+1] as i64)==210 { if (fb[p*3+2] as i64)==50 { near_yellow=near_yellow+1 } } } 103 } 104 p=p+1 105 } 106 107 let sz: i64 = fb_bmp_save(fb, W, H, "knowledge/status/nishios_raster.bmp\x00" as *u8) 108 let hd: i64 = sys_openat_wr("knowledge/status/nishios_raster.html\x00" as *u8, 0x1a4) 109 if hd>0 { let html: *u8 = "<!doctype html><html><body style=\x27background:#0a0a12;color:#8af;font-family:monospace;text-align:center\x27><h3>NishiOS sovereign software rasterizer (Gouraud + Z-buffer)</h3><img src=\x27nishios_raster.bmp\x27 style=\x27image-rendering:pixelated;width:640px;border:1px solid #333\x27></body></html>\x00"; var hn: i64=0; while html[hn]!=(0 as u8){hn=hn+1} sys_write(hd, html, hn); sys_close(hd) } 110 111 rs_puts(" covered pixels="); rs_num(covered); rs_puts(" near(z=40) pixels="); rs_num(near_px); rs_puts(" of which yellow="); rs_num(near_yellow); rs_puts(" R range="); rs_num(minr); rs_puts(".."); rs_num(maxr); rs_puts("\n" as *u8) 112 113 var pass: i64=0 114 var ttl: i64=0 115 ttl=ttl+1; rs_puts(" T1 triangles rasterized (substantial coverage, corner is background): " as *u8); if covered>K_MAGIC_1500 { if (fb[(2*W+2)*3] as i64)==20 { pass=pass+1; rs_puts("PASS\n" as *u8) } else { rs_puts("FAIL\n" as *u8) } } else { rs_puts("FAIL\n" as *u8) } 116 ttl=ttl+1; rs_puts(" T2 Z-BUFFER correct: every near pixel stays near-yellow despite a far tri drawn LAST over it: " as *u8); if near_px>0 { if near_yellow==near_px { pass=pass+1; rs_puts("PASS\n" as *u8) } else { rs_puts("FAIL\n" as *u8) } } else { rs_puts("FAIL\n" as *u8) } 117 ttl=ttl+1; rs_puts(" T3 Gouraud shading produced real colour variation (R range>50): " as *u8); if (maxr-minr)>50 { pass=pass+1; rs_puts("PASS\n" as *u8) } else { rs_puts("FAIL\n" as *u8) } 118 ttl=ttl+1; rs_puts(" T4 framebuffer encoded to BMP: " as *u8); if sz>0 { pass=pass+1; rs_puts("PASS\n" as *u8) } else { rs_puts("FAIL\n" as *u8) } 119 120 rs_puts("NISHIOS-RASTER-GATE passed "); rs_num(pass); rs_puts("/"); rs_num(ttl) 121 if pass==ttl { rs_puts(" verdict=GREEN (sovereign 3D rasterizer w/ depth test -- first rung of the graphics stack toward native gaming)\n" as *u8); sys_exit(0); return 0 } 122 rs_puts(" verdict=RED\n" as *u8); sys_exit(1); return 1 123}