X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=blobdiff_plain;f=src%2Fpolytmpl.h;h=2147666938fbc7eadce60a753c7dc57e48621ea7;hp=2021b3bd56fbbedf9325d68ab390e73217776c48;hb=e0a94da7c7b657cebbb9e07c861054540706d5da;hpb=6218ea71a2a175dca5bf88ca7922e97f42f85e69 diff --git a/src/polytmpl.h b/src/polytmpl.h index 2021b3b..2147666 100644 --- a/src/polytmpl.h +++ b/src/polytmpl.h @@ -22,12 +22,12 @@ 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; @@ -48,7 +48,7 @@ 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; @@ -70,7 +70,7 @@ static uint32_t SCANEDGE(struct pvertex *v0, struct pvertex *v1, struct pvertex void POLYFILL(struct pvertex *pv, int nverts) { int i; - int topidx = 0, botidx = 0, sltop = pimg_fb.height, slbot = 0; + int topidx = 0, botidx = 0, sltop = pfill_fb.height, slbot = 0; struct pvertex *left, *right; uint16_t color; /* the following variables are used for interpolating horizontally accros scanlines */ @@ -93,8 +93,15 @@ void POLYFILL(struct pvertex *pv, int nverts) if(pv[i].y > pv[botidx].y) botidx = i; } - left = alloca(pimg_fb.height * sizeof *left); - right = alloca(pimg_fb.height * sizeof *right); + int winding = 0; + for(i=0; i> 8) * ((pv[next].y + pv[i].y) >> 8); + } + + /* +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; +#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) { + edge = y0 > y1 ? left : right; + } else { + 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 +156,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 +171,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; @@ -149,22 +187,30 @@ 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; int32_t x; x = left[i].x; - pixptr = pimg_fb.pixels + i * pimg_fb.width + (x >> 8); + 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; +#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; @@ -173,30 +219,56 @@ void POLYFILL(struct pvertex *pv, int nverts) bslope = (db << 8) / dx; #endif #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) + int cr, cg, cb; +#endif #ifdef GOURAUD - /* drop the extra 8 bits when packing */ - int cr = r >> 8; - int cg = g >> 8; - int cb = b >> 8; - color = PACK_RGB16(cr, cg, cb); + /* 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); + if(cr > 255) cr = 255; + if(cg > 255) cg = 255; + if(cb > 255) cb = 255; r += rslope; g += gslope; b += bslope; #endif #ifdef TEXMAP - /* TODO */ + { + 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]; +#ifdef GOURAUD + /* 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 * UNPACK_R16(texel)) >> 8; + cg = (cg * UNPACK_G16(texel)) >> 8; + cb = (cb * UNPACK_B16(texel)) >> 8; +#else + cr = UNPACK_R16(texel); + cg = UNPACK_G16(texel); + cb = UNPACK_B16(texel); +#endif + } u += uslope; v += vslope; #endif +#if defined(GOURAUD) || defined(TEXMAP) + color = PACK_RGB16(cr, cg, cb); +#endif #ifdef DEBUG_OVERDRAW *pixptr++ += DEBUG_OVERDRAW;