2 RetroRay - integrated standalone vintage modeller/renderer
3 Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
19 #pragma warning (disable: 4101)
22 #if !defined(GOURAUD) && !defined(TEXMAP) && !defined(ZBUF)
26 void POLYFILL(struct pvertex *varr, int vnum)
28 int i, line, top, bot;
29 struct pvertex *vlast, *v, *vn, *tab;
30 int32_t x, y0, y1, dx, dy, slope, fx, fy;
32 gaw_pixel *fbptr, *pptr, color;
34 int32_t r, g, b, dr, dg, db, rslope, gslope, bslope;
36 int32_t a, da, aslope;
40 int32_t tu, tv, du, dv, uslope, vslope;
45 int32_t z, dz, zslope;
50 /* for flat shading we already know the color, so pack it once */
51 color = PACK_RGB(varr[0].r, varr[0].g, varr[0].b);
54 vlast = varr + vnum - 1;
55 top = pfill_fb.height;
58 for(i=0; i<vnum; i++) {
59 /* scan the edge between the current and next vertex */
63 if(vn->y == v->y) continue; // XXX ???
66 /* inrementing Y: left side */
69 /* decrementing Y: right side, flip vertices to trace bottom->up */
75 /* calculate edge slope */
78 slope = (dx << 8) / dy;
81 r = v->r << COLOR_SHIFT;
82 g = v->g << COLOR_SHIFT;
83 b = v->b << COLOR_SHIFT;
84 dr = (vn->r << COLOR_SHIFT) - r;
85 dg = (vn->g << COLOR_SHIFT) - g;
86 db = (vn->b << COLOR_SHIFT) - b;
87 rslope = (dr << 8) / dy;
88 gslope = (dg << 8) / dy;
89 bslope = (db << 8) / dy;
91 a = v->a << COLOR_SHIFT;
92 da = (vn->a << COLOR_SHIFT) - a;
93 aslope = (da << 8) / dy;
94 #endif /* BLEND_ALPHA */
101 uslope = (du << 8) / dy;
102 vslope = (dv << 8) / dy;
107 zslope = (dz << 8) / dy;
110 y0 = (v->y + 0x100) & 0xffffff00; /* start from the next scanline */
111 fy = y0 - v->y; /* fractional part before the next scanline */
112 fx = (fy * slope) >> 8; /* X adjust for the step to the next scanline */
113 x = v->x + fx; /* adjust X */
114 y1 = vn->y & 0xffffff00; /* last scanline of the edge <= vn->y */
116 /* also adjust other interpolated attributes */
118 r += (fy * rslope) >> 8;
119 g += (fy * gslope) >> 8;
120 b += (fy * bslope) >> 8;
122 a += (fy * aslope) >> 8;
123 #endif /* BLEND_ALPHA */
126 tu += (fy * uslope) >> 8;
127 tv += (fy * vslope) >> 8;
130 z += (fy * zslope) >> 8;
134 if(line < top) top = line;
135 if((y1 >> 8) > bot) bot = y1 >> 8;
137 if(line > 0) tab += line;
139 while(line <= (y1 >> 8) && line < pfill_fb.height) {
141 int val = x < 0 ? 0 : x >> 8;
142 tab->x = val < pfill_fb.width ? val : pfill_fb.width - 1;
149 #endif /* BLEND_ALPHA */
167 #endif /* BLEND_ALPHA */
181 if(bot >= pfill_fb.height) bot = pfill_fb.height - 1;
183 fbptr = pfill_fb.pixels + top * pfill_fb.width;
184 for(i=top; i<=bot; i++) {
186 len = right[i].x - start;
187 /* XXX we probably need more precision in left/right.x */
190 dx = len == 0 ? 256 : (len << 8);
200 rslope = (dr << 8) / dx;
201 gslope = (dg << 8) / dx;
202 bslope = (db << 8) / dx;
206 aslope = (da << 8) / dx;
207 #endif /* BLEND_ALPHA */
212 du = right[i].u - tu;
213 dv = right[i].v - tv;
214 uslope = (du << 8) / dx;
215 vslope = (dv << 8) / dx;
220 zslope = (dz << 8) / dx;
221 zptr = pfill_zbuf + i * pfill_fb.width + start;
224 pptr = fbptr + start;
226 #if defined(GOURAUD) || defined(TEXMAP) || defined(BLEND_ALPHA) || defined(BLEND_ADD)
232 #if defined(BLEND_ALPHA) || defined(BLEND_ADD)
245 /* ZFAIL: advance all attributes and continue */
266 /* we upped the color precision to while interpolating the
267 * edges, now drop the extra bits before packing
269 cr = r < 0 ? 0 : (r >> COLOR_SHIFT);
270 cg = g < 0 ? 0 : (g >> COLOR_SHIFT);
271 cb = b < 0 ? 0 : (b >> COLOR_SHIFT);
276 ca = a < 0 ? 0 : (a >> COLOR_SHIFT);
278 #endif /* BLEND_ALPHA */
281 tx = (tu >> (16 - pfill_tex.xshift)) & pfill_tex.xmask;
282 ty = (tv >> (16 - pfill_tex.yshift)) & pfill_tex.ymask;
283 texel = pfill_tex.pixels[(ty << pfill_tex.xshift) + tx];
289 /* for flat textured, cr,cg,cb would not be initialized */
296 #endif /* !GOURAUD */
297 /* This is not correct, should be /255, but it's much faster
298 * to shift by 8 (/256), and won't make a huge difference
300 cr = (cr * UNPACK_R(texel)) >> 8;
301 cg = (cg * UNPACK_G(texel)) >> 8;
302 cb = (cb * UNPACK_B(texel)) >> 8;
304 ca = (ca * UNPACK_A(texel)) >> 8;
309 inv_alpha = 255 - ca;
311 cr = (cr * ca + UNPACK_R(fbcol) * inv_alpha) >> 8;
312 cg = (cg * ca + UNPACK_G(fbcol) * inv_alpha) >> 8;
313 cb = (cb * ca + UNPACK_B(fbcol) * inv_alpha) >> 8;
314 #endif /* BLEND_ALPHA */
317 cr += UNPACK_R(fbcol);
318 cg += UNPACK_G(fbcol);
319 cb += UNPACK_B(fbcol);
320 #endif /* BLEND_ADD */
322 #ifdef DEBUG_OVERDRAW
323 *pptr++ += DEBUG_OVERDRAW;
325 #if defined(GOURAUD) || defined(TEXMAP) || defined(BLEND_ALPHA) || defined(BLEND_ADD)
326 if(cr >= 255) cr = 255;
327 if(cg >= 255) cg = 255;
328 if(cb >= 255) cb = 255;
329 color = PACK_RGB(cr, cg, cb);
334 fbptr += pfill_fb.width;