code wiki / _hdl_build / nx_raster3d_bilinear.nx

nx_raster3d_bilinear.nx source

↩ module page · 140 lines · 9513 B

1// nx_raster3d_bilinear.nx -- GATE: BILINEAR TEXTURE FILTERING, the SOTA texture-quality upgrade (smooth sampling vs 2// blocky nearest-neighbor). Blends the 4 nearest texels by the fractional (u,v) position, per color channel, all in 3// integer fixed-point (FBITS=8) => BIT-EXACT on any CPU, no GPU. Combined with the perspective-correct mapping 4// (nx_raster3d_tex) this is what real GPUs do. Nearest-neighbor is the low-quality baseline; bilinear is SOTA. 5// T1 bilinear KAT: sampling EXACTLY between a black and a white texel yields gray (~127) -- a blend nearest cannot make. 6// T2 weighting KAT: sampling 1/4 of the way yields ~64 (25% of 255) -- proves fractional weighting, not rounding. 7// T3 a bilinear-filtered textured quad produces INTERMEDIATE colors (smooth) that nearest-neighbor would never emit. 8// T4 (EXCEED) determinism -- bit-identical across runs. 9// expect_exit: 0 Sovereign: nx_syscalls. NEVER-BRICK: software render, writes 0 GPU firmware. 10import "nx_syscalls.nx" 11const INVZ_MAGIC_5381: i64 = 5381 12 13func g_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 14func g_pn(v: i64) -> i64 { let b: *u8=sys_mmap(28); var x: i64=v; if x<0{b[0]=45;sys_write(1,b,1);x=0-x} if x==0{b[0]=48;sys_write(1,b,1);return 0} var d: i64=0; var y: i64=x; while y>0{d=d+1;y=y/10} var i: i64=d-1; y=x; while i>=0{b[i]=(48+(y%10)) as u8;y=y/10;i=i-1} sys_write(1,b,d); return 0 } 15func ck(name: *u8, c: i64) -> i64 { if c==1 { g_puts(" PASS " as *u8) } else { g_puts(" FAIL " as *u8) } g_puts(name); g_puts("\n" as *u8); return c } 16 17const W: i64 = 64 18const H: i64 = 64 19const ZINF: i64 = 1000000000 20const INVZ_Q: i64 = 1048576 // 2^20 inverse-depth scale (perspective) 21const FBITS: i64 = 8 // texture-coord fractional bits 22const FONE: i64 = 256 // 1.0 in FBITS 23 24func fb_clear(fb: *i64, zb: *i64) -> i64 { var i: i64=0; while i<W*H { fb[i]=0; zb[i]=ZINF; i=i+1 } return 0 } 25func cksum(fb: *i64) -> i64 { var h: i64=INVZ_MAGIC_5381; var i: i64=0; while i<W*H { h=((h<<5)+h)+fb[i]; i=i+1 } return h } 26func edge(ax: i64, ay: i64, bx: i64, by: i64, px: i64, py: i64) -> i64 { return (bx-ax)*(py-ay) - (by-ay)*(px-ax) } 27func chan(c: i64, sh: i64) -> i64 { return (c>>sh)&255 } 28 29// BILINEAR sample: blend the 4 texels around (ufp,vfp) [FBITS fixed-point] by the fractional position, per channel. 30func bilinear_sample(tex: *i64, tw: i64, th: i64, ufp: i64, vfp: i64) -> i64 { 31 var ui: i64 = ufp>>FBITS; var vi: i64 = vfp>>FBITS 32 let uf: i64 = ufp&(FONE-1); let vf: i64 = vfp&(FONE-1) 33 if ui<0 {ui=0} if ui>tw-1 {ui=tw-1} 34 if vi<0 {vi=0} if vi>th-1 {vi=th-1} 35 var ui1: i64=ui+1; if ui1>tw-1 {ui1=tw-1} 36 var vi1: i64=vi+1; if vi1>th-1 {vi1=th-1} 37 let c00: i64=tex[vi*tw+ui]; let c10: i64=tex[vi*tw+ui1]; let c01: i64=tex[vi1*tw+ui]; let c11: i64=tex[vi1*tw+ui1] 38 var out: i64=0; var s: i64=16 39 while s>=0 { 40 let a: i64=chan(c00,s); let b: i64=chan(c10,s); let c: i64=chan(c01,s); let dd: i64=chan(c11,s) 41 let top: i64 = a*(FONE-uf) + b*uf // blend along u (top row) 42 let bot: i64 = c*(FONE-uf) + dd*uf // blend along u (bottom row) 43 let val: i64 = (top*(FONE-vf) + bot*vf) >> (FBITS+FBITS) // blend along v; back to 0..255 44 out = out | (val<<s) 45 s=s-8 46 } 47 return out 48} 49 50// perspective-correct + BILINEAR textured triangle: recover (u,v) in fixed-point, bilinear-sample. 51func draw_tri_bl(fb: *i64, zb: *i64, x0: i64, y0: i64, z0: i64, u0: i64, v0: i64, x1: i64, y1: i64, z1: i64, u1: i64, v1: i64, x2: i64, y2: i64, z2: i64, u2: i64, v2: i64, tex: *i64, texw: i64, texh: i64) -> i64 { 52 let area0: i64 = edge(x0,y0,x1,y1,x2,y2) 53 if area0==0 { return 0 } 54 let iz0: i64=INVZ_Q/z0; let iz1: i64=INVZ_Q/z1; let iz2: i64=INVZ_Q/z2 55 let uz0: i64=u0*iz0; let uz1: i64=u1*iz1; let uz2: i64=u2*iz2 56 let sz0: i64=v0*iz0; let sz1: i64=v1*iz1; let sz2: i64=v2*iz2 57 var minx: i64=x0; if x1<minx {minx=x1} if x2<minx {minx=x2} if minx<0 {minx=0} 58 var maxx: i64=x0; if x1>maxx {maxx=x1} if x2>maxx {maxx=x2} if maxx>W-1 {maxx=W-1} 59 var miny: i64=y0; if y1<miny {miny=y1} if y2<miny {miny=y2} if miny<0 {miny=0} 60 var maxy: i64=y0; if y1>maxy {maxy=y1} if y2>maxy {maxy=y2} if maxy>H-1 {maxy=H-1} 61 var py: i64=miny 62 while py<=maxy { 63 var px: i64=minx 64 while px<=maxx { 65 let w0: i64=edge(x1,y1,x2,y2,px,py); let w1: i64=edge(x2,y2,x0,y0,px,py); let w2: i64=edge(x0,y0,x1,y1,px,py) 66 var inside: i64=0 67 if area0>0 { if w0>=0 { if w1>=0 { if w2>=0 { inside=1 } } } } 68 else { if w0<=0 { if w1<=0 { if w2<=0 { inside=1 } } } } 69 if inside==1 { 70 var aw0: i64=w0; var aw1: i64=w1; var aw2: i64=w2; var aar: i64=area0 71 if area0<0 { aw0=0-w0; aw1=0-w1; aw2=0-w2; aar=0-area0 } 72 let den: i64 = aw0*iz0 + aw1*iz1 + aw2*iz2 73 if den!=0 { 74 let ufp: i64 = ((aw0*uz0 + aw1*uz1 + aw2*uz2) << FBITS) / den 75 let vfp: i64 = ((aw0*sz0 + aw1*sz1 + aw2*sz2) << FBITS) / den 76 let depth: i64 = (aw0*z0 + aw1*z1 + aw2*z2)/aar 77 let idx: i64 = py*W+px 78 if depth < zb[idx] { zb[idx]=depth; fb[idx]=bilinear_sample(tex, texw, texh, ufp, vfp) } 79 } 80 } 81 px=px+1 82 } 83 py=py+1 84 } 85 return 0 86} 87 88func main() -> i64 { 89 g_puts("nx_raster3d_bilinear (SOVEREIGN integer bilinear texture filtering: the SOTA smooth-sampling upgrade)\n" as *u8) 90 var pass: i64=0; var total: i64=0 91 let tex: *i64=sys_mmap(64*8) as *i64 92 var i: i64=0; while i<64 { tex[i]=0; i=i+1 } 93 tex[0]=0x000000; tex[1]=0xFFFFFF // 4x4 texture: (0,0)=black, (1,0)=white 94 95 // T1: exactly-between (u=0.5) -> gray ~127 per channel. nearest-neighbor could only give 0 or 255. 96 let mid: i64 = bilinear_sample(tex, 4, 4, FONE/2, 0) 97 let midR: i64 = (mid>>16)&255 98 var t1: i64=0; if midR>=126 { if midR<=129 { t1=1 } } 99 g_puts(" T1 sample halfway black|white: color="); g_pn(mid); g_puts(" R="); g_pn(midR); g_puts(" (blend ~127; nearest could only be 0 or 255)\n" as *u8) 100 pass=pass+ck("T1: BILINEAR blends -- halfway between black and white samples gray (~127), impossible for nearest-neighbor" as *u8, t1); total=total+1 101 102 // T2: quarter of the way (u=0.25) -> ~64 (25% of 255). proves fractional WEIGHTING. 103 let q: i64 = bilinear_sample(tex, 4, 4, FONE/4, 0) 104 let qR: i64 = (q>>16)&255 105 var t2: i64=0; if qR>=60 { if qR<=68 { t2=1 } } 106 g_puts(" T2 sample 1/4 toward white: R="); g_pn(qR); g_puts(" (~64 = 25% of 255 -- fractional weighting)\n" as *u8) 107 pass=pass+ck("T2: BILINEAR weighting is fractional -- 1/4 position gives ~1/4 intensity (not a rounded step)" as *u8, t2); total=total+1 108 109 // T3: render a checker quad with bilinear -> INTERMEDIATE colors appear (smooth edges) that nearest never emits. 110 let ck2: *i64=sys_mmap(256*8) as *i64 111 var tj: i64=0; while tj<256 { let cu: i64=tj%16; let cv: i64=tj/16; if (((cu>>1)^(cv>>1))&1)==0 { ck2[tj]=0xFFFFFF } else { ck2[tj]=0x000000 } tj=tj+1 } 112 let fb: *i64=sys_mmap(W*H*8) as *i64; let zb: *i64=sys_mmap(W*H*8) as *i64 113 fb_clear(fb, zb) 114 draw_tri_bl(fb, zb, 8,8,220, 0,0, 55,10,320, 15,0, 8,55,220, 0,15, ck2, 16, 16) 115 draw_tri_bl(fb, zb, 55,10,320, 15,0, 55,55,320, 15,15, 8,55,220, 0,15, ck2, 16, 16) 116 var inter: i64=0; var filled: i64=0; var pi: i64=0 117 while pi<W*H { let c: i64=fb[pi]; if c!=0 { filled=filled+1; let r: i64=(c>>16)&255; if r>16 { if r<239 { inter=inter+1 } } } pi=pi+1 } 118 var t3: i64=0; if filled>200 { if inter>20 { t3=1 } } 119 g_puts(" T3 bilinear checker quad: filled="); g_pn(filled); g_puts(" intermediate-shade pixels="); g_pn(inter); g_puts(" (nearest-neighbor would emit 0)\n" as *u8) 120 pass=pass+ck("T3: a bilinear-filtered quad emits INTERMEDIATE shades at texel boundaries (smooth; nearest = hard steps)" as *u8, t3); total=total+1 121 122 // T4 (EXCEED): determinism 123 let fb2: *i64=sys_mmap(W*H*8) as *i64; let zb2: *i64=sys_mmap(W*H*8) as *i64 124 fb_clear(fb2, zb2) 125 draw_tri_bl(fb2, zb2, 8,8,220, 0,0, 55,10,320, 15,0, 8,55,220, 0,15, ck2, 16, 16) 126 draw_tri_bl(fb2, zb2, 55,10,320, 15,0, 55,55,320, 15,15, 8,55,220, 0,15, ck2, 16, 16) 127 let h1: i64=cksum(fb); let h2: i64=cksum(fb2) 128 var t4: i64=0; if h1==h2 { t4=1 } 129 g_puts(" T4 determinism: run1="); g_pn(h1); g_puts(" run2="); g_pn(h2); g_puts("\n" as *u8) 130 pass=pass+ck("T4 (EXCEED): bilinear render is BIT-IDENTICAL across runs (integer-deterministic, any CPU, no GPU)" as *u8, t4); total=total+1 131 132 var okall: i64=0; if pass==total { okall=1 } 133 g_puts("---- nx_raster3d_bilinear: passed "); g_pn(pass); g_puts(" / "); g_pn(total); g_puts(" ----\n" as *u8) 134 if okall==1 { 135 let logf: i64=sys_openat_append("knowledge/status/raster3d_bilinear.log" as *u8, 420) 136 if logf>=0 { let z: i64=sys_write(logf,"NXRASTER3DBILINEAR GREEN: integer bilinear texture filtering -- 4-texel fractional blend per channel; KAT-proven (halfway=gray, quarter=~64) beyond nearest-neighbor; smooth quad render, bit-deterministic\n" as *u8,192); sys_close(logf) } 137 g_puts("verdict=GREEN (sovereign integer bilinear texture filtering: 4-texel fractional blend, KAT-proven smoothing beyond nearest, bit-deterministic; texture quality now SOTA)\n" as *u8); sys_exit(0); return 0 138 } 139 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 140}