code wiki / _hdl_build / nx_gi_gate.nx

nx_gi_gate.nx source

↩ module page · 135 lines · 6168 B

1// nx_gi_gate.nx -- ★R3 of the Infinigen ladder: SINGLE-BOUNCE GI (irradiance cache). Verifies the PHYSICS 2// signatures, not just "pixels changed": 3// T1 SCOPE: sky pixels are BYTE-IDENTICAL with GI on (bounce light cannot reach the sky) + terrain changed 4// T2 ★SHADE-FILL: relative brightening in the darkest terrain quartile >> in the brightest (bounce dominates 5// where direct light is absent -- the defining GI behaviour) 6// T3 ★COLOURED bounce: in shade, green gains more than blue (sunlit GRASS bleeds green -- colour transport, 7// not a flat ambient boost) + panel knowledge/nx_gi_panel.png (off | on | amplified difference) 8// license_tier: ORIGINAL expect_exit: 0 9import "nx_syscalls.nx" 10import "nx_png.nx" 11import "nx_worldgen.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 b: *u8=sys_mmap(32) as *u8; var x: i64=v; var ng: i64=0; if x<0{ng=1;x=0-x} var i: i64=31; if x==0{b[i]=48 as u8;i=i-1} while x>0{b[i]=(48+x%10) as u8;x=x/10;i=i-1} if ng==1{b[i]=45 as u8;i=i-1} sys_write(1,(b as i64+i+1) as *u8,31-i); return 0 } 15func lum(px: i64) -> i64 { return (px&255) + ((px>>8)&255) + ((px>>16)&255) } 16 17func main() -> i64 { 18 hw("=== nx_gi_gate -- R3: single-bounce irradiance cache (colour-bleeding GI) ===\n" as *u8) 19 var fails: i64 = 0 20 let W: i64 = wg_w(); let H: i64 = wg_h(); let npx: i64 = W*H 21 let seed: i64 = 314 22 let cam: *i64 = sys_mmap(4*8) as *i64 23 let fbA: *i64 = sys_mmap(npx*8) as *i64 24 let fbB: *i64 = sys_mmap(npx*8) as *i64 25 let dep: *i64 = sys_mmap(npx*8) as *i64 26 let seg: *i64 = sys_mmap(npx*8) as *i64 27 let nrm: *i64 = sys_mmap(npx*8) as *i64 28 wg_set_gi(0) 29 worldgen_render_full(seed, 0, 0, cam, fbA, dep, seg, nrm) 30 wg_set_gi(1) 31 worldgen_render_full(seed, 0, 0, cam, fbB, dep, seg, nrm) 32 wg_set_gi(0) 33 34 // ---- T1 scope: sky identical, terrain changed ---- 35 var skydiff: i64 = 0 36 var terrdiff: i64 = 0 37 var i: i64 = 0 38 while i < npx { 39 if seg[i] == 0 { if fbA[i] != fbB[i] { skydiff = skydiff + 1 } } 40 if seg[i] == 1 { if fbA[i] != fbB[i] { terrdiff = terrdiff + 1 } } 41 i = i + 1 42 } 43 hw(" scope: sky-diff px="); pn(skydiff); hw(" terrain-diff px="); pn(terrdiff); hw("\n" as *u8) 44 var t1: i64 = 0 45 if skydiff == 0 { if terrdiff > 50000 { t1 = 1 } } 46 if t1 == 1 { hw("T1 PASS bounce reaches terrain, never the sky (scope is physical)\n" as *u8) } 47 else { fails=fails+1; hw("T1 FAIL scope\n" as *u8) } 48 49 // ---- T2 shade-fill: split terrain by A-luma quartiles; compare RELATIVE gains ---- 50 // luma histogram over terrain 51 let hist: *i64 = sys_mmap(800*8) as *i64 52 var nterr: i64 = 0 53 i = 0 54 while i < npx { 55 if seg[i] == 1 { let l: i64 = lum(fbA[i]); hist[l] = hist[l] + 1; nterr = nterr + 1 } 56 i = i + 1 57 } 58 var q1: i64 = 0 59 var acc: i64 = 0 60 var li: i64 = 0 61 while li < 766 { acc = acc + hist[li]; if q1 == 0 { if acc*4 >= nterr { q1 = li } } li = li + 1 } 62 var q3: i64 = 0 63 acc = 0 64 li = 0 65 while li < 766 { acc = acc + hist[li]; if q3 == 0 { if acc*4 >= nterr*3 { q3 = li } } li = li + 1 } 66 var shade_pm: i64 = 0 67 var shade_n: i64 = 0 68 var sun_pm: i64 = 0 69 var sun_n: i64 = 0 70 var shade_dg: i64 = 0 71 var shade_db: i64 = 0 72 i = 0 73 while i < npx { 74 if seg[i] == 1 { 75 let lA: i64 = lum(fbA[i]) 76 let dl: i64 = lum(fbB[i]) - lA 77 if lA <= q1 { 78 shade_pm = shade_pm + dl*1000/(lA+1) 79 shade_dg = shade_dg + ((fbB[i]>>8)&255) - ((fbA[i]>>8)&255) 80 shade_db = shade_db + ((fbB[i]>>16)&255) - ((fbA[i]>>16)&255) 81 shade_n = shade_n + 1 82 } 83 if lA >= q3 { 84 sun_pm = sun_pm + dl*1000/(lA+1) 85 sun_n = sun_n + 1 86 } 87 } 88 i = i + 1 89 } 90 let shade_rel: i64 = shade_pm/(shade_n+1) 91 let sun_rel: i64 = sun_pm/(sun_n+1) 92 hw(" shade-fill: q1="); pn(q1); hw(" q3="); pn(q3); hw(" relative gain shade="); pn(shade_rel); hw("pm sunlit="); pn(sun_rel); hw("pm\n" as *u8) 93 var t2: i64 = 0 94 if shade_rel > 60 { if shade_rel > sun_rel*2 { t2 = 1 } } 95 if t2 == 1 { hw("T2 PASS bounce FILLS SHADE (relative gain in shadow >> in sunlight -- the GI signature)\n" as *u8) } 96 else { fails=fails+1; hw("T2 FAIL shade-fill\n" as *u8) } 97 98 // ---- T3 coloured bounce + panel ---- 99 let dgm: i64 = shade_dg/(shade_n+1) 100 let dbm: i64 = shade_db/(shade_n+1) 101 hw(" colour transport in shade: mean dG="); pn(dgm); hw(" mean dB="); pn(dbm); hw("\n" as *u8) 102 var t3: i64 = 0 103 if dgm > dbm + 1 { if dgm > 2 { t3 = 1 } } 104 if t3 == 1 { hw("T3 PASS the bounce is GREEN (grass colour transported into shade, not a flat boost)\n" as *u8) } 105 else { fails=fails+1; hw("T3 FAIL colour\n" as *u8) } 106 107 // panel: off | on | amplified difference (x6 around mid-grey) 108 let GW: i64 = W*3 109 let gal: *i64 = sys_mmap(GW*H*8) as *i64 110 var y: i64 = 0 111 while y < H { 112 var x: i64 = 0 113 while x < W { 114 let pi: i64 = y*W+x 115 gal[y*GW+x] = fbA[pi] 116 gal[y*GW+W+x] = fbB[pi] 117 var dr: i64 = 128 + ((fbB[pi]&255) - (fbA[pi]&255))*6 118 var dg: i64 = 128 + (((fbB[pi]>>8)&255) - ((fbA[pi]>>8)&255))*6 119 var db: i64 = 128 + (((fbB[pi]>>16)&255) - ((fbA[pi]>>16)&255))*6 120 if dr<0{dr=0} if dr>255{dr=255} 121 if dg<0{dg=0} if dg>255{dg=255} 122 if db<0{db=0} if db>255{db=255} 123 gal[y*GW+W*2+x] = dr + dg*256 + db*65536 124 x = x + 1 125 } 126 y = y + 1 127 } 128 write_png(gal, GW, H, "knowledge/nx_gi_panel.png" as *u8) 129 hw("T4 panel -> knowledge/nx_gi_panel.png (GI off | GI on | difference x6)\n" as *u8) 130 131 if fails == 0 { hw("GI-GATE GREEN -- R3: single-bounce irradiance cache verified by physics (sky-scope + shade-fill + green colour transport). Honest label: one bounce, no bounce-visibility, coarse cells -- not path tracing\n" as *u8); sys_exit(0); return 0 } 132 hw("GI-GATE RED fails="); pn(fails); hw("\n" as *u8) 133 sys_exit(1) 134 return 1 135}