fixed uninitialized color in flat untextured z-buffer rasterizer variant
[dosdemo] / src / 3dgfx / polytmpl.h
1 static uint32_t SCANEDGE(struct pvertex *v0, struct pvertex *v1, struct pvertex *edge)
2 {
3         int i;
4         int32_t x, dx, dy, slope;
5 #ifdef GOURAUD
6         int r, g, b, dr, dg, db;
7         int32_t rslope, gslope, bslope;
8 #ifdef BLEND_ALPHA
9         int32_t a, da, aslope;
10 #endif
11 #endif  /* GOURAUD */
12 #ifdef TEXMAP
13         int32_t u, v, du, dv, uslope, vslope;
14 #endif
15 #ifdef ZBUF
16         int32_t z, dz, zslope;
17 #endif
18         int32_t start_idx, end_idx;
19
20         if(v0->y > v1->y) {
21                 struct pvertex *tmp = v0;
22                 v0 = v1;
23                 v1 = tmp;
24         }
25
26         x = v0->x;
27         dy = v1->y - v0->y;
28         dx = v1->x - v0->x;
29         slope = (dx << 8) / dy;
30 #ifdef GOURAUD
31         r = (v0->r << COLOR_SHIFT);
32         g = (v0->g << COLOR_SHIFT);
33         b = (v0->b << COLOR_SHIFT);
34         dr = (v1->r << COLOR_SHIFT) - r;
35         dg = (v1->g << COLOR_SHIFT) - g;
36         db = (v1->b << COLOR_SHIFT) - b;
37         rslope = (dr << 8) / dy;
38         gslope = (dg << 8) / dy;
39         bslope = (db << 8) / dy;
40 #ifdef BLEND_ALPHA
41         a = (v0->a << COLOR_SHIFT);
42         da = (v1->a << COLOR_SHIFT) - a;
43         aslope = (da << 8) / dy;
44 #endif  /* BLEND_ALPHA */
45 #endif  /* GOURAUD */
46 #ifdef TEXMAP
47         u = v0->u;
48         v = v0->v;
49         du = v1->u - v0->u;
50         dv = v1->v - v0->v;
51         uslope = (du << 8) / dy;
52         vslope = (dv << 8) / dy;
53 #endif
54 #ifdef ZBUF
55         z = v0->z;
56         dz = v1->z - v0->z;
57         zslope = (dz << 8) / dy;
58 #endif
59
60         start_idx = v0->y >> 8;
61         end_idx = v1->y >> 8;
62
63         for(i=start_idx; i<end_idx; i++) {
64                 CHECKEDGE(i);
65                 edge[i].x = x;
66                 x += slope;
67 #ifdef GOURAUD
68                 /* we'll store the color in the edge tables with COLOR_SHIFT extra bits of precision */
69                 edge[i].r = r;
70                 edge[i].g = g;
71                 edge[i].b = b;
72                 r += rslope;
73                 g += gslope;
74                 b += bslope;
75 #ifdef BLEND_ALPHA
76                 edge[i].a = a;
77                 a += aslope;
78 #endif
79 #endif  /* GOURAUD */
80 #ifdef TEXMAP
81                 edge[i].u = u;
82                 edge[i].v = v;
83                 u += uslope;
84                 v += vslope;
85 #endif
86 #ifdef ZBUF
87                 edge[i].z = z;
88                 z += zslope;
89 #endif
90         }
91
92         return (uint32_t)start_idx | ((uint32_t)(end_idx - 1) << 16);
93 }
94
95 void POLYFILL(struct pvertex *pv, int nverts)
96 {
97         int i, winding;
98         int topidx = 0, botidx = 0, sltop = pfill_fb.height, slbot = 0;
99         g3d_pixel color;
100         /* the following variables are used for interpolating horizontally accros scanlines */
101 #if defined(GOURAUD) || defined(TEXMAP) || defined(ZBUF)
102         int mid;
103         int32_t dx, tmp;
104 #endif
105 #if !defined(GOURAUD) && !defined(TEXMAP)
106         /* flat version, just pack the color now */
107         color = G3D_PACK_RGB(pv[0].r, pv[0].g, pv[0].b);
108 #endif
109 #ifdef GOURAUD
110         int32_t r, g, b, dr, dg, db, rslope, gslope, bslope;
111 #ifdef BLEND_ALPHA
112         int32_t a, da, aslope;
113 #endif
114 #endif
115 #ifdef TEXMAP
116         int32_t u, v, du, dv, uslope, vslope;
117 #endif
118 #ifdef ZBUF
119         int32_t z, dz, zslope;
120 #endif
121
122         for(i=1; i<nverts; i++) {
123                 if(pv[i].y < pv[topidx].y) topidx = i;
124                 if(pv[i].y > pv[botidx].y) botidx = i;
125         }
126
127         winding = 0;
128         for(i=0; i<nverts; i++) {
129                 int next = NEXTIDX(i);
130                 winding += ((pv[next].x - pv[i].x) >> 4) * ((pv[next].y + pv[i].y) >> 4);
131         }
132
133         for(i=0; i<nverts; i++) {
134                 int next = NEXTIDX(i);
135                 int32_t y0 = pv[i].y;
136                 int32_t y1 = pv[next].y;
137
138                 if((y0 >> 8) == (y1 >> 8)) {
139                         /*if(y0 > y1) {*/
140                                 int i0, i1;
141                                 int idx = y0 >> 8;
142                                 if(pv[i].x < pv[next].x) {
143                                         i0 = i;
144                                         i1 = next;
145                                 } else {
146                                         i0 = next;
147                                         i1 = i;
148                                 }
149                                 CHECKEDGE(idx);
150                                 left[idx].x = pv[i0].x;
151                                 right[idx].x = pv[i1].x;
152 #ifdef GOURAUD
153                                 left[idx].r = pv[i0].r << COLOR_SHIFT;
154                                 left[idx].g = pv[i0].g << COLOR_SHIFT;
155                                 left[idx].b = pv[i0].b << COLOR_SHIFT;
156                                 right[idx].r = pv[i1].r << COLOR_SHIFT;
157                                 right[idx].g = pv[i1].g << COLOR_SHIFT;
158                                 right[idx].b = pv[i1].b << COLOR_SHIFT;
159 #ifdef BLEND_ALPHA
160                                 left[idx].a = pv[i0].a << COLOR_SHIFT;
161                                 right[idx].a = pv[i1].a << COLOR_SHIFT;
162 #endif  /* BLEND_ALPHA */
163 #endif
164 #ifdef TEXMAP
165                                 left[idx].u = pv[i0].u;
166                                 left[idx].v = pv[i0].v;
167                                 right[idx].u = pv[i1].u;
168                                 right[idx].v = pv[i1].v;
169 #endif
170 #ifdef ZBUF
171                                 left[idx].z = pv[i0].z;
172                                 right[idx].z = pv[i1].z;
173 #endif
174                                 CHECKEDGE(idx);
175                                 if(idx > slbot) slbot = idx;
176                                 if(idx < sltop) sltop = idx;
177                         /*}*/
178                 } else {
179                         struct pvertex *edge;
180                         uint32_t res, tmp;
181
182                         if(winding < 0) {
183                                 /* clockwise */
184                                 edge = y0 > y1 ? left : right;
185                         } else {
186                                 /* counter-clockwise */
187                                 edge = y0 > y1 ? right : left;
188                         }
189                         res = SCANEDGE(pv + i, pv + next, edge);
190                         tmp = (res >> 16) & 0xffff;
191                         if(tmp > slbot) slbot = tmp;
192                         if((tmp = res & 0xffff) < sltop) {
193                                 sltop = tmp;
194                         }
195                 }
196         }
197
198         /* calculate the slopes of all attributes across the largest span out
199          * of the three: middle, top, or bottom.
200          */
201 #ifndef HIGH_QUALITY
202 #if defined(GOURAUD) || defined(TEXMAP)
203         mid = (sltop + slbot) >> 1;
204         CHECKEDGE(sltop);
205         CHECKEDGE(slbot);
206         CHECKEDGE(mid);
207         dx = right[mid].x - left[mid].x;
208         if((tmp = right[sltop].x - left[sltop].x) > dx) {
209                 dx = tmp;
210                 mid = sltop;
211         }
212         if((tmp = right[slbot].x - left[slbot].x) > dx) {
213                 dx = tmp;
214                 mid = slbot;
215         }
216         if(!dx) dx = 256;       /* avoid division by zero */
217 #endif
218         CHECKEDGE(idx);
219 #ifdef GOURAUD
220         dr = right[mid].r - left[mid].r;
221         dg = right[mid].g - left[mid].g;
222         db = right[mid].b - left[mid].b;
223         rslope = (dr << 8) / dx;
224         gslope = (dg << 8) / dx;
225         bslope = (db << 8) / dx;
226 #ifdef BLEND_ALPHA
227         da = right[mid].a - left[mid].a;
228         aslope = (da << 8) / dx;
229 #endif  /* BLEND_ALPHA */
230 #endif
231 #ifdef TEXMAP
232         du = right[mid].u - left[mid].u;
233         dv = right[mid].v - left[mid].v;
234         uslope = (du << 8) / dx;
235         vslope = (dv << 8) / dx;
236 #endif
237 #ifdef ZBUF
238         dz = right[mid].z - left[mid].z;
239         zslope = (dz << 8) / dx;
240 #endif
241 #endif  /* !defined(HIGH_QUALITY) */
242
243         /* for each scanline ... */
244         for(i=sltop; i<=slbot; i++) {
245                 g3d_pixel *pixptr;
246                 int32_t x;
247 #ifdef ZBUF
248                 uint16_t *zptr;
249 #endif
250
251                 CHECKEDGE(i);
252                 x = left[i].x;
253                 pixptr = pfill_fb.pixels + i * pfill_fb.width + (x >> 8);
254
255 #ifdef GOURAUD
256                 r = left[i].r;
257                 g = left[i].g;
258                 b = left[i].b;
259 #ifdef BLEND_ALPHA
260                 a = left[i].a;
261 #endif  /* BLEND_ALPHA */
262 #endif
263 #ifdef TEXMAP
264                 u = left[i].u;
265                 v = left[i].v;
266 #endif
267 #ifdef ZBUF
268                 z = left[i].z;
269                 zptr = pfill_zbuf + i * pfill_fb.width + (x >> 8);
270 #endif
271                 CHECKEDGE(i);
272
273 #if defined(HIGH_QUALITY) && (defined(GOURAUD) || defined(TEXMAP) || defined(ZBUF))
274                 if(!(dx = right[i].x - left[i].x)) dx = 256;
275
276                 CHECKEDGE(i);
277 #ifdef GOURAUD
278                 dr = right[i].r - left[i].r;
279                 dg = right[i].g - left[i].g;
280                 db = right[i].b - left[i].b;
281                 rslope = (dr << 8) / dx;
282                 gslope = (dg << 8) / dx;
283                 bslope = (db << 8) / dx;
284 #ifdef BLEND_ALPHA
285                 da = right[i].a - left[i].a;
286                 aslope = (da << 8) / dx;
287 #endif  /* BLEND_ALPHA */
288 #endif  /* GOURAUD */
289 #ifdef TEXMAP
290                 du = right[i].u - left[i].u;
291                 dv = right[i].v - left[i].v;
292                 uslope = (du << 8) / dx;
293                 vslope = (dv << 8) / dx;
294 #endif
295 #ifdef ZBUF
296                 dz = right[i].z - left[i].z;
297                 zslope = (dz << 8) / dx;
298 #endif
299 #endif  /* HIGH_QUALITY */
300                 CHECKEDGE(i);
301
302                 /* go across the scanline interpolating if necessary */
303                 while(x <= right[i].x) {
304                         /*if(x == (180 << 8) && i == 174) {
305                                 asm("int $3");
306                         }*/
307 #if defined(GOURAUD) || defined(TEXMAP) || defined(BLEND_ALPHA) || defined(BLEND_ADD)
308                         int cr, cg, cb;
309 #endif
310 #if defined(BLEND_ALPHA) || defined(BLEND_ADD)
311                         g3d_pixel fbcol;
312 #endif
313 #ifdef BLEND_ALPHA
314                         int alpha, inv_alpha;
315 #endif
316
317 #ifdef ZBUF
318                         int32_t cz = z;
319                         z += zslope;
320
321                         if(z <= *zptr) {
322                                 *zptr++ = z;
323                         } else {
324 #ifdef GOURAUD
325                                 r += rslope;
326                                 g += gslope;
327                                 b += bslope;
328 #ifdef BLEND_ALPHA
329                                 a += aslope;
330 #endif
331 #endif
332 #ifdef TEXMAP
333                                 u += uslope;
334                                 v += vslope;
335 #endif
336                                 /* skip pixel */
337                                 pixptr++;
338                                 zptr++;
339                                 x += 256;
340                                 continue;
341                         }
342 #endif
343
344 #ifdef GOURAUD
345                         /* we upped the color precision to while interpolating the
346                          * edges, now drop the extra bits before packing
347                          */
348                         cr = r < 0 ? 0 : (r >> COLOR_SHIFT);
349                         cg = g < 0 ? 0 : (g >> COLOR_SHIFT);
350                         cb = b < 0 ? 0 : (b >> COLOR_SHIFT);
351                         r += rslope;
352                         g += gslope;
353                         b += bslope;
354 #ifdef BLEND_ALPHA
355                         a += aslope;
356 #else
357                         if(cr > 255) cr = 255;
358                         if(cg > 255) cg = 255;
359                         if(cb > 255) cb = 255;
360 #endif  /* BLEND_ALPHA */
361 #endif  /* GOURAUD */
362 #ifdef TEXMAP
363                         {
364                                 int tx = (u >> (16 - pfill_tex.xshift)) & pfill_tex.xmask;
365                                 int ty = (v >> (16 - pfill_tex.yshift)) & pfill_tex.ymask;
366                                 g3d_pixel texel = pfill_tex.pixels[(ty << pfill_tex.xshift) + tx];
367 #ifdef GOURAUD
368                                 /* This is not correct, should be /255, but it's much faster
369                                  * to shift by 8 (/256), and won't make a huge difference
370                                  */
371                                 cr = (cr * G3D_UNPACK_R(texel)) >> 8;
372                                 cg = (cg * G3D_UNPACK_G(texel)) >> 8;
373                                 cb = (cb * G3D_UNPACK_B(texel)) >> 8;
374 #else
375                                 cr = G3D_UNPACK_R(texel);
376                                 cg = G3D_UNPACK_G(texel);
377                                 cb = G3D_UNPACK_B(texel);
378 #endif
379                         }
380                         u += uslope;
381                         v += vslope;
382 #endif
383
384 #if defined(BLEND_ALPHA) || defined(BLEND_ADD)
385 #if !defined(GOURAUD) && !defined(TEXMAP)
386                         /* flat version: cr,cg,cb are uninitialized so far */
387                         cr = pv[0].r;
388                         cg = pv[0].g;
389                         cb = pv[0].b;
390 #endif
391                         fbcol = *pixptr;
392
393 #ifdef BLEND_ALPHA
394 #ifdef GOURAUD
395                         alpha = a >> COLOR_SHIFT;
396 #else
397                         alpha = pv[0].a;
398 #endif
399                         inv_alpha = 255 - alpha;
400                         cr = (cr * alpha + G3D_UNPACK_R(fbcol) * inv_alpha) >> 8;
401                         cg = (cg * alpha + G3D_UNPACK_G(fbcol) * inv_alpha) >> 8;
402                         cb = (cb * alpha + G3D_UNPACK_B(fbcol) * inv_alpha) >> 8;
403 #else   /* !BLEND_ALPHA (so BLEND_ADD) */
404                         cr += G3D_UNPACK_R(fbcol);
405                         cg += G3D_UNPACK_R(fbcol);
406                         cb += G3D_UNPACK_R(fbcol);
407 #endif
408                         if(cr > 255) cr = 255;
409                         if(cg > 255) cg = 255;
410                         if(cb > 255) cb = 255;
411 #endif  /* BLEND(ALPHA|ADD) */
412
413 #if defined(GOURAUD) || defined(TEXMAP) || defined(BLEND_ALPHA) || defined(BLEND_ADD)
414                         color = G3D_PACK_RGB(cr, cg, cb);
415 #endif
416
417 #ifdef DEBUG_OVERDRAW
418                         *pixptr++ += DEBUG_OVERDRAW;
419 #else
420                         *pixptr++ = color;
421 #endif
422                         x += 256;
423                 }
424         }
425 }
426