X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=blobdiff_plain;f=src%2Fpolytmpl.h;h=0f50b7d68c5168ad276dd5b1386e41448dcf9bc2;hp=79660ef0cb374eb990260937179390c61eb4d885;hb=d956a9d9273eebfacfda58cb3bafff017269d5dc;hpb=07ce18b114e1e01b2a85a04079128f3eb754de1d diff --git a/src/polytmpl.h b/src/polytmpl.h index 79660ef..0f50b7d 100644 --- a/src/polytmpl.h +++ b/src/polytmpl.h @@ -5,7 +5,10 @@ static uint32_t SCANEDGE(struct pvertex *v0, struct pvertex *v1, struct pvertex #ifdef GOURAUD int r, g, b, dr, dg, db; int32_t rslope, gslope, bslope; +#ifdef BLEND + int32_t a, da, aslope; #endif +#endif /* GOURAUD */ #ifdef TEXMAP int32_t u, v, du, dv, uslope, vslope; #endif @@ -22,16 +25,21 @@ static uint32_t SCANEDGE(struct pvertex *v0, struct pvertex *v1, struct pvertex dx = v1->x - v0->x; slope = (dx << 8) / dy; #ifdef GOURAUD - r = (v0->r << 8); - g = (v0->g << 8); - b = (v0->b << 8); - dr = (v1->r << 8) - r; - dg = (v1->g << 8) - g; - db = (v1->b << 8) - b; + r = (v0->r << COLOR_SHIFT); + g = (v0->g << COLOR_SHIFT); + b = (v0->b << COLOR_SHIFT); + dr = (v1->r << COLOR_SHIFT) - r; + dg = (v1->g << COLOR_SHIFT) - g; + db = (v1->b << COLOR_SHIFT) - b; rslope = (dr << 8) / dy; gslope = (dg << 8) / dy; bslope = (db << 8) / dy; -#endif +#ifdef BLEND + a = (v0->a << COLOR_SHIFT); + da = (v1->a << COLOR_SHIFT) - a; + aslope = (da << 8) / dy; +#endif /* BLEND */ +#endif /* GOURAUD */ #ifdef TEXMAP u = v0->u; v = v0->v; @@ -48,14 +56,18 @@ static uint32_t SCANEDGE(struct pvertex *v0, struct pvertex *v1, struct pvertex edge[i].x = x; x += slope; #ifdef GOURAUD - /* we'll store the color in the edge tables with 8 extra bits of precision */ + /* we'll store the color in the edge tables with COLOR_SHIFT extra bits of precision */ edge[i].r = r; edge[i].g = g; edge[i].b = b; r += rslope; g += gslope; b += bslope; +#ifdef BLEND + edge[i].a = a; + a += aslope; #endif +#endif /* GOURAUD */ #ifdef TEXMAP edge[i].u = u; edge[i].v = v; @@ -69,20 +81,23 @@ static uint32_t SCANEDGE(struct pvertex *v0, struct pvertex *v1, struct pvertex void POLYFILL(struct pvertex *pv, int nverts) { - int i; + int i, winding; int topidx = 0, botidx = 0, sltop = pfill_fb.height, slbot = 0; struct pvertex *left, *right; - uint16_t color; + g3d_pixel color; /* the following variables are used for interpolating horizontally accros scanlines */ #if defined(GOURAUD) || defined(TEXMAP) - /*int mid;*/ - int32_t dx/*, tmp*/; + int mid; + int32_t dx, tmp; #else /* flat version, just pack the color now */ - color = PACK_RGB16(pv[0].r, pv[0].g, pv[0].b); + color = G3D_PACK_RGB(pv[0].r, pv[0].g, pv[0].b); #endif #ifdef GOURAUD int32_t r, g, b, dr, dg, db, rslope, gslope, bslope; +#ifdef BLEND + int32_t a, da, aslope; +#endif #endif #ifdef TEXMAP int32_t u, v, du, dv, uslope, vslope; @@ -93,8 +108,15 @@ void POLYFILL(struct pvertex *pv, int nverts) if(pv[i].y > pv[botidx].y) botidx = i; } - left = alloca(pfill_fb.height * sizeof *left); - right = alloca(pfill_fb.height * sizeof *right); + winding = 0; + for(i=0; i> 4) * ((pv[next].y + pv[i].y) >> 4); + } + + /* +1 to avoid crashing due to off-by-one rounding errors in the rasterization */ + left = alloca((pfill_fb.height + 1) * sizeof *left); + right = alloca((pfill_fb.height + 1) * sizeof *right); for(i=0; i> 8) == (y1 >> 8)) { - if(y0 > y1) { + /*if(y0 > y1) {*/ + int i0, i1; int idx = y0 >> 8; - left[idx].x = pv[i].x < pv[next].x ? pv[i].x : pv[next].x; - right[idx].x = pv[i].x < pv[next].x ? pv[next].x : pv[i].x; - } + if(pv[i].x < pv[next].x) { + i0 = i; + i1 = next; + } else { + i0 = next; + i1 = i; + } + left[idx].x = pv[i0].x; + right[idx].x = pv[i1].x; +#ifdef GOURAUD + left[idx].r = pv[i0].r << COLOR_SHIFT; + left[idx].g = pv[i0].g << COLOR_SHIFT; + left[idx].b = pv[i0].b << COLOR_SHIFT; + right[idx].r = pv[i1].r << COLOR_SHIFT; + right[idx].g = pv[i1].g << COLOR_SHIFT; + right[idx].b = pv[i1].b << COLOR_SHIFT; +#ifdef BLEND + left[idx].a = pv[i0].a << COLOR_SHIFT; + right[idx].a = pv[i1].a << COLOR_SHIFT; +#endif /* BLEND */ +#endif +#ifdef TEXMAP + left[idx].u = pv[i0].u; + left[idx].v = pv[i0].v; + right[idx].u = pv[i1].u; + right[idx].v = pv[i1].v; +#endif + if(idx > slbot) slbot = idx; + if(idx < sltop) sltop = idx; + /*}*/ } else { - struct pvertex *edge = y0 > y1 ? left : right; - uint32_t res = SCANEDGE(pv + i, pv + next, edge); - uint32_t tmp = (res >> 16) & 0xffff; + struct pvertex *edge; + uint32_t res, tmp; + + if(winding < 0) { + /* clockwise */ + edge = y0 > y1 ? left : right; + } else { + /* counter-clockwise */ + edge = y0 > y1 ? right : left; + } + res = SCANEDGE(pv + i, pv + next, edge); + tmp = (res >> 16) & 0xffff; if(tmp > slbot) slbot = tmp; if((tmp = res & 0xffff) < sltop) { sltop = tmp; @@ -118,8 +177,10 @@ void POLYFILL(struct pvertex *pv, int nverts) } } - /* find the mid-point and calculate slopes for all attributes */ -#if 0 + /* calculate the slopes of all attributes across the largest span out + * of the three: middle, top, or bottom. + */ +#ifndef HIGH_QUALITY #if defined(GOURAUD) || defined(TEXMAP) mid = (sltop + slbot) >> 1; dx = right[mid].x - left[mid].x; @@ -131,9 +192,7 @@ void POLYFILL(struct pvertex *pv, int nverts) dx = tmp; mid = slbot; } - if(!dx) { - dx = 256; /* 1 */ - } + if(!dx) dx = 256; /* avoid division by zero */ #endif #ifdef GOURAUD dr = right[mid].r - left[mid].r; @@ -142,6 +201,10 @@ void POLYFILL(struct pvertex *pv, int nverts) rslope = (dr << 8) / dx; gslope = (dg << 8) / dx; bslope = (db << 8) / dx; +#ifdef BLEND + da = right[mid].a - left[mid].a; + aslope = (da << 8) / dx; +#endif /* BLEND */ #endif #ifdef TEXMAP du = right[mid].u - left[mid].u; @@ -149,72 +212,125 @@ void POLYFILL(struct pvertex *pv, int nverts) uslope = (du << 8) / dx; vslope = (dv << 8) / dx; #endif -#endif /* 0 */ +#endif /* !defined(HIGH_QUALITY) */ + /* for each scanline ... */ for(i=sltop; i<=slbot; i++) { - uint16_t *pixptr; + g3d_pixel *pixptr; int32_t x; x = left[i].x; pixptr = pfill_fb.pixels + i * pfill_fb.width + (x >> 8); -#if defined(GOURAUD) || defined(TEXMAP) - if(!(dx = right[i].x - left[i].x)) dx = 256; /* 1 */ -#endif #ifdef GOURAUD r = left[i].r; g = left[i].g; b = left[i].b; +#ifdef BLEND + a = left[i].a; +#endif /* BLEND */ +#endif +#ifdef TEXMAP + u = left[i].u; + v = left[i].v; +#endif + +#if defined(HIGH_QUALITY) && (defined(GOURAUD) || defined(TEXMAP)) + if(!(dx = right[i].x - left[i].x)) dx = 256; + +#ifdef GOURAUD dr = right[i].r - left[i].r; dg = right[i].g - left[i].g; db = right[i].b - left[i].b; rslope = (dr << 8) / dx; gslope = (dg << 8) / dx; bslope = (db << 8) / dx; -#endif +#ifdef BLEND + da = right[i].a - left[i].a; + aslope = (da << 8) / dx; +#endif /* BLEND */ +#endif /* GOURAUD */ #ifdef TEXMAP - u = left[i].u; - v = left[i].v; du = right[i].u - left[i].u; dv = right[i].v - left[i].v; uslope = (du << 8) / dx; vslope = (dv << 8) / dx; #endif +#endif /* HIGH_QUALITY */ + /* go across the scanline interpolating if necessary */ while(x <= right[i].x) { -#if defined(GOURAUD) || defined(TEXMAP) +#if defined(GOURAUD) || defined(TEXMAP) || defined(BLEND) int cr, cg, cb; #endif +#ifdef BLEND + g3d_pixel fbcol; + int alpha, inv_alpha; +#endif #ifdef GOURAUD - /* drop the extra 8 bits when packing */ - cr = r >> 8; - cg = g >> 8; - cb = b >> 8; + /* we upped the color precision to while interpolating the + * edges, now drop the extra bits before packing + */ + cr = r < 0 ? 0 : (r >> COLOR_SHIFT); + cg = g < 0 ? 0 : (g >> COLOR_SHIFT); + cb = b < 0 ? 0 : (b >> COLOR_SHIFT); r += rslope; g += gslope; b += bslope; -#endif +#ifdef BLEND + a += aslope; +#else + if(cr > 255) cr = 255; + if(cg > 255) cg = 255; + if(cb > 255) cb = 255; +#endif /* BLEND */ +#endif /* GOURAUD */ #ifdef TEXMAP { int tx = (u >> (16 - pfill_tex.xshift)) & pfill_tex.xmask; int ty = (v >> (16 - pfill_tex.yshift)) & pfill_tex.ymask; - uint16_t texel = pfill_tex.pixels[(ty << pfill_tex.xshift) + tx]; + g3d_pixel texel = pfill_tex.pixels[(ty << pfill_tex.xshift) + tx]; #ifdef GOURAUD - /* XXX this is not correct, should be /255, but it might not make a huge difference */ - cr = (cr * UNPACK_R16(texel)) >> 8; - cg = (cg * UNPACK_G16(texel)) >> 8; - cb = (cb * UNPACK_B16(texel)) >> 8; + /* This is not correct, should be /255, but it's much faster + * to shift by 8 (/256), and won't make a huge difference + */ + cr = (cr * G3D_UNPACK_R(texel)) >> 8; + cg = (cg * G3D_UNPACK_G(texel)) >> 8; + cb = (cb * G3D_UNPACK_B(texel)) >> 8; #else - cr = UNPACK_R16(texel); - cg = UNPACK_G16(texel); - cb = UNPACK_B16(texel); + cr = G3D_UNPACK_R(texel); + cg = G3D_UNPACK_G(texel); + cb = G3D_UNPACK_B(texel); #endif } u += uslope; v += vslope; #endif -#if defined(GOURAUD) || defined(TEXMAP) - color = PACK_RGB16(cr, cg, cb); + +#ifdef BLEND +#if !defined(GOURAUD) && !defined(TEXMAP) + /* flat version: cr,cg,cb are uninitialized so far */ + cr = pv[0].r; + cg = pv[0].g; + cb = pv[0].b; +#endif +#ifdef GOURAUD + alpha = a >> COLOR_SHIFT; +#else + alpha = pv[0].a; +#endif + fbcol = *pixptr; + inv_alpha = 255 - alpha; + cr = (cr * alpha + G3D_UNPACK_R(fbcol) * inv_alpha) >> 8; + cg = (cg * alpha + G3D_UNPACK_G(fbcol) * inv_alpha) >> 8; + cb = (cb * alpha + G3D_UNPACK_B(fbcol) * inv_alpha) >> 8; + if(cr > 255) cr = 255; + if(cg > 255) cg = 255; + if(cb > 255) cb = 255; +#endif /* BLEND */ + +#if defined(GOURAUD) || defined(TEXMAP) || defined(BLEND) + color = G3D_PACK_RGB(cr, cg, cb); #endif #ifdef DEBUG_OVERDRAW