zbuffer partial implementation
authorJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 30 Jun 2020 18:37:37 +0000 (21:37 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 30 Jun 2020 18:37:37 +0000 (21:37 +0300)
.gitignore
src/3dgfx/3dgfx.c
src/3dgfx/3dgfx.h
src/3dgfx/polyfill.c
src/3dgfx/polyfill.h
src/3dgfx/polytmpl.h

index 0d8b1b8..e86dd42 100644 (file)
@@ -43,3 +43,10 @@ cspr/
 tools/img2bin/img2bin
 tools/ropesim/ropesim
 tools/gltest/test
+RUN
+*.dae
+*.mtl
+*.glb
+*.blend*
+*.ppm
+*.png
index e199a64..16024f8 100644 (file)
@@ -17,6 +17,8 @@
 #include "demo.h"
 #include "util.h"
 
+#define ENABLE_ZBUFFER
+
 #define STACK_SIZE     8
 typedef float g3d_matrix[16];
 
@@ -90,7 +92,7 @@ static const float idmat[] = {
 
 int g3d_init(void)
 {
-       if(!(st = malloc(sizeof *st))) {
+       if(!(st = calloc(1, sizeof *st))) {
                fprintf(stderr, "failed to allocate G3D context\n");
                return -1;
        }
@@ -101,6 +103,9 @@ int g3d_init(void)
 
 void g3d_destroy(void)
 {
+#ifdef ENABLE_ZBUFFER
+       free(pfill_zbuf);
+#endif
        free(st);
 }
 
@@ -108,6 +113,9 @@ void g3d_reset(void)
 {
        int i;
 
+#ifdef ENABLE_ZBUFFER
+       free(pfill_zbuf);
+#endif
        memset(st, 0, sizeof *st);
 
        st->opt = G3D_CLIP_FRUSTUM;
@@ -128,10 +136,22 @@ void g3d_reset(void)
 
 void g3d_framebuffer(int width, int height, void *pixels)
 {
-       static int prev_height;
+       static int max_height;
+
+#ifdef ENABLE_ZBUFFER
+       static int max_npixels;
+       int npixels = width * height;
+
+       if(npixels > max_npixels) {
+               free(pfill_zbuf);
+               pfill_zbuf = malloc(npixels * sizeof *pfill_zbuf);
+               max_npixels = npixels;
+       }
+#endif
 
-       if(height > prev_height) {
+       if(height > max_height) {
                polyfill_fbheight(height);
+               max_height = height;
        }
 
        st->width = width;
index e317fab..2aeb8be 100644 (file)
@@ -38,7 +38,7 @@ enum {
 /* g3d_enable/g3d_disable bits */
 enum {
        G3D_CULL_FACE   = 0x000001,
-       G3D_DEPTH_TEST  = 0x000002,     /* XXX not implemented */
+       G3D_DEPTH_TEST  = 0x000002,
        G3D_LIGHTING    = 0x000004,
        G3D_LIGHT0              = 0x000008,
        G3D_LIGHT1              = 0x000010,
index 972c218..a6eb19f 100644 (file)
@@ -15,6 +15,7 @@
 /* mode bits: 00-wire 01-flat 10-gouraud 11-reserved
  *     bit 2: texture
  *     bit 3-4: blend mode: 00-none 01-alpha 10-additive 11-reserved
+ *     bit 5: zbuffering
  */
 void (*fillfunc[])(struct pvertex*, int) = {
        polyfill_wire,
@@ -40,10 +41,35 @@ void (*fillfunc[])(struct pvertex*, int) = {
        polyfill_add_tex_wire,
        polyfill_add_tex_flat,
        polyfill_add_tex_gouraud,
+       0, 0, 0, 0, 0, 0, 0, 0, 0,
+       polyfill_wire,
+       polyfill_flat_zbuf,
+       polyfill_gouraud_zbuf,
+       0,
+       polyfill_tex_wire,
+       polyfill_tex_flat_zbuf,
+       polyfill_tex_gouraud_zbuf,
+       0,
+       polyfill_alpha_wire,
+       polyfill_alpha_flat_zbuf,
+       polyfill_alpha_gouraud_zbuf,
+       0,
+       polyfill_alpha_tex_wire,
+       polyfill_alpha_tex_flat_zbuf,
+       polyfill_alpha_tex_gouraud_zbuf,
+       0,
+       polyfill_add_wire,
+       polyfill_add_flat_zbuf,
+       polyfill_add_gouraud_zbuf,
+       0,
+       polyfill_add_tex_wire,
+       polyfill_add_tex_flat_zbuf,
+       polyfill_add_tex_gouraud_zbuf,
        0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
 struct pimage pfill_fb, pfill_tex;
+uint16_t *pfill_zbuf;
 
 #define EDGEPAD        8
 static struct pvertex *edgebuf, *left, *right;
@@ -171,6 +197,7 @@ void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
 #undef TEXMAP
 #undef BLEND_ALPHA
 #undef BLEND_ADD
+#undef ZBUF
 #include "polytmpl.h"
 #undef POLYFILL
 #undef SCANEDGE
@@ -181,6 +208,7 @@ void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
 #undef TEXMAP
 #undef BLEND_ALPHA
 #undef BLEND_ADD
+#undef ZBUF
 #include "polytmpl.h"
 #undef POLYFILL
 #undef SCANEDGE
@@ -191,6 +219,7 @@ void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
 #define TEXMAP
 #undef BLEND_ALPHA
 #undef BLEND_ADD
+#undef ZBUF
 #include "polytmpl.h"
 #undef POLYFILL
 #undef SCANEDGE
@@ -201,6 +230,7 @@ void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
 #define TEXMAP
 #undef BLEND_ALPHA
 #undef BLEND_ADD
+#undef ZBUF
 #include "polytmpl.h"
 #undef POLYFILL
 #undef SCANEDGE
@@ -211,6 +241,7 @@ void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
 #undef TEXMAP
 #define BLEND_ALPHA
 #undef BLEND_ADD
+#undef ZBUF
 #include "polytmpl.h"
 #undef POLYFILL
 #undef SCANEDGE
@@ -221,6 +252,7 @@ void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
 #undef TEXMAP
 #define BLEND_ALPHA
 #undef BLEND_ADD
+#undef ZBUF
 #include "polytmpl.h"
 #undef POLYFILL
 #undef SCANEDGE
@@ -231,6 +263,7 @@ void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
 #define TEXMAP
 #define BLEND_ALPHA
 #undef BLEND_ADD
+#undef ZBUF
 #include "polytmpl.h"
 #undef POLYFILL
 #undef SCANEDGE
@@ -241,6 +274,7 @@ void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
 #define TEXMAP
 #define BLEND_ALPHA
 #undef BLEND_ADD
+#undef ZBUF
 #include "polytmpl.h"
 #undef POLYFILL
 #undef SCANEDGE
@@ -251,6 +285,7 @@ void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
 #undef TEXMAP
 #undef BLEND_ALPHA
 #define BLEND_ADD
+#undef ZBUF
 #include "polytmpl.h"
 #undef POLYFILL
 #undef SCANEDGE
@@ -261,6 +296,7 @@ void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
 #undef TEXMAP
 #undef BLEND_ALPHA
 #define BLEND_ADD
+#undef ZBUF
 #include "polytmpl.h"
 #undef POLYFILL
 #undef SCANEDGE
@@ -271,6 +307,7 @@ void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
 #define TEXMAP
 #undef BLEND_ALPHA
 #define BLEND_ADD
+#undef ZBUF
 #include "polytmpl.h"
 #undef POLYFILL
 #undef SCANEDGE
@@ -281,6 +318,141 @@ void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
 #define TEXMAP
 #undef BLEND_ALPHA
 #define BLEND_ADD
+#undef ZBUF
+#include "polytmpl.h"
+#undef POLYFILL
+#undef SCANEDGE
+
+/* ---- zbuffer variants ----- */
+
+#define POLYFILL polyfill_flat_zbuf
+#define SCANEDGE scanedge_flat_zbuf
+#undef GOURAUD
+#undef TEXMAP
+#undef BLEND_ALPHA
+#undef BLEND_ADD
+#define ZBUF
+#include "polytmpl.h"
+#undef POLYFILL
+#undef SCANEDGE
+
+#define POLYFILL polyfill_gouraud_zbuf
+#define SCANEDGE scanedge_gouraud_zbuf
+#define GOURAUD
+#undef TEXMAP
+#undef BLEND_ALPHA
+#undef BLEND_ADD
+#define ZBUF
+#include "polytmpl.h"
+#undef POLYFILL
+#undef SCANEDGE
+
+#define POLYFILL polyfill_tex_flat_zbuf
+#define SCANEDGE scanedge_tex_flat_zbuf
+#undef GOURAUD
+#define TEXMAP
+#undef BLEND_ALPHA
+#undef BLEND_ADD
+#define ZBUF
+#include "polytmpl.h"
+#undef POLYFILL
+#undef SCANEDGE
+
+#define POLYFILL polyfill_tex_gouraud_zbuf
+#define SCANEDGE scanedge_tex_gouraud_zbuf
+#define GOURAUD
+#define TEXMAP
+#undef BLEND_ALPHA
+#undef BLEND_ADD
+#define ZBUF
+#include "polytmpl.h"
+#undef POLYFILL
+#undef SCANEDGE
+
+#define POLYFILL polyfill_alpha_flat_zbuf
+#define SCANEDGE scanedge_alpha_flat_zbuf
+#undef GOURAUD
+#undef TEXMAP
+#define BLEND_ALPHA
+#undef BLEND_ADD
+#define ZBUF
+#include "polytmpl.h"
+#undef POLYFILL
+#undef SCANEDGE
+
+#define POLYFILL polyfill_alpha_gouraud_zbuf
+#define SCANEDGE scanedge_alpha_gouraud_zbuf
+#define GOURAUD
+#undef TEXMAP
+#define BLEND_ALPHA
+#undef BLEND_ADD
+#define ZBUF
+#include "polytmpl.h"
+#undef POLYFILL
+#undef SCANEDGE
+
+#define POLYFILL polyfill_alpha_tex_flat_zbuf
+#define SCANEDGE scanedge_alpha_tex_flat_zbuf
+#undef GOURAUD
+#define TEXMAP
+#define BLEND_ALPHA
+#undef BLEND_ADD
+#define ZBUF
+#include "polytmpl.h"
+#undef POLYFILL
+#undef SCANEDGE
+
+#define POLYFILL polyfill_alpha_tex_gouraud_zbuf
+#define SCANEDGE scanedge_alpha_tex_gouraud_zbuf
+#define GOURAUD
+#define TEXMAP
+#define BLEND_ALPHA
+#undef BLEND_ADD
+#define ZBUF
+#include "polytmpl.h"
+#undef POLYFILL
+#undef SCANEDGE
+
+#define POLYFILL polyfill_add_flat_zbuf
+#define SCANEDGE scanedge_add_flat_zbuf
+#undef GOURAUD
+#undef TEXMAP
+#undef BLEND_ALPHA
+#define BLEND_ADD
+#define ZBUF
+#include "polytmpl.h"
+#undef POLYFILL
+#undef SCANEDGE
+
+#define POLYFILL polyfill_add_gouraud_zbuf
+#define SCANEDGE scanedge_add_gouraud_zbuf
+#define GOURAUD
+#undef TEXMAP
+#undef BLEND_ALPHA
+#define BLEND_ADD
+#define ZBUF
+#include "polytmpl.h"
+#undef POLYFILL
+#undef SCANEDGE
+
+#define POLYFILL polyfill_add_tex_flat_zbuf
+#define SCANEDGE scanedge_add_tex_flat_zbuf
+#undef GOURAUD
+#define TEXMAP
+#undef BLEND_ALPHA
+#define BLEND_ADD
+#define ZBUF
+#include "polytmpl.h"
+#undef POLYFILL
+#undef SCANEDGE
+
+#define POLYFILL polyfill_add_tex_gouraud_zbuf
+#define SCANEDGE scanedge_add_tex_gouraud_zbuf
+#define GOURAUD
+#define TEXMAP
+#undef BLEND_ALPHA
+#define BLEND_ADD
+#define ZBUF
 #include "polytmpl.h"
 #undef POLYFILL
 #undef SCANEDGE
index 19092f0..fed8eda 100644 (file)
@@ -8,6 +8,7 @@
 #define POLYFILL_TEX_BIT       0x04
 #define POLYFILL_ALPHA_BIT     0x08
 #define POLYFILL_ADD_BIT       0x10
+#define POLYFILL_ZBUF_BIT      0x20
 
 enum {
        POLYFILL_WIRE                   = 0,
@@ -32,7 +33,32 @@ enum {
 
        POLYFILL_ADD_TEX_WIRE   = 20,
        POLYFILL_ADD_TEX_FLAT,
-       POLYFILL_ADD_TEX_GOURAUD
+       POLYFILL_ADD_TEX_GOURAUD,
+
+
+       POLYFILL_WIRE_ZBUF                      = 32,
+       POLYFILL_FLAT_ZBUF,
+       POLYFILL_GOURAUD_ZBUF,
+
+       POLYFILL_TEX_WIRE_ZBUF          = 36,
+       POLYFILL_TEX_FLAT_ZBUF,
+       POLYFILL_TEX_GOURAUD_ZBUF,
+
+       POLYFILL_ALPHA_WIRE_ZBUF        = 40,
+       POLYFILL_ALPHA_FLAT_ZBUF,
+       POLYFILL_ALPHA_GOURAUD_ZBUF,
+
+       POLYFILL_ALPHA_TEX_WIRE_ZBUF = 44,
+       POLYFILL_ALPHA_TEX_FLAT_ZBUF,
+       POLYFILL_ALPHA_TEX_GOURAUD_ZBUF,
+
+       POLYFILL_ADD_WIRE_ZBUF          = 48,
+       POLYFILL_ADD_FLAT_ZBUF,
+       POLYFILL_ADD_GOURAUD_ZBUF,
+
+       POLYFILL_ADD_TEX_WIRE_ZBUF      = 52,
+       POLYFILL_ADD_TEX_FLAT_ZBUF,
+       POLYFILL_ADD_TEX_GOURAUD_ZBUF
 };
 
 /* projected vertices for the rasterizer */
@@ -40,6 +66,7 @@ struct pvertex {
        int32_t x, y; /* 24.8 fixed point */
        int32_t u, v; /* 16.16 fixed point */
        int32_t r, g, b, a;  /* int 0-255 */
+       uint16_t z;     /* 0-65535 */
 };
 
 struct pimage {
@@ -52,6 +79,7 @@ struct pimage {
 
 extern struct pimage pfill_fb;
 extern struct pimage pfill_tex;
+extern uint16_t *pfill_zbuf;
 
 void polyfill_fbheight(int height);
 
@@ -75,5 +103,17 @@ void polyfill_add_gouraud(struct pvertex *verts, int nverts);
 void polyfill_add_tex_wire(struct pvertex *verts, int nverts);
 void polyfill_add_tex_flat(struct pvertex *verts, int nverts);
 void polyfill_add_tex_gouraud(struct pvertex *verts, int nverts);
+void polyfill_flat_zbuf(struct pvertex *verts, int nverts);
+void polyfill_gouraud_zbuf(struct pvertex *verts, int nverts);
+void polyfill_tex_flat_zbuf(struct pvertex *verts, int nverts);
+void polyfill_tex_gouraud_zbuf(struct pvertex *verts, int nverts);
+void polyfill_alpha_flat_zbuf(struct pvertex *verts, int nverts);
+void polyfill_alpha_gouraud_zbuf(struct pvertex *verts, int nverts);
+void polyfill_alpha_tex_flat_zbuf(struct pvertex *verts, int nverts);
+void polyfill_alpha_tex_gouraud_zbuf(struct pvertex *verts, int nverts);
+void polyfill_add_flat_zbuf(struct pvertex *verts, int nverts);
+void polyfill_add_gouraud_zbuf(struct pvertex *verts, int nverts);
+void polyfill_add_tex_flat_zbuf(struct pvertex *verts, int nverts);
+void polyfill_add_tex_gouraud_zbuf(struct pvertex *verts, int nverts);
 
 #endif /* POLYFILL_H_ */
index 2072e2b..01bbd01 100644 (file)
@@ -12,6 +12,9 @@ static uint32_t SCANEDGE(struct pvertex *v0, struct pvertex *v1, struct pvertex
 #ifdef TEXMAP
        int32_t u, v, du, dv, uslope, vslope;
 #endif
+#ifdef ZBUF
+       int z, dz, zslope;
+#endif
        int32_t start_idx, end_idx;
 
        if(v0->y > v1->y) {
@@ -48,6 +51,11 @@ static uint32_t SCANEDGE(struct pvertex *v0, struct pvertex *v1, struct pvertex
        uslope = (du << 8) / dy;
        vslope = (dv << 8) / dy;
 #endif
+#ifdef ZBUF
+       z = v0->z;
+       dz = v1->z - v0->z;
+       zslope = (dz << 8) / dy;
+#endif
 
        start_idx = v0->y >> 8;
        end_idx = v1->y >> 8;
@@ -58,7 +66,6 @@ static uint32_t SCANEDGE(struct pvertex *v0, struct pvertex *v1, struct pvertex
                x += slope;
 #ifdef GOURAUD
                /* we'll store the color in the edge tables with COLOR_SHIFT extra bits of precision */
-               CHECKEDGE(i);
                edge[i].r = r;
                edge[i].g = g;
                edge[i].b = b;
@@ -66,18 +73,20 @@ static uint32_t SCANEDGE(struct pvertex *v0, struct pvertex *v1, struct pvertex
                g += gslope;
                b += bslope;
 #ifdef BLEND_ALPHA
-               CHECKEDGE(i);
                edge[i].a = a;
                a += aslope;
 #endif
 #endif /* GOURAUD */
 #ifdef TEXMAP
-               CHECKEDGE(i);
                edge[i].u = u;
                edge[i].v = v;
                u += uslope;
                v += vslope;
 #endif
+#ifdef ZBUF
+               edge[i].z = z;
+               z += zslope;
+#endif
        }
 
        return (uint32_t)start_idx | ((uint32_t)(end_idx - 1) << 16);
@@ -89,7 +98,7 @@ void POLYFILL(struct pvertex *pv, int nverts)
        int topidx = 0, botidx = 0, sltop = pfill_fb.height, slbot = 0;
        g3d_pixel color;
        /* the following variables are used for interpolating horizontally accros scanlines */
-#if defined(GOURAUD) || defined(TEXMAP)
+#if defined(GOURAUD) || defined(TEXMAP) || defined(ZBUF)
        int mid;
        int32_t dx, tmp;
 #else
@@ -105,6 +114,9 @@ void POLYFILL(struct pvertex *pv, int nverts)
 #ifdef TEXMAP
        int32_t u, v, du, dv, uslope, vslope;
 #endif
+#ifdef ZBUF
+       int z, dz, zslope;
+#endif
 
        for(i=1; i<nverts; i++) {
                if(pv[i].y < pv[topidx].y) topidx = i;
@@ -154,6 +166,10 @@ void POLYFILL(struct pvertex *pv, int nverts)
                                right[idx].u = pv[i1].u;
                                right[idx].v = pv[i1].v;
 #endif
+#ifdef ZBUF
+                               left[idx].z = pv[i0].z;
+                               right[idx].z = pv[i1].z;
+#endif
                                CHECKEDGE(idx);
                                if(idx > slbot) slbot = idx;
                                if(idx < sltop) sltop = idx;
@@ -217,12 +233,19 @@ void POLYFILL(struct pvertex *pv, int nverts)
        uslope = (du << 8) / dx;
        vslope = (dv << 8) / dx;
 #endif
+#ifdef ZBUF
+       dz = right[mid].z - left[mid].z;
+       zslope = (dz << 8) / dx;
+#endif
 #endif /* !defined(HIGH_QUALITY) */
 
        /* for each scanline ... */
        for(i=sltop; i<=slbot; i++) {
                g3d_pixel *pixptr;
                int32_t x;
+#ifdef ZBUF
+               uint16_t *zptr;
+#endif
 
                CHECKEDGE(i);
                x = left[i].x;
@@ -240,9 +263,13 @@ void POLYFILL(struct pvertex *pv, int nverts)
                u = left[i].u;
                v = left[i].v;
 #endif
+#ifdef ZBUF
+               z = left[i].z;
+               zptr = pfill_zbuf + i * pfill_fb.width + (x >> 8);
+#endif
                CHECKEDGE(i);
 
-#if defined(HIGH_QUALITY) && (defined(GOURAUD) || defined(TEXMAP))
+#if defined(HIGH_QUALITY) && (defined(GOURAUD) || defined(TEXMAP) || defined(ZBUF))
                if(!(dx = right[i].x - left[i].x)) dx = 256;
 
                CHECKEDGE(i);
@@ -264,6 +291,10 @@ void POLYFILL(struct pvertex *pv, int nverts)
                uslope = (du << 8) / dx;
                vslope = (dv << 8) / dx;
 #endif
+#ifdef ZBUF
+               dz = right[i].z - left[i].z;
+               zslope = (dz << 8) / dx;
+#endif
 #endif /* HIGH_QUALITY */
                CHECKEDGE(i);
 
@@ -278,6 +309,31 @@ void POLYFILL(struct pvertex *pv, int nverts)
 #ifdef BLEND_ALPHA
                        int alpha, inv_alpha;
 #endif
+
+#ifdef ZBUF
+                       int cz = z;
+                       z += zslope;
+
+                       if(z <= *zptr) {
+                               *zptr = z;
+                       } else {
+#ifdef GOURAUD
+                               r += rslope;
+                               g += gslope;
+                               b += bslope;
+#ifdef BLEND_ALPHA
+                               a += aslope;
+#endif
+#endif
+#ifdef TEXMAP
+                               u += uslope;
+                               v += vslope;
+#endif
+                               goto skip_pixel;
+                       }
+                       zptr++;
+#endif
+
 #ifdef GOURAUD
                        /* we upped the color precision to while interpolating the
                         * edges, now drop the extra bits before packing
@@ -351,6 +407,9 @@ void POLYFILL(struct pvertex *pv, int nverts)
                        color = G3D_PACK_RGB(cr, cg, cb);
 #endif
 
+#ifdef ZBUF
+skip_pixel:
+#endif
 #ifdef DEBUG_OVERDRAW
                        *pixptr++ += DEBUG_OVERDRAW;
 #else