backported g3d changes:
authorJohn Tsiombikas <jtsiomb@census.gr>
Wed, 4 Sep 2019 12:00:18 +0000 (15:00 +0300)
committerJohn Tsiombikas <jtsiomb@census.gr>
Wed, 4 Sep 2019 12:00:18 +0000 (15:00 +0300)
 - rasterizer selection controled by enable bits
 - polygon blending
 - g3d_pixel typedef (uint16_t here)

src/3dgfx.c
src/3dgfx.h
src/gfxutil.h
src/infcubes.c
src/polyfill.c
src/polyfill.h
src/polytest.c
src/polytmpl.h

index 083f507..fb24c43 100644 (file)
@@ -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; i<G3D_NUM_MATRICES; i++) {
                g3d_matrix_mode(i);
@@ -159,7 +159,7 @@ void g3d_front_face(unsigned int order)
 
 void g3d_polygon_mode(int pmode)
 {
-       st->fill_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)
index 363a1b2..5c30e9c 100644 (file)
@@ -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 */
index f0468b6..adbbd15 100644 (file)
 #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);
 
index 46462f7..dd1bd33 100644 (file)
@@ -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();
index 1393cd2..3f94e25 100644 (file)
@@ -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
index b52b5de..86c7947 100644 (file)
@@ -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_ */
index 41442d5..0b05313 100644 (file)
@@ -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)
index f36b288..11ce0fa 100644 (file)
@@ -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