From b226cf6f5d3cd88c4d7ab31b89cd8585dde964ba Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 5 May 2008 21:02:21 +0000 Subject: [PATCH] experiment with texture filtering --- panda/src/tinydisplay/clip.c | 8 ++--- panda/src/tinydisplay/zbuffer.c | 33 ++++++++++++++++++++ panda/src/tinydisplay/zbuffer.h | 43 +++++++++++++++++---------- panda/src/tinydisplay/ztriangle_two.h | 12 ++++---- 4 files changed, 71 insertions(+), 25 deletions(-) diff --git a/panda/src/tinydisplay/clip.c b/panda/src/tinydisplay/clip.c index 9a089a81c1..8551bd2ffb 100644 --- a/panda/src/tinydisplay/clip.c +++ b/panda/src/tinydisplay/clip.c @@ -35,10 +35,10 @@ void gl_transform_to_viewport(GLContext *c,GLVertex *v) /* texture */ if (c->texture_2d_enabled) { - v->zp.s=(int)(v->tex_coord.X * (ZB_POINT_S_MAX - ZB_POINT_S_MIN) - + ZB_POINT_S_MIN); - v->zp.t=(int)(v->tex_coord.Y * (ZB_POINT_T_MAX - ZB_POINT_T_MIN) - + ZB_POINT_T_MIN); + v->zp.s=(int)(v->tex_coord.X * (ZB_POINT_ST_MAX - ZB_POINT_ST_MIN) + + ZB_POINT_ST_MIN); + v->zp.t=(int)(v->tex_coord.Y * (ZB_POINT_ST_MAX - ZB_POINT_ST_MIN) + + ZB_POINT_ST_MIN); } } diff --git a/panda/src/tinydisplay/zbuffer.c b/panda/src/tinydisplay/zbuffer.c index b2c80592b9..8e75f75d08 100644 --- a/panda/src/tinydisplay/zbuffer.c +++ b/panda/src/tinydisplay/zbuffer.c @@ -340,3 +340,36 @@ void ZB_clear_viewport(ZBuffer * zb, int clear_z, int z, } } } + +#define ZB_ST_FRAC_HIGH (1 << ZB_POINT_ST_FRAC_BITS) +#define ZB_ST_FRAC_MASK (ZB_ST_FRAC_HIGH - 1) + +PIXEL lookup_texture_bilinear(PIXEL *texture, int s, int t) +{ + PIXEL p1, p2, p3, p4; + int sf, tf; + int r, g, b, a; + + p1 = ZB_LOOKUP_TEXTURE_NEAREST(texture, s, t); + p2 = ZB_LOOKUP_TEXTURE_NEAREST(texture, s + ZB_ST_FRAC_HIGH, t); + sf = s & ZB_ST_FRAC_MASK; + + p3 = ZB_LOOKUP_TEXTURE_NEAREST(texture, s, t + ZB_ST_FRAC_HIGH); + p4 = ZB_LOOKUP_TEXTURE_NEAREST(texture, s + ZB_ST_FRAC_HIGH, t + ZB_ST_FRAC_HIGH); + tf = t & ZB_ST_FRAC_MASK; + + r = (((PIXEL_R(p4) * sf + PIXEL_R(p3) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * tf + + ((PIXEL_R(p2) * sf + PIXEL_R(p1) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * (ZB_ST_FRAC_HIGH - tf)) >> ZB_POINT_ST_FRAC_BITS; + + g = (((PIXEL_G(p4) * sf + PIXEL_G(p3) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * tf + + ((PIXEL_G(p2) * sf + PIXEL_G(p1) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * (ZB_ST_FRAC_HIGH - tf)) >> ZB_POINT_ST_FRAC_BITS; + + b = (((PIXEL_B(p4) * sf + PIXEL_B(p3) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * tf + + ((PIXEL_B(p2) * sf + PIXEL_B(p1) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * (ZB_ST_FRAC_HIGH - tf)) >> ZB_POINT_ST_FRAC_BITS; + + a = (((PIXEL_A(p4) * sf + PIXEL_A(p3) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * tf + + ((PIXEL_A(p2) * sf + PIXEL_A(p1) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * (ZB_ST_FRAC_HIGH - tf)) >> ZB_POINT_ST_FRAC_BITS; + + return RGBA_TO_PIXEL(r, g, b, a); +} + diff --git a/panda/src/tinydisplay/zbuffer.h b/panda/src/tinydisplay/zbuffer.h index 672eaebd41..67db7b34bc 100644 --- a/panda/src/tinydisplay/zbuffer.h +++ b/panda/src/tinydisplay/zbuffer.h @@ -18,25 +18,36 @@ /* The number of fractional bits below the S and T texture coords. The more we have, the more precise the texel calculation will be when we zoom into small details of a texture; but the greater - chance we'll overflow our 32-bit integer if the T texcoord gets - large. */ -#define ZB_POINT_ST_FRAC_BITS 10 + chance we might overflow our 32-bit integer. */ +#define ZB_POINT_ST_FRAC_BITS 12 /* Various parameters and accessors based on the above bits. */ -#define ZB_POINT_S_LOW ZB_POINT_ST_FRAC_BITS -#define ZB_POINT_S_MIN 0 -#define ZB_POINT_S_MAX (1 << (ZB_POINT_ST_BITS + ZB_POINT_S_LOW)) -#define ZB_POINT_S_MASK ((1 << (ZB_POINT_ST_BITS + ZB_POINT_S_LOW)) - (1 << ZB_POINT_S_LOW)) +#define ZB_POINT_ST_MIN 0 +#define ZB_POINT_ST_MAX (1 << (ZB_POINT_ST_BITS + ZB_POINT_ST_FRAC_BITS)) +#define ZB_POINT_ST_MASK ((1 << (ZB_POINT_ST_BITS + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS)) -#define ZB_POINT_T_LOW (ZB_POINT_ST_BITS + ZB_POINT_S_LOW) -#define ZB_POINT_T_MIN 0 -#define ZB_POINT_T_MAX (1 << (ZB_POINT_ST_BITS + ZB_POINT_T_LOW)) -#define ZB_POINT_T_MASK ((1 << (ZB_POINT_ST_BITS + ZB_POINT_T_LOW)) - (1 << ZB_POINT_T_LOW)) - -// Returns the index within a 256x256 texture for the given (s, t) -// texel. +/* Returns the index within a 256x256 texture for the given (s, t) + texel. */ #define ZB_TEXEL(s, t) \ - ((((t) & ZB_POINT_T_MASK) | ((s) & ZB_POINT_S_MASK)) >> ZB_POINT_ST_FRAC_BITS) + ((((t) & ZB_POINT_ST_MASK) >> (ZB_POINT_ST_FRAC_BITS - ZB_POINT_ST_BITS)) | \ + (((s) & ZB_POINT_ST_MASK) >> ZB_POINT_ST_FRAC_BITS)) + +#define ZB_LOOKUP_TEXTURE_NEAREST(texture, s, t) \ + (texture)[ZB_TEXEL(s, t)] + +#if 1 +/* Use no texture filtering by default. It's faster, even though it + looks terrible. */ +#define ZB_LOOKUP_TEXTURE(texture, s, t) \ + ZB_LOOKUP_TEXTURE_NEAREST(texture, s, t) + +#else +/* Experiment with bilinear filtering. Looks great, but seems to run + about 25% slower. */ +#define ZB_LOOKUP_TEXTURE(texture, s, t) \ + lookup_texture_bilinear((texture), (s), (t)) + +#endif #define ZB_POINT_RED_MIN 0x0000 #define ZB_POINT_RED_MAX 0xffff @@ -122,6 +133,8 @@ void ZB_clear_viewport(ZBuffer * zb, int clear_z, int z, int clear_color, int r, int g, int b, int a, int xmin, int ymin, int xsize, int ysize); +PIXEL lookup_texture_bilinear(PIXEL *texture, int s, int t); + /* linesize is in BYTES */ void ZB_copyFrameBuffer(ZBuffer *zb,void *buf,int linesize); diff --git a/panda/src/tinydisplay/ztriangle_two.h b/panda/src/tinydisplay/ztriangle_two.h index 30a49fb567..2615922e28 100644 --- a/panda/src/tinydisplay/ztriangle_two.h +++ b/panda/src/tinydisplay/ztriangle_two.h @@ -82,7 +82,7 @@ void FNAME(ZB_fillTriangleMapping) (ZBuffer *zb, { \ zz=z >> ZB_POINT_Z_FRAC_BITS; \ if (ZCMP(pz[_a], zz)) { \ - tmp = texture[ZB_TEXEL(s, t)]; \ + tmp = ZB_LOOKUP_TEXTURE(texture, s, t); \ if (ACMP(zb, PIXEL_A(tmp))) { \ STORE_PIX(pp[_a], tmp, PIXEL_R(tmp), PIXEL_G(tmp), PIXEL_B(tmp), PIXEL_A(tmp)); \ STORE_Z(pz[_a], zz); \ @@ -118,7 +118,7 @@ void FNAME(ZB_fillTriangleMappingFlat) (ZBuffer *zb, { \ zz=z >> ZB_POINT_Z_FRAC_BITS; \ if (ZCMP(pz[_a], zz)) { \ - tmp = texture[ZB_TEXEL(s, t)]; \ + tmp = ZB_LOOKUP_TEXTURE(texture, s, t); \ int a = oa * PIXEL_A(tmp) >> 16; \ if (ACMP(zb, a)) { \ STORE_PIX(pp[_a], \ @@ -159,7 +159,7 @@ void FNAME(ZB_fillTriangleMappingSmooth) (ZBuffer *zb, { \ zz=z >> ZB_POINT_Z_FRAC_BITS; \ if (ZCMP(pz[_a], zz)) { \ - tmp = texture[ZB_TEXEL(s, t)]; \ + tmp = ZB_LOOKUP_TEXTURE(texture, s, t); \ int a = oa1 * PIXEL_A(tmp) >> 16; \ if (ACMP(zb, a)) { \ STORE_PIX(pp[_a], \ @@ -216,7 +216,7 @@ void FNAME(ZB_fillTriangleMappingPerspective) (ZBuffer *zb, { \ zz=z >> ZB_POINT_Z_FRAC_BITS; \ if (ZCMP(pz[_a], zz)) { \ - tmp = texture[ZB_TEXEL(s, t)]; \ + tmp = ZB_LOOKUP_TEXTURE(texture, s, t); \ if (ACMP(zb, PIXEL_A(tmp))) { \ STORE_PIX(pp[_a], tmp, PIXEL_R(tmp), PIXEL_G(tmp), PIXEL_B(tmp), PIXEL_A(tmp)); \ STORE_Z(pz[_a], zz); \ @@ -321,7 +321,7 @@ void FNAME(ZB_fillTriangleMappingPerspectiveFlat) (ZBuffer *zb, { \ zz=z >> ZB_POINT_Z_FRAC_BITS; \ if (ZCMP(pz[_a], zz)) { \ - tmp = texture[ZB_TEXEL(s, t)]; \ + tmp = ZB_LOOKUP_TEXTURE(texture, s, t); \ int a = oa * PIXEL_A(tmp) >> 16; \ if (ACMP(zb, a)) { \ STORE_PIX(pp[_a], \ @@ -434,7 +434,7 @@ void FNAME(ZB_fillTriangleMappingPerspectiveSmooth) (ZBuffer *zb, { \ zz=z >> ZB_POINT_Z_FRAC_BITS; \ if (ZCMP(pz[_a], zz)) { \ - tmp = texture[ZB_TEXEL(s, t)]; \ + tmp = ZB_LOOKUP_TEXTURE(texture, s, t); \ int a = oa1 * PIXEL_A(tmp) >> 16; \ if (ACMP(zb, a)) { \ STORE_PIX(pp[_a], \