From 659ca11730af4e7e5b1b350efa4198a9c42de287 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Tue, 30 Jun 2020 21:37:37 +0300 Subject: [PATCH] zbuffer partial implementation --- .gitignore | 7 ++ src/3dgfx/3dgfx.c | 26 +++++++- src/3dgfx/3dgfx.h | 2 +- src/3dgfx/polyfill.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/3dgfx/polyfill.h | 42 +++++++++++- src/3dgfx/polytmpl.h | 69 ++++++++++++++++++-- 6 files changed, 308 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 0d8b1b8..e86dd42 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,10 @@ cspr/ tools/img2bin/img2bin tools/ropesim/ropesim tools/gltest/test +RUN +*.dae +*.mtl +*.glb +*.blend* +*.ppm +*.png diff --git a/src/3dgfx/3dgfx.c b/src/3dgfx/3dgfx.c index e199a64..16024f8 100644 --- a/src/3dgfx/3dgfx.c +++ b/src/3dgfx/3dgfx.c @@ -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; diff --git a/src/3dgfx/3dgfx.h b/src/3dgfx/3dgfx.h index e317fab..2aeb8be 100644 --- a/src/3dgfx/3dgfx.h +++ b/src/3dgfx/3dgfx.h @@ -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, diff --git a/src/3dgfx/polyfill.c b/src/3dgfx/polyfill.c index 972c218..a6eb19f 100644 --- a/src/3dgfx/polyfill.c +++ b/src/3dgfx/polyfill.c @@ -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 diff --git a/src/3dgfx/polyfill.h b/src/3dgfx/polyfill.h index 19092f0..fed8eda 100644 --- a/src/3dgfx/polyfill.h +++ b/src/3dgfx/polyfill.h @@ -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_ */ diff --git a/src/3dgfx/polytmpl.h b/src/3dgfx/polytmpl.h index 2072e2b..01bbd01 100644 --- a/src/3dgfx/polytmpl.h +++ b/src/3dgfx/polytmpl.h @@ -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 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 -- 1.7.10.4