From: John Tsiombikas Date: Wed, 4 Sep 2019 12:00:18 +0000 (+0300) Subject: backported g3d changes: X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=commitdiff_plain;h=5f36e95f19ad8d7a5a1dd546ffeb54ce95d51749 backported g3d changes: - rasterizer selection controled by enable bits - polygon blending - g3d_pixel typedef (uint16_t here) --- diff --git a/src/3dgfx.c b/src/3dgfx.c index 083f507..fb24c43 100644 --- a/src/3dgfx.c +++ b/src/3dgfx.c @@ -37,7 +37,7 @@ struct material { struct g3d_state { unsigned int opt; int frontface; - int fill_mode; + int polymode; g3d_matrix mat[G3D_NUM_MATRICES][STACK_SIZE]; int mtop[G3D_NUM_MATRICES]; @@ -50,7 +50,7 @@ struct g3d_state { struct material mtl; int width, height; - uint16_t *pixels; + g3d_pixel *pixels; int vport[4]; @@ -83,7 +83,7 @@ int g3d_init(void) return -1; } st->opt = G3D_CLIP_FRUSTUM; - st->fill_mode = POLYFILL_FLAT; + st->polymode = POLYFILL_FLAT; for(i=0; ifill_mode = pmode; + st->polymode = pmode; } void g3d_matrix_mode(int mmode) @@ -411,7 +411,7 @@ void g3d_draw(int prim, const struct g3d_vertex *varr, int varr_size) void g3d_draw_indexed(int prim, const struct g3d_vertex *varr, int varr_size, const uint16_t *iarr, int iarr_size) { - int i, j, vnum, nfaces; + int i, j, vnum, nfaces, fill_mode; struct pvertex pv[16]; struct g3d_vertex v[16]; int mvtop = st->mtop[G3D_MODELVIEW]; @@ -511,26 +511,33 @@ void g3d_draw_indexed(int prim, const struct g3d_vertex *varr, int varr_size, if(st->opt & G3D_BLEND) { int r, g, b; int inv_alpha = 255 - pv[0].a; - uint16_t *dest = st->pixels + (pv[0].y >> 8) * st->width + (pv[0].x >> 8); - r = ((int)pv[0].r * pv[0].a + UNPACK_R16(*dest) * inv_alpha) >> 8; - g = ((int)pv[0].g * pv[0].a + UNPACK_G16(*dest) * inv_alpha) >> 8; - b = ((int)pv[0].b * pv[0].a + UNPACK_B16(*dest) * inv_alpha) >> 8; - *dest++ = PACK_RGB16(r, g, b); + g3d_pixel *dest = st->pixels + (pv[0].y >> 8) * st->width + (pv[0].x >> 8); + r = ((int)pv[0].r * pv[0].a + G3D_UNPACK_R(*dest) * inv_alpha) >> 8; + g = ((int)pv[0].g * pv[0].a + G3D_UNPACK_G(*dest) * inv_alpha) >> 8; + b = ((int)pv[0].b * pv[0].a + G3D_UNPACK_B(*dest) * inv_alpha) >> 8; + *dest++ = G3D_PACK_RGB(r, g, b); } else { - uint16_t *dest = st->pixels + (pv[0].y >> 8) * st->width + (pv[0].x >> 8); - *dest = PACK_RGB16(pv[0].r, pv[0].g, pv[0].b); + g3d_pixel *dest = st->pixels + (pv[0].y >> 8) * st->width + (pv[0].x >> 8); + *dest = G3D_PACK_RGB(pv[0].r, pv[0].g, pv[0].b); } break; case 2: { - uint16_t col = PACK_RGB16(pv[0].r, pv[0].g, pv[0].b); + g3d_pixel col = G3D_PACK_RGB(pv[0].r, pv[0].g, pv[0].b); draw_line(pv[0].x >> 8, pv[0].y >> 8, pv[1].x >> 8, pv[1].y >> 8, col); } break; default: - polyfill(st->fill_mode, pv, vnum); + fill_mode = st->polymode; + if(st->opt & G3D_TEXTURE_2D) { + fill_mode |= POLYFILL_TEX_BIT; + } + if(st->opt & G3D_BLEND) { + fill_mode |= POLYFILL_BLEND_BIT; + } + polyfill(fill_mode, pv, vnum); } } } @@ -578,20 +585,22 @@ void g3d_normal(float x, float y, float z) st->imm_curv.nz = z; } +#define CLAMP(x, a, b) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x))) + void g3d_color3b(unsigned char r, unsigned char g, unsigned char b) { - st->imm_curv.r = r; - st->imm_curv.g = g; - st->imm_curv.b = b; + st->imm_curv.r = CLAMP(r, 0, 255); + st->imm_curv.g = CLAMP(g, 0, 255); + st->imm_curv.b = CLAMP(b, 0, 255); st->imm_curv.a = 255; } void g3d_color4b(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { - st->imm_curv.r = r; - st->imm_curv.g = g; - st->imm_curv.b = b; - st->imm_curv.a = a; + st->imm_curv.r = CLAMP(r, 0, 255); + st->imm_curv.g = CLAMP(g, 0, 255); + st->imm_curv.b = CLAMP(b, 0, 255); + st->imm_curv.a = CLAMP(a, 0, 255); } void g3d_color3f(float r, float g, float b) @@ -599,9 +608,9 @@ void g3d_color3f(float r, float g, float b) int ir = r * 255.0f; int ig = g * 255.0f; int ib = b * 255.0f; - st->imm_curv.r = ir > 255 ? 255 : ir; - st->imm_curv.g = ig > 255 ? 255 : ig; - st->imm_curv.b = ib > 255 ? 255 : ib; + st->imm_curv.r = CLAMP(ir, 0, 255); + st->imm_curv.g = CLAMP(ig, 0, 255); + st->imm_curv.b = CLAMP(ib, 0, 255); st->imm_curv.a = 255; } @@ -611,10 +620,10 @@ void g3d_color4f(float r, float g, float b, float a) int ig = g * 255.0f; int ib = b * 255.0f; int ia = a * 255.0f; - st->imm_curv.r = ir > 255 ? 255 : ir; - st->imm_curv.g = ig > 255 ? 255 : ig; - st->imm_curv.b = ib > 255 ? 255 : ib; - st->imm_curv.a = ia > 255 ? 255 : ia; + st->imm_curv.r = CLAMP(ir, 0, 255); + st->imm_curv.g = CLAMP(ig, 0, 255); + st->imm_curv.b = CLAMP(ib, 0, 255); + st->imm_curv.a = CLAMP(ia, 0, 255); } void g3d_texcoord(float u, float v) diff --git a/src/3dgfx.h b/src/3dgfx.h index 363a1b2..5c30e9c 100644 --- a/src/3dgfx.h +++ b/src/3dgfx.h @@ -2,6 +2,24 @@ #define THREEDGFX_H_ #include "inttypes.h" +#include "gfxutil.h" + +#define G3D_PIXFMT16 +typedef uint16_t g3d_pixel; + +#ifdef G3D_PIXFMT16 +#define G3D_PACK_RGB(r, g, b) PACK_RGB16(r, g, b) +#define G3D_UNPACK_R(c) UNPACK_R16(c) +#define G3D_UNPACK_G(c) UNPACK_G16(c) +#define G3D_UNPACK_B(c) UNPACK_B16(c) +#endif +#ifdef G3D_PIXFMT32 +#define G3D_PACK_RGB(r, g, b) PACK_RGB32(r, g, b) +#define G3D_UNPACK_R(c) UNPACK_R32(c) +#define G3D_UNPACK_G(c) UNPACK_G32(c) +#define G3D_UNPACK_B(c) UNPACK_B32(c) +#endif + struct g3d_vertex { float x, y, z, w; @@ -47,9 +65,7 @@ enum { G3D_CCW, G3D_CW }; enum { G3D_WIRE, G3D_FLAT, - G3D_GOURAUD, - G3D_TEX, - G3D_TEX_GOURAUD + G3D_GOURAUD }; /* matrix stacks */ diff --git a/src/gfxutil.h b/src/gfxutil.h index f0468b6..adbbd15 100644 --- a/src/gfxutil.h +++ b/src/gfxutil.h @@ -15,6 +15,10 @@ #define PACK_RGB32(r, g, b) \ ((((r) & 0xff) << 16) | (((g) & 0xff) << 8) | ((b) & 0xff)) +#define UNPACK_R32(c) (((c) >> 16) & 0xff) +#define UNPACK_G32(c) (((c) >> 8) & 0xff) +#define UNPACK_B32(c) ((c) & 0xff) + int clip_line(int *x0, int *y0, int *x1, int *y1, int xmin, int ymin, int xmax, int ymax); void draw_line(int x0, int y0, int x1, int y1, unsigned short color); diff --git a/src/infcubes.c b/src/infcubes.c index 46462f7..dd1bd33 100644 --- a/src/infcubes.c +++ b/src/infcubes.c @@ -112,7 +112,8 @@ static void draw(void) memset(fb_pixels, 0, fb_width * fb_height * 2); - g3d_polygon_mode(G3D_TEX); + g3d_polygon_mode(G3D_FLAT); + g3d_enable(G3D_TEXTURE_2D); g3d_enable(G3D_TEXTURE_GEN); g3d_push_matrix(); diff --git a/src/polyfill.c b/src/polyfill.c index 1393cd2..3f94e25 100644 --- a/src/polyfill.c +++ b/src/polyfill.c @@ -9,14 +9,30 @@ #endif #include "polyfill.h" #include "gfxutil.h" -#include "demo.h" +#define FILL_POLY_BITS 0x03 + +/* mode bits: 00-wire 01-flat 10-gouraud 11-reserved + * bit 2: texture + * bit 3: blend + */ void (*fillfunc[])(struct pvertex*, int) = { polyfill_wire, polyfill_flat, polyfill_gouraud, - polyfill_tex, - polyfill_tex_gouraud + 0, + polyfill_tex_wire, + polyfill_tex_flat, + polyfill_tex_gouraud, + 0, + polyfill_blend_wire, + polyfill_blend_flat, + polyfill_blend_gouraud, + 0, + polyfill_blend_tex_wire, + polyfill_blend_tex_flat, + polyfill_blend_tex_gouraud, + 0 }; struct pimage pfill_fb, pfill_tex; @@ -57,6 +73,21 @@ void polyfill_wire(struct pvertex *verts, int nverts) } } +void polyfill_tex_wire(struct pvertex *verts, int nverts) +{ + polyfill_wire(verts, nverts); /* TODO */ +} + +void polyfill_blend_wire(struct pvertex *verts, int nverts) +{ + polyfill_wire(verts, nverts); /* TODO */ +} + +void polyfill_blend_tex_wire(struct pvertex *verts, int nverts) +{ + polyfill_wire(verts, nverts); /* TODO */ +} + #define NEXTIDX(x) (((x) - 1 + nverts) % nverts) #define PREVIDX(x) (((x) + 1) % nverts) @@ -79,6 +110,7 @@ void polyfill_wire(struct pvertex *verts, int nverts) #define SCANEDGE scanedge_flat #undef GOURAUD #undef TEXMAP +#undef BLEND #include "polytmpl.h" #undef POLYFILL #undef SCANEDGE @@ -87,14 +119,16 @@ void polyfill_wire(struct pvertex *verts, int nverts) #define SCANEDGE scanedge_gouraud #define GOURAUD #undef TEXMAP +#undef BLEND #include "polytmpl.h" #undef POLYFILL #undef SCANEDGE -#define POLYFILL polyfill_tex -#define SCANEDGE scanedge_tex +#define POLYFILL polyfill_tex_flat +#define SCANEDGE scanedge_tex_flat #undef GOURAUD #define TEXMAP +#undef BLEND #include "polytmpl.h" #undef POLYFILL #undef SCANEDGE @@ -103,6 +137,43 @@ void polyfill_wire(struct pvertex *verts, int nverts) #define SCANEDGE scanedge_tex_gouraud #define GOURAUD #define TEXMAP +#undef BLEND +#include "polytmpl.h" +#undef POLYFILL +#undef SCANEDGE + +#define POLYFILL polyfill_blend_flat +#define SCANEDGE scanedge_blend_flat +#undef GOURAUD +#undef TEXMAP +#define BLEND +#include "polytmpl.h" +#undef POLYFILL +#undef SCANEDGE + +#define POLYFILL polyfill_blend_gouraud +#define SCANEDGE scanedge_blend_gouraud +#define GOURAUD +#undef TEXMAP +#define BLEND +#include "polytmpl.h" +#undef POLYFILL +#undef SCANEDGE + +#define POLYFILL polyfill_blend_tex_flat +#define SCANEDGE scanedge_blend_tex_flat +#undef GOURAUD +#define TEXMAP +#define BLEND +#include "polytmpl.h" +#undef POLYFILL +#undef SCANEDGE + +#define POLYFILL polyfill_blend_tex_gouraud +#define SCANEDGE scanedge_blend_tex_gouraud +#define GOURAUD +#define TEXMAP +#define BLEND #include "polytmpl.h" #undef POLYFILL #undef SCANEDGE diff --git a/src/polyfill.h b/src/polyfill.h index b52b5de..86c7947 100644 --- a/src/polyfill.h +++ b/src/polyfill.h @@ -2,13 +2,28 @@ #define POLYFILL_H_ #include "inttypes.h" +#include "3dgfx.h" + +#define POLYFILL_MODE_MASK 0x03 +#define POLYFILL_TEX_BIT 0x04 +#define POLYFILL_BLEND_BIT 0x08 enum { - POLYFILL_WIRE, + POLYFILL_WIRE = 0, POLYFILL_FLAT, POLYFILL_GOURAUD, - POLYFILL_TEX, - POLYFILL_TEX_GOURAUD + + POLYFILL_TEX_WIRE = 4, + POLYFILL_TEX_FLAT, + POLYFILL_TEX_GOURAUD, + + POLYFILL_BLEND_WIRE = 8, + POLYFILL_BLEND_FLAT, + POLYFILL_BLEND_GOURAUD, + + POLYFILL_BLEND_TEX_WIRE = 12, + POLYFILL_BLEND_TEX_FLAT, + POLYFILL_BLEND_TEX_GOURAUD }; /* projected vertices for the rasterizer */ @@ -19,7 +34,7 @@ struct pvertex { }; struct pimage { - uint16_t *pixels; + g3d_pixel *pixels; int width, height; int xshift, yshift; @@ -30,10 +45,18 @@ extern struct pimage pfill_fb; extern struct pimage pfill_tex; void polyfill(int mode, struct pvertex *verts, int nverts); + void polyfill_wire(struct pvertex *verts, int nverts); void polyfill_flat(struct pvertex *verts, int nverts); void polyfill_gouraud(struct pvertex *verts, int nverts); -void polyfill_tex(struct pvertex *verts, int nverts); +void polyfill_tex_wire(struct pvertex *verts, int nverts); +void polyfill_tex_flat(struct pvertex *verts, int nverts); void polyfill_tex_gouraud(struct pvertex *verts, int nverts); +void polyfill_blend_wire(struct pvertex *verts, int nverts); +void polyfill_blend_flat(struct pvertex *verts, int nverts); +void polyfill_blend_gouraud(struct pvertex *verts, int nverts); +void polyfill_blend_tex_wire(struct pvertex *verts, int nverts); +void polyfill_blend_tex_flat(struct pvertex *verts, int nverts); +void polyfill_blend_tex_gouraud(struct pvertex *verts, int nverts); #endif /* POLYFILL_H_ */ diff --git a/src/polytest.c b/src/polytest.c index 41442d5..0b05313 100644 --- a/src/polytest.c +++ b/src/polytest.c @@ -99,7 +99,8 @@ static void start(long trans_time) g3d_enable(G3D_LIGHTING); g3d_enable(G3D_LIGHT0); - g3d_polygon_mode(G3D_TEX_GOURAUD); + g3d_polygon_mode(G3D_GOURAUD); + g3d_enable(G3D_TEXTURE_2D); } static void update(void) diff --git a/src/polytmpl.h b/src/polytmpl.h index f36b288..11ce0fa 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 @@ -31,7 +34,12 @@ static uint32_t SCANEDGE(struct pvertex *v0, struct pvertex *v1, struct pvertex 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; @@ -55,7 +63,11 @@ static uint32_t SCANEDGE(struct pvertex *v0, struct pvertex *v1, struct pvertex 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; @@ -72,17 +84,20 @@ void POLYFILL(struct pvertex *pv, int nverts) 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; #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; @@ -128,6 +143,10 @@ void POLYFILL(struct pvertex *pv, int nverts) 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; @@ -182,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; @@ -193,7 +216,7 @@ void POLYFILL(struct pvertex *pv, int nverts) /* for each scanline ... */ for(i=sltop; i<=slbot; i++) { - uint16_t *pixptr; + g3d_pixel *pixptr; int32_t x; x = left[i].x; @@ -203,6 +226,9 @@ void POLYFILL(struct pvertex *pv, int nverts) 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; @@ -219,7 +245,11 @@ void POLYFILL(struct pvertex *pv, int nverts) 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 du = right[i].u - left[i].u; dv = right[i].v - left[i].v; @@ -230,9 +260,13 @@ void POLYFILL(struct pvertex *pv, int nverts) /* 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 /* we upped the color precision to while interpolating the * edges, now drop the extra bits before packing @@ -240,36 +274,63 @@ void POLYFILL(struct pvertex *pv, int nverts) 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 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 /* 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; + 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