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}