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)
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);
G3D_WIRE,
G3D_FLAT,
G3D_GOURAUD,
+ G3D_TEX,
+ G3D_TEX_GOURAUD
};
/* matrix stacks */
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);
#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))
polyfill_tex_gouraud
};
-struct pimage pimg_fb, pimg_texture;
+struct pimage pfill_fb, pfill_tex;
void polyfill(int mode, 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);
}
}
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);
#include "demo.h"
#include "3dgfx.h"
#include "gfxutil.h"
+#include "polyfill.h" /* just for struct pimage */
struct mesh {
int prim;
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",
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;
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; i<torus.vcount; i++) {
+ torus.varr[i].u *= 4.0;
+ torus.varr[i].v *= 2.0;
+ }
+
+ gen_texture(&tex, 128, 128);
#ifdef DEBUG_POLYFILL
lowres_width = fb_width / LOWRES_SCALE;
g3d_enable(G3D_LIGHTING);
g3d_enable(G3D_LIGHT0);
- g3d_polygon_mode(G3D_GOURAUD);
+ g3d_polygon_mode(G3D_TEX_GOURAUD);
}
static void update(void)
zsort(&torus);
- g3d_mtl_diffuse(0.3, 0.6, 1.0);
+ g3d_mtl_diffuse(0.4, 0.7, 1.0);
+ g3d_set_texture(tex.width, tex.height, tex.pixels);
+
draw_mesh(&torus);
/*draw_mesh(&cube);*/
dptr += fb_width * LOWRES_SCALE - fb_width;
}
}
+
+static int gen_texture(struct pimage *img, int xsz, int ysz)
+{
+ int i, j;
+ uint16_t *pix;
+
+ if(!(img->pixels = malloc(xsz * ysz * sizeof *pix))) {
+ return -1;
+ }
+ pix = img->pixels;
+
+ for(i=0; i<ysz; i++) {
+ for(j=0; j<xsz; j++) {
+ int val = i ^ j;
+
+ *pix++ = PACK_RGB16(val, val, val);
+ }
+ }
+
+ img->width = xsz;
+ img->height = ysz;
+ return 0;
+}
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);
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<nverts; i++) {
int next = NEXTIDX(i);
int32_t x;
x = left[i].x;
- pixptr = pimg_fb.pixels + i * pimg_fb.width + (x >> 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 */
#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;