code wiki / _hdl_build / nx_shade.nx

nx_shade.nx source

↩ module page · 88 lines · 4072 B

1// nx_shade.nx -- P1 VISUALIZATION: RGB GOURAUD shading + TEXTURE mapping (barycentric), writing to a 2// packed-RGB framebuffer (fb[y*w+x] = R | G<<8 | B<<16) ready for nx_png.write_png. Extends the existing 3// single-channel shaded raster to full per-vertex RGB interpolation + per-vertex UV texture sampling. 4// Pure integer (Pineda edge functions). 100% sovereign. license_tier: ORIGINAL 5import "nx_syscalls.nx" 6 7func sh_rgb(r: i64, g: i64, b: i64) -> i64 { return (r & 0xff) | ((g & 0xff) << 8) | ((b & 0xff) << 16) } 8func sh_r(c: i64) -> i64 { return c & 0xff } 9func sh_g(c: i64) -> i64 { return (c >> 8) & 0xff } 10func sh_b(c: i64) -> i64 { return (c >> 16) & 0xff } 11 12// Pineda edge function: >0 left of edge AB through C (signed area*2). 13func sh_edge(ax: i64, ay: i64, bx: i64, by: i64, cx: i64, cy: i64) -> i64 { 14 return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax) 15} 16 17func sh_clear(fb: *i64, w: i64, h: i64, c: i64) -> i64 { var i: i64=0; while i < w*h { fb[i]=c; i=i+1 } return 0 } 18 19// GOURAUD: fill triangle, interpolate per-vertex RGB (ca/cb/cc packed) smoothly across pixels. 20func sh_tri_gouraud(fb: *i64, w: i64, h: i64, 21 x0: i64, y0: i64, ca: i64, x1: i64, y1: i64, cb: i64, x2: i64, y2: i64, cc: i64) -> i64 { 22 let area: i64 = sh_edge(x0, y0, x1, y1, x2, y2) 23 if area == 0 { return 0 - 1 } 24 var xmin: i64=x0; if x1<xmin {xmin=x1} if x2<xmin {xmin=x2} 25 var xmax: i64=x0; if x1>xmax {xmax=x1} if x2>xmax {xmax=x2} 26 var ymin: i64=y0; if y1<ymin {ymin=y1} if y2<ymin {ymin=y2} 27 var ymax: i64=y0; if y1>ymax {ymax=y1} if y2>ymax {ymax=y2} 28 if xmin<0 {xmin=0} if ymin<0 {ymin=0} 29 if xmax>=w {xmax=w-1} if ymax>=h {ymax=h-1} 30 var py: i64=ymin 31 while py<=ymax { 32 var px: i64=xmin 33 while px<=xmax { 34 let e0: i64 = sh_edge(x1,y1,x2,y2,px,py) 35 let e1: i64 = sh_edge(x2,y2,x0,y0,px,py) 36 let e2: i64 = sh_edge(x0,y0,x1,y1,px,py) 37 var inside: i64=0 38 if area>0 { if e0>=0 { if e1>=0 { if e2>=0 { inside=1 } } } } 39 if area<0 { if e0<=0 { if e1<=0 { if e2<=0 { inside=1 } } } } 40 if inside==1 { 41 let r: i64 = (e0*sh_r(ca) + e1*sh_r(cb) + e2*sh_r(cc)) / area 42 let g: i64 = (e0*sh_g(ca) + e1*sh_g(cb) + e2*sh_g(cc)) / area 43 let b: i64 = (e0*sh_b(ca) + e1*sh_b(cb) + e2*sh_b(cc)) / area 44 fb[py*w+px] = sh_rgb(r,g,b) 45 } 46 px=px+1 47 } 48 py=py+1 49 } 50 return 0 51} 52 53// TEXTURED: fill triangle, interpolate per-vertex UV (texel coords) + sample tex[v*ts+u] (packed RGB). 54func sh_tri_textured(fb: *i64, w: i64, h: i64, tex: *i64, ts: i64, 55 x0: i64, y0: i64, u0: i64, v0: i64, 56 x1: i64, y1: i64, u1: i64, v1: i64, 57 x2: i64, y2: i64, u2: i64, v2: i64) -> i64 { 58 let area: i64 = sh_edge(x0, y0, x1, y1, x2, y2) 59 if area == 0 { return 0 - 1 } 60 var xmin: i64=x0; if x1<xmin {xmin=x1} if x2<xmin {xmin=x2} 61 var xmax: i64=x0; if x1>xmax {xmax=x1} if x2>xmax {xmax=x2} 62 var ymin: i64=y0; if y1<ymin {ymin=y1} if y2<ymin {ymin=y2} 63 var ymax: i64=y0; if y1>ymax {ymax=y1} if y2>ymax {ymax=y2} 64 if xmin<0 {xmin=0} if ymin<0 {ymin=0} 65 if xmax>=w {xmax=w-1} if ymax>=h {ymax=h-1} 66 var py: i64=ymin 67 while py<=ymax { 68 var px: i64=xmin 69 while px<=xmax { 70 let e0: i64 = sh_edge(x1,y1,x2,y2,px,py) 71 let e1: i64 = sh_edge(x2,y2,x0,y0,px,py) 72 let e2: i64 = sh_edge(x0,y0,x1,y1,px,py) 73 var inside: i64=0 74 if area>0 { if e0>=0 { if e1>=0 { if e2>=0 { inside=1 } } } } 75 if area<0 { if e0<=0 { if e1<=0 { if e2<=0 { inside=1 } } } } 76 if inside==1 { 77 var u: i64 = (e0*u0 + e1*u1 + e2*u2) / area 78 var v: i64 = (e0*v0 + e1*v1 + e2*v2) / area 79 if u<0 {u=0} if u>=ts {u=ts-1} 80 if v<0 {v=0} if v>=ts {v=ts-1} 81 fb[py*w+px] = tex[v*ts+u] 82 } 83 px=px+1 84 } 85 py=py+1 86 } 87 return 0 88}