From: John Tsiombikas Date: Tue, 4 Oct 2016 03:00:26 +0000 (+0300) Subject: added texture mapping X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=commitdiff_plain;h=07ce18b114e1e01b2a85a04079128f3eb754de1d added texture mapping --- diff --git a/src/3dgfx.c b/src/3dgfx.c index d7e2e41..47b3830 100644 --- a/src/3dgfx.c +++ b/src/3dgfx.c @@ -91,9 +91,9 @@ void g3d_framebuffer(int width, int height, void *pixels) st->height = height; st->pixels = pixels; - pimg_fb.pixels = pixels; - pimg_fb.width = width; - pimg_fb.height = height; + pfill_fb.pixels = pixels; + pfill_fb.width = width; + pfill_fb.height = height; } void g3d_enable(unsigned int opt) @@ -340,6 +340,33 @@ void g3d_mtl_shininess(float shin) st->mtl.shin = shin; } +static INLINE int calc_shift(unsigned int x) +{ + int res = -1; + while(x) { + x >>= 1; + ++res; + } + return res; +} + +static INLINE int calc_mask(unsigned int x) +{ + return x - 1; +} + +void g3d_set_texture(int xsz, int ysz, void *pixels) +{ + pfill_tex.pixels = pixels; + pfill_tex.width = xsz; + pfill_tex.height = ysz; + + pfill_tex.xshift = calc_shift(xsz); + pfill_tex.yshift = calc_shift(ysz); + pfill_tex.xmask = calc_mask(xsz); + pfill_tex.ymask = calc_mask(ysz); +} + void g3d_draw(int prim, const struct g3d_vertex *varr, int varr_size) { g3d_draw_indexed(prim, varr, varr_size, 0, 0); diff --git a/src/3dgfx.h b/src/3dgfx.h index ecc3f3c..fbbccf6 100644 --- a/src/3dgfx.h +++ b/src/3dgfx.h @@ -39,6 +39,8 @@ enum { G3D_WIRE, G3D_FLAT, G3D_GOURAUD, + G3D_TEX, + G3D_TEX_GOURAUD }; /* matrix stacks */ @@ -88,6 +90,8 @@ void g3d_mtl_diffuse(float r, float g, float b); void g3d_mtl_specular(float r, float g, float b); void g3d_mtl_shininess(float shin); +void g3d_set_texture(int xsz, int ysz, void *pixels); + 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 int16_t *iarr, int iarr_size); diff --git a/src/gfxutil.h b/src/gfxutil.h index f811987..07883ef 100644 --- a/src/gfxutil.h +++ b/src/gfxutil.h @@ -4,6 +4,10 @@ #define PACK_RGB16(r, g, b) \ (((((r) >> 3) & 0x1f) << 11) | ((((g) >> 2) & 0x3f) << 5) | (((b) >> 3) & 0x1f)) +#define UNPACK_R16(c) (((c) >> 8) & 0x7c) +#define UNPACK_G16(c) (((c) >> 3) & 0xfc) +#define UNPACK_B16(c) (((c) << 3) & 0x7c) + #define PACK_RGB32(r, g, b) \ ((((r) & 0xff) << 16) | (((g) & 0xff) << 8) | ((b) & 0xff)) diff --git a/src/polyfill.c b/src/polyfill.c index 634d525..0d1351e 100644 --- a/src/polyfill.c +++ b/src/polyfill.c @@ -19,7 +19,7 @@ void (*fillfunc[])(struct pvertex*, int) = { polyfill_tex_gouraud }; -struct pimage pimg_fb, pimg_texture; +struct pimage pfill_fb, pfill_tex; void polyfill(int mode, struct pvertex *verts, int nverts) { @@ -46,13 +46,13 @@ void polyfill_wire(struct pvertex *verts, int nverts) ++v; x1 = v->x >> 8; y1 = v->y >> 8; - if(clip_line(&x0, &y0, &x1, &y1, 0, 0, pimg_fb.width, pimg_fb.height)) { + if(clip_line(&x0, &y0, &x1, &y1, 0, 0, pfill_fb.width, pfill_fb.height)) { draw_line(x0, y0, x1, y1, color); } } x0 = verts[0].x >> 8; y0 = verts[0].y >> 8; - if(clip_line(&x1, &y1, &x0, &y0, 0, 0, pimg_fb.width, pimg_fb.height)) { + if(clip_line(&x1, &y1, &x0, &y0, 0, 0, pfill_fb.width, pfill_fb.height)) { draw_line(x1, y1, x0, y0, color); } } diff --git a/src/polyfill.h b/src/polyfill.h index a01130c..2a6b42d 100644 --- a/src/polyfill.h +++ b/src/polyfill.h @@ -21,10 +21,13 @@ struct pvertex { struct pimage { uint16_t *pixels; int width, height; + + int xshift, yshift; + unsigned int xmask, ymask; }; -extern struct pimage pimg_fb; -extern struct pimage pimg_texture; +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); diff --git a/src/polytest.c b/src/polytest.c index e7c3cdf..800dd46 100644 --- a/src/polytest.c +++ b/src/polytest.c @@ -6,6 +6,7 @@ #include "demo.h" #include "3dgfx.h" #include "gfxutil.h" +#include "polyfill.h" /* just for struct pimage */ struct mesh { int prim; @@ -23,6 +24,7 @@ static int gen_cube(struct mesh *mesh, float sz); static int gen_torus(struct mesh *mesh, float rad, float ringrad, int usub, int vsub); static void zsort(struct mesh *m); static void draw_lowres_raster(void); +static int gen_texture(struct pimage *img, int xsz, int ysz); static struct screen scr = { "polytest", @@ -35,6 +37,8 @@ static struct screen scr = { static float theta, phi = 25; static struct mesh cube, torus; +static struct pimage tex; + #define LOWRES_SCALE 10 static uint16_t *lowres_pixels; static int lowres_width, lowres_height; @@ -46,8 +50,17 @@ struct screen *polytest_screen(void) static int init(void) { + int i; + gen_cube(&cube, 1.0); gen_torus(&torus, 1.0, 0.25, 24, 12); + /* scale texcoords */ + for(i=0; ipixels = malloc(xsz * ysz * sizeof *pix))) { + return -1; + } + pix = img->pixels; + + for(i=0; iwidth = xsz; + img->height = ysz; + return 0; +} diff --git a/src/polytmpl.h b/src/polytmpl.h index 2021b3b..79660ef 100644 --- a/src/polytmpl.h +++ b/src/polytmpl.h @@ -70,13 +70,13 @@ 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 */ #if defined(GOURAUD) || defined(TEXMAP) - int mid; - int32_t dx, tmp; + /*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); @@ -93,8 +93,8 @@ 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); + left = alloca(pfill_fb.height * sizeof *left); + right = alloca(pfill_fb.height * sizeof *right); for(i=0; i> 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 */ @@ -182,21 +182,40 @@ void POLYFILL(struct pvertex *pv, int nverts) #endif 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); + cr = r >> 8; + cg = g >> 8; + cb = b >> 8; 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 + /* XXX this is not correct, should be /255, but it might not 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;