code wiki / _hdl_build / nx_shade_gate.nx
nx_shade_gate.nx source
↩ module page · 78 lines · 4015 B
1// nx_shade_gate.nx -- proves P1 texture/gouraud. Renders a 96x48 image: LEFT = gouraud triangle with
2// red/green/blue vertices (smooth RGB gradient); RIGHT = a triangle textured with an 8x8 yellow/purple
3// checkerboard. Asserts: each gouraud vertex region is the right hue, the interior is a true blend, and
4// the textured region contains BOTH checker colors. Writes knowledge/nx_shade.png for eyeball verify.
5// license_tier: ORIGINAL expect_exit: 0
6import "nx_syscalls.nx"
7import "nx_shade.nx"
8import "nx_png.nx"
9
10func vw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
11func vn(v: i64) -> i64 { let bb: *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{bb[i]=t[k-1-i];i=i+1} sys_write(1,bb,k); return 0 }
12func px(fb: *i64, w: i64, x: i64, y: i64) -> i64 { return fb[y*w + x] }
13
14func main() -> i64 {
15 let w: i64 = 96
16 let h: i64 = 48
17 let fb: *i64 = sys_mmap(8 * 96 * 48) as *i64
18 sh_clear(fb, w, h, sh_rgb(20, 20, 30)) // dark slate background
19
20 let RED: i64 = sh_rgb(255,0,0)
21 let GRN: i64 = sh_rgb(0,255,0)
22 let BLU: i64 = sh_rgb(0,0,255)
23 // LEFT: gouraud triangle A(6,6)=red B(44,6)=green C(24,42)=blue
24 sh_tri_gouraud(fb, w, h, 6,6,RED, 44,6,GRN, 24,42,BLU)
25
26 // 8x8 checkerboard texture: yellow / purple
27 let YEL: i64 = sh_rgb(230,210,40)
28 let PUR: i64 = sh_rgb(120,40,160)
29 let tex: *i64 = sys_mmap(8 * 64) as *i64
30 var ti: i64 = 0
31 while ti < 64 {
32 let u: i64 = ti % 8
33 let v: i64 = ti / 8
34 if ((u + v) & 1) == 0 { tex[ti] = YEL } else { tex[ti] = PUR }
35 ti = ti + 1
36 }
37 // RIGHT: textured triangle (52,6)uv(0,0) (92,6)uv(7,0) (72,42)uv(3,7)
38 sh_tri_textured(fb, w, h, tex, 8, 52,6,0,0, 92,6,7,0, 72,42,3,7)
39
40 write_png(fb, w, h, "knowledge/nx_shade.png" as *u8)
41
42 var pass: i64 = 0
43 var total: i64 = 0
44
45 // gouraud hue checks (sample points proven inside the triangle)
46 let pa: i64 = px(fb,w, 9,9) // near red vertex
47 total=total+1; if sh_r(pa) > sh_g(pa) { if sh_r(pa) > sh_b(pa) { pass=pass+1 } else { vw("S1 FAIL not red\n") } } else { vw("S1 FAIL not red\n") }
48 let pb: i64 = px(fb,w, 40,9) // near green vertex
49 total=total+1; if sh_g(pb) > sh_r(pb) { if sh_g(pb) > sh_b(pb) { pass=pass+1 } else { vw("S2 FAIL not green\n") } } else { vw("S2 FAIL not green\n") }
50 let pc: i64 = px(fb,w, 24,38) // near blue vertex
51 total=total+1; if sh_b(pc) > sh_r(pc) { if sh_b(pc) > sh_g(pc) { pass=pass+1 } else { vw("S3 FAIL not blue\n") } } else { vw("S3 FAIL not blue\n") }
52 let pm: i64 = px(fb,w, 24,18) // interior = blend
53 total=total+1; if sh_r(pm)>0 { if sh_g(pm)>0 { if sh_b(pm)>0 { pass=pass+1 } else { vw("S4 FAIL no blend\n") } } else { vw("S4 FAIL no blend\n") } } else { vw("S4 FAIL no blend\n") }
54
55 // texture: both checker colors present in the right half
56 var nyel: i64 = 0
57 var npur: i64 = 0
58 var y: i64 = 0
59 while y < h {
60 var x: i64 = 50
61 while x < w {
62 let c: i64 = px(fb,w,x,y)
63 if c == YEL { nyel = nyel + 1 }
64 if c == PUR { npur = npur + 1 }
65 x = x + 1
66 }
67 y = y + 1
68 }
69 total=total+1; if nyel > 0 { if npur > 0 { pass=pass+1 } else { vw("S5 FAIL purple absent\n") } } else { vw("S5 FAIL yellow absent\n") }
70
71 vw("=== SHADE render -> knowledge/nx_shade.png (96x48) ===\n")
72 vw(" gouraud A(9,9)=("); vn(sh_r(pa)); vw(","); vn(sh_g(pa)); vw(","); vn(sh_b(pa)); vw(") blend(24,18)=("); vn(sh_r(pm)); vw(","); vn(sh_g(pm)); vw(","); vn(sh_b(pm)); vw(")\n")
73 vw(" texture checker: yellow_px="); vn(nyel); vw(" purple_px="); vn(npur); vw("\n")
74 vw("SHADE "); vn(pass); vw("/"); vn(total); vw("\n")
75 if pass == total { vw("SHADE ALL-PASS (RGB gouraud gradient + textured checkerboard; PNG written)\n"); sys_exit(0) }
76 sys_exit(1)
77 return 1
78}