code wiki / _hdl_build / nx_phong_gate.nx

nx_phong_gate.nx source

↩ module page · 88 lines · 5207 B

1// nx_phong_gate.nx -- ★F3 BLINN-PHONG specular: prove a real specular HIGHLIGHT (a bright near-white spot where the 2// half-vector aligns with the normal) that flat/Lambert matte shading cannot produce. T1 shiny sphere has bright 3// highlight pixels, matte does not. T2 determinism. T3 gallery (sphere matte | sphere shiny | being shiny w/ skin sheen). 4// license_tier: ORIGINAL expect_exit: 0 5import "nx_syscalls.nx" 6import "nx_png.nx" 7import "nx_trimesh.nx" 8import "nx_isosurf.nx" 9import "nx_bodyatlas.nx" 10 11func hw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 12func 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 } 13func clearfb(fb: *i64, n: i64, c: i64) -> i64 { var i: i64=0; while i<n { fb[i]=c; i=i+1 } return 0 } 14// count near-white (specular) pixels: all channels high 15func bright(fb: *i64, n: i64) -> i64 { var c: i64=0; var i: i64=0; while i<n { let p: i64=fb[i]; if (p&255)>210 { if ((p>>8)&255)>210 { if ((p>>16)&255)>210 { c=c+1 } } } i=i+1 } return c } 16 17const BG: i64 = 24 + 26*256 + 34*65536 18const W: i64 = 300 19const H: i64 = 340 20 21func main() -> i64 { 22 hw("=== nx_phong_gate -- F3 Blinn-Phong specular highlight ===\n" as *u8) 23 var fails: i64 = 0 24 let npx: i64 = W*H 25 let fb: *i64 = sys_mmap(npx*8) as *i64 26 let zb: *i64 = sys_mmap(npx*8) as *i64 27 28 // a smooth sphere (mid-blue so a white highlight contrasts) 29 tm_reset() 30 tm_uvsphere(0, 0, 0, 150, 20, 28, 90 + 120*256 + 200*65536) 31 tm_compute_normals() 32 33 tm_set_spec(0) 34 clearfb(fb, npx, BG); trimesh_zclear(zb, npx); trimesh_render(fb, zb, W, H, 400, 0-300, 1400, 520, 1) 35 let matte: i64 = bright(fb, npx) 36 tm_set_spec(140) 37 clearfb(fb, npx, BG); trimesh_zclear(zb, npx); trimesh_render(fb, zb, W, H, 400, 0-300, 1400, 520, 1) 38 let shiny: i64 = bright(fb, npx) 39 hw(" sphere bright(near-white) pixels: matte="); pn(matte); hw(" shiny="); pn(shiny); hw("\n" as *u8) 40 var t1: i64 = 0 41 if matte < 40 { if shiny > 100 { t1 = 1 } } 42 if t1 == 1 { hw("T1 PASS SPECULAR: a real highlight appears with spec on ("); pn(shiny); hw(" bright px) that matte lacks ("); pn(matte); hw(")\n" as *u8) } 43 else { fails=fails+1; hw("T1 FAIL matte="); pn(matte); hw(" shiny="); pn(shiny); hw("\n" as *u8) } 44 45 // T2 determinism (spec on) 46 let f2: *i64 = sys_mmap(npx*8) as *i64 47 clearfb(f2, npx, BG); trimesh_zclear(zb, npx); trimesh_render(f2, zb, W, H, 400, 0-300, 1400, 520, 1) 48 var diff: i64 = 0; var i: i64 = 0 49 while i < npx { if f2[i]!=fb[i] { diff=diff+1 } i=i+1 } 50 var t2: i64 = 0 51 if diff == 0 { t2 = 1 } 52 if t2 == 1 { hw("T2 PASS deterministic\n" as *u8) } else { fails=fails+1; hw("T2 FAIL diff="); pn(diff); hw("\n" as *u8) } 53 54 // T3 gallery: sphere matte | sphere shiny | being skin w/ sheen 55 let GW: i64 = W*3 56 let gal: *i64 = sys_mmap(GW*H*8) as *i64 57 clearfb(gal, GW*H, BG) 58 let cell: *i64 = sys_mmap(npx*8) as *i64 59 // cell 0 matte, cell 1 shiny (sphere) 60 tm_reset(); tm_uvsphere(0,0,0,150,20,28, 90+120*256+200*65536); tm_compute_normals() 61 tm_set_spec(0); clearfb(cell,npx,BG); trimesh_zclear(zb,npx); trimesh_render(cell,zb,W,H,400,0-300,1400,520,1) 62 var y: i64=0 63 while y<H { var x: i64=0; while x<W { gal[y*GW+x]=cell[y*W+x]; x=x+1 } y=y+1 } 64 tm_set_spec(150); clearfb(cell,npx,BG); trimesh_zclear(zb,npx); trimesh_render(cell,zb,W,H,400,0-300,1400,520,1) 65 y=0 66 while y<H { var x: i64=0; while x<W { gal[y*GW+W+x]=cell[y*W+x]; x=x+1 } y=y+1 } 67 // cell 2: being skin mesh with a subtle sheen 68 atlas_build(0) 69 let GXb: i64=32; let GYb: i64=110; let GZb: i64=20; let GCb: i64=18 70 let grid: *i64 = sys_mmap((GXb+1)*(GYb+1)*(GZb+1)*8) as *i64 71 i=0 72 while i<=GXb { var jj: i64=0; while jj<=GYb { var k: i64=0; while k<=GZb { grid[(i*(GYb+1)+jj)*(GZb+1)+k]=ba_sdf(0-288+i*GCb, 0-990+jj*GCb, 0-180+k*GCb, 1); k=k+1 } jj=jj+1 } i=i+1 } 73 tm_reset(); surface_nets(grid, GXb,GYb,GZb, 0-288,0-990,0-180, GCb, 0, 216+172*256+152*65536) 74 let vp: *i64=sys_mmap(24) as *i64 75 i=0; let nv: i64=tm_nv() 76 while i<nv { tm_vpos(i,vp); let kk: i64=ba_nearest(vp[0],vp[1],vp[2],1); if kk>=0 { tm_vcol(i,ba_part_color(kk)) } else { tm_vcol(i,216+172*256+152*65536) } i=i+1 } 77 tm_set_spec(70) // subtle skin sheen 78 clearfb(cell,npx,BG); trimesh_zclear(zb,npx); trimesh_render(cell,zb,W,H,2400,0-260,2900,520,2) 79 y=0 80 while y<H { var x: i64=0; while x<W { gal[y*GW+2*W+x]=cell[y*W+x]; x=x+1 } y=y+1 } 81 write_png(gal, GW, H, "knowledge/nx_phong.png" as *u8) 82 hw("T3 gallery -> knowledge/nx_phong.png (sphere matte | sphere shiny | being w/ skin sheen)\n" as *u8) 83 84 if fails == 0 { hw("PHONG-GATE GREEN -- F3 Blinn-Phong specular: real highlights (opt-in tm_set_spec, zero-cost off), per-vertex + interpolated. Census Phong GAP->HAVE. Residual: per-material roughness/metalness (PBR) + textures.\n" as *u8); sys_exit(0); return 0 } 85 hw("PHONG-GATE RED fails="); pn(fails); hw("\n" as *u8) 86 sys_exit(1) 87 return 1 88}