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}