code wiki / _hdl_build / nx_depth_tri_gate.nx
nx_depth_tri_gate.nx source
↩ module page · 105 lines · 5817 B
1// nx_depth_tri_gate.nx -- proves the Z-BUFFER: overlapping triangles resolve OCCLUSION order-independently.
2// Two big triangles both cover the center pixel: NEAR (z=100, RED) and FAR (z=900, BLUE).
3// T1 depth-on: far-then-near frame == near-then-far frame (occlusion is ORDER-INDEPENDENT).
4// T2 the overlap pixel shows the NEAR triangle (red), not the far one -> the depth TEST actually occludes.
5// T3 NEG-CONTROL painter's (depth-off): far-then-near != near-then-far (draw order matters) -> the depth
6// test in T1 was load-bearing, not a no-op that trivially always matches.
7// Artifact: knowledge/nx_depth_tri.ppm (depth-on far-then-near). license_tier: ORIGINAL expect_exit: 0
8import "nx_syscalls.nx"
9import "nx_image.nx"
10import "nx_depth_tri.nx"
11import "nx_png_write.nx"
12
13func hw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
14func pn(v: i64) -> i64 { let t: *u8=sys_mmap(24); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} 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} let b: *u8=sys_mmap(24); var j: i64=0; while j<k{b[j]=t[k-1-j];j=j+1} sys_write(1,b,k); return 0 }
15
16func img_black(fb: *Image) -> i64 {
17 let p: *u8 = fb.pixels
18 let n: i64 = fb.height * fb.stride
19 var i: i64 = 0
20 while i < n { p[i] = 0 as u8; i = i + 1 }
21 return 0
22}
23func img_diff(a: *Image, b: *Image) -> i64 {
24 let pa: *u8 = a.pixels
25 let pb: *u8 = b.pixels
26 let n: i64 = a.height * a.stride
27 var d: i64 = 0
28 var i: i64 = 0
29 while i < n { if pa[i] != pb[i] { d = d + 1 } i = i + 1 }
30 return d
31}
32
33func main() -> i64 {
34 hw("=== nx_depth_tri_gate -- Z-buffer: order-independent occlusion (2D blit -> real 3D visibility) ===\n" as *u8)
35 var fails: i64 = 0
36 let W: i64 = 128
37 let H: i64 = 128
38 let npix: i64 = W * H
39 let zb: *i64 = sys_mmap(npix * 8) as *i64
40 let BIG: i64 = 1000000000
41
42 // NEAR (red, z=100): apex-down triangle covering the center. FAR (blue, z=900): apex-up triangle covering
43 // the center. They OVERLAP in a central diamond; the center pixel (64,64) is inside BOTH.
44
45 // ---- ORDER A: FAR then NEAR (depth on) ----
46 let fbA: *Image = nx_image_alloc(W, H, 3)
47 img_black(fbA)
48 depth_clear(zb, npix, BIG)
49 depth_tri_render(fbA, zb, 10, 118, 900, 118, 118, 900, 64, 18, 900, 0, 0, 255, 1) // FAR blue first
50 depth_tri_render(fbA, zb, 10, 10, 100, 118, 10, 100, 64, 110, 100, 255, 0, 0, 1) // NEAR red second
51
52 // ---- ORDER B: NEAR then FAR (depth on) -- MUST equal A ----
53 let fbB: *Image = nx_image_alloc(W, H, 3)
54 img_black(fbB)
55 depth_clear(zb, npix, BIG)
56 depth_tri_render(fbB, zb, 10, 10, 100, 118, 10, 100, 64, 110, 100, 255, 0, 0, 1) // NEAR red first
57 depth_tri_render(fbB, zb, 10, 118, 900, 118, 118, 900, 64, 18, 900, 0, 0, 255, 1) // FAR blue second
58
59 let d1: i64 = img_diff(fbA, fbB)
60 hw(" depth-on order-diff bytes=" as *u8); pn(d1); hw("\n" as *u8)
61 var t1: i64 = 0
62 if d1 == 0 { t1 = 1 }
63 if t1 == 1 { hw("T1 PASS occlusion ORDER-INDEPENDENT (far->near frame == near->far frame with depth test)\n" as *u8) } else { fails=fails+1; hw("T1 FAIL depth frames differ by draw order\n" as *u8) }
64
65 // T2: overlap pixel (64,64) is RED (near), not blue (far)
66 let off: i64 = 64 * fbA.stride + 64 * 3
67 let pr: *u8 = fbA.pixels
68 var t2: i64 = 0
69 if pr[off] == (255 as u8) { if pr[off+2] == (0 as u8) { t2 = 1 } }
70 hw(" overlap px(64,64) rgb=" as *u8); pn(pr[off] as i64); hw("," as *u8); pn(pr[off+1] as i64); hw("," as *u8); pn(pr[off+2] as i64); hw("\n" as *u8)
71 if t2 == 1 { hw("T2 PASS overlap shows the NEAR surface (red) -> the depth test actually occludes the far one\n" as *u8) } else { fails=fails+1; hw("T2 FAIL overlap not near-red\n" as *u8) }
72
73 // ---- NEG-CONTROL: painter's (depth OFF) -- order MUST matter ----
74 let fN1: *Image = nx_image_alloc(W, H, 3)
75 img_black(fN1)
76 depth_clear(zb, npix, BIG)
77 depth_tri_render(fN1, zb, 10, 118, 900, 118, 118, 900, 64, 18, 900, 0, 0, 255, 0) // far then near, NO depth
78 depth_tri_render(fN1, zb, 10, 10, 100, 118, 10, 100, 64, 110, 100, 255, 0, 0, 0)
79 let fN2: *Image = nx_image_alloc(W, H, 3)
80 img_black(fN2)
81 depth_clear(zb, npix, BIG)
82 depth_tri_render(fN2, zb, 10, 10, 100, 118, 10, 100, 64, 110, 100, 255, 0, 0, 0) // near then far, NO depth
83 depth_tri_render(fN2, zb, 10, 118, 900, 118, 118, 900, 64, 18, 900, 0, 0, 255, 0)
84 let dN: i64 = img_diff(fN1, fN2)
85 hw(" painter's order-diff bytes=" as *u8); pn(dN); hw("\n" as *u8)
86 var t3: i64 = 0
87 if dN > 0 { t3 = 1 }
88 if t3 == 1 { hw("T3 PASS neg-control: WITHOUT depth, draw order changes the frame -> the depth test in T1 was load-bearing\n" as *u8) } else { fails=fails+1; hw("T3 FAIL painter's frames identical (depth test not load-bearing)\n" as *u8) }
89
90 // artifact: viewable PPM of the depth-on frame
91 let hdr: *u8 = "P6\n128 128\n255\n" as *u8
92 var hn: i64 = 0
93 while hdr[hn] != (0 as u8) { hn = hn + 1 }
94 let fd: i64 = sys_openat_wr("knowledge/nx_depth_tri.ppm\x00" as *u8, 0x1a4)
95 sys_write(fd, hdr, hn)
96 sys_write(fd, fbA.pixels, npix * 3)
97 sys_close(fd)
98 hw("artifact -> knowledge/nx_depth_tri.ppm (depth-on overlap; center diamond = near red over far blue)\n" as *u8)
99 nx_png_write_rgb("knowledge/nx_depth_tri.png\x00" as *u8, fbA.pixels, W, H)
100 hw("artifact -> knowledge/nx_depth_tri.png (viewable)\n" as *u8)
101
102 if fails == 0 { hw("NX-DEPTH-TRI GREEN -- Z-buffer occlusion order-independent + load-bearing (3D visibility primitive; next: perspective-correct interp + scene depth in the window)\n" as *u8); sys_exit(0); return 0 }
103 hw("NX-DEPTH-TRI RED fails=" as *u8); pn(fails); hw("\n" as *u8)
104 sys_exit(1); return 1
105}