nx_textured_tri.nx source
↩ module page · 62 lines · 2543 B
1// nx_textured_tri.nx -- TEXTURED TRIANGLE rasterizer: barycentric edge-function fill + per-fragment UV
2// interpolation + nx_tex_sample (bilinear). This closes the "texture mapping" residual = an image mapped ONTO
3// a rasterized surface (real texture MAPPING, not just a standalone sampler). Pure integer, deterministic.
4// license_tier: ORIGINAL
5import "nx_syscalls.nx"
6import "nx_tex_sample.nx"
7
8// edge function (b-a) x (p-a): >0 when p is left of edge a->b (CCW)
9func tt_edge(ax: i64, ay: i64, bx: i64, by: i64, px: i64, py: i64) -> i64 {
10 return (bx - ax) * (py - ay) - (by - ay) * (px - ax)
11}
12
13// Rasterize a textured triangle into fb (RGB Image). UVs in Q10. A grayscale texel -> gray RGB pixel.
14func txtri_render(fb: *Image, tex: *Image, x0: i64, y0: i64, u0: i64, v0: i64, x1: i64, y1: i64, u1: i64, v1: i64, x2: i64, y2: i64, u2: i64, v2: i64) -> i64 {
15 var area: i64 = tt_edge(x0, y0, x1, y1, x2, y2)
16 if area == 0 { return 0 }
17 var sgn: i64 = 1
18 if area < 0 { sgn = 0 - 1; area = 0 - area }
19 // bounding box, clamped to the framebuffer
20 var minx: i64 = x0
21 if x1 < minx { minx = x1 }
22 if x2 < minx { minx = x2 }
23 var maxx: i64 = x0
24 if x1 > maxx { maxx = x1 }
25 if x2 > maxx { maxx = x2 }
26 var miny: i64 = y0
27 if y1 < miny { miny = y1 }
28 if y2 < miny { miny = y2 }
29 var maxy: i64 = y0
30 if y1 > maxy { maxy = y1 }
31 if y2 > maxy { maxy = y2 }
32 if minx < 0 { minx = 0 }
33 if miny < 0 { miny = 0 }
34 if maxx >= fb.width { maxx = fb.width - 1 }
35 if maxy >= fb.height { maxy = fb.height - 1 }
36 let px: *u8 = fb.pixels
37 var py: i64 = miny
38 while py <= maxy {
39 var pxi: i64 = minx
40 while pxi <= maxx {
41 let w0: i64 = tt_edge(x1, y1, x2, y2, pxi, py) * sgn
42 let w1: i64 = tt_edge(x2, y2, x0, y0, pxi, py) * sgn
43 let w2: i64 = tt_edge(x0, y0, x1, y1, pxi, py) * sgn
44 if w0 >= 0 {
45 if w1 >= 0 {
46 if w2 >= 0 {
47 let u: i64 = (w0 * u0 + w1 * u1 + w2 * u2) / area
48 let v: i64 = (w0 * v0 + w1 * v1 + w2 * v2) / area
49 let g: i64 = nx_txs_sample_bilinear(tex, u, v, NX_TXS_WRAP_CLAMP)
50 let off: i64 = py * fb.stride + pxi * 3
51 px[off] = g as u8
52 px[off + 1] = g as u8
53 px[off + 2] = g as u8
54 }
55 }
56 }
57 pxi = pxi + 1
58 }
59 py = py + 1
60 }
61 return 0
62}