From 13e6367b959971d06c095414300ce0c54a43d337 Mon Sep 17 00:00:00 2001 From: danij Date: Fri, 21 May 2010 05:17:54 +0100 Subject: [PATCH] Changed: When loading sprites add an additonal 1-pixel border around the graphic which is then scaled and clipped out at render time. This addresses various GL filtering issues where a sprite contains color information in the edge texels. --- doomsday/engine/portable/include/r_data.h | 1 + doomsday/engine/portable/include/r_things.h | 1 + doomsday/engine/portable/src/gl_texmanager.c | 10 +++++----- doomsday/engine/portable/src/r_things.c | 16 +++++++++++----- doomsday/engine/portable/src/rend_sprite.c | 13 ++++++------- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/doomsday/engine/portable/include/r_data.h b/doomsday/engine/portable/include/r_data.h index b856b5517b..1a74ca020c 100644 --- a/doomsday/engine/portable/include/r_data.h +++ b/doomsday/engine/portable/include/r_data.h @@ -146,6 +146,7 @@ typedef struct flat_s { typedef struct { lumpnum_t lump; // Real lump number. short width, height, offX, offY; + int extraOffset[2]; // Used on ALL sprites to hide edge filtering artefacts. } spritetex_t; // Model skin. diff --git a/doomsday/engine/portable/include/r_things.h b/doomsday/engine/portable/include/r_things.h index 1f54c2820d..b1f065d093 100644 --- a/doomsday/engine/portable/include/r_things.h +++ b/doomsday/engine/portable/include/r_things.h @@ -87,6 +87,7 @@ typedef struct rendspriteparams_s { float center[3]; // The real center point. float width, height; float viewOffX; // View-aligned offset to center point. + float viewOffY; float srvo[3]; // Short-range visual offset. float distance; // Distance from viewer. boolean viewAligned; diff --git a/doomsday/engine/portable/src/gl_texmanager.c b/doomsday/engine/portable/src/gl_texmanager.c index bebb4ff6b6..7c8447f942 100644 --- a/doomsday/engine/portable/src/gl_texmanager.c +++ b/doomsday/engine/portable/src/gl_texmanager.c @@ -1611,8 +1611,8 @@ byte GL_LoadSprite(image_t* image, const gltexture_inst_t* inst, const lumppatch_t* patch; void* tmp = NULL; - image->width = sprTex->width; - image->height = sprTex->height; + image->width = sprTex->width+abs(sprTex->extraOffset[0])*2; + image->height = sprTex->height+abs(sprTex->extraOffset[1])*2; image->pixelSize = 1; image->pixels = M_Calloc(2 * image->width * image->height); @@ -1633,7 +1633,7 @@ byte GL_LoadSprite(image_t* image, const gltexture_inst_t* inst, patch = W_CacheLumpNum(sprTex->lump, PU_STATIC); } - image->isMasked = DrawRealPatch(image->pixels, image->width, image->height, patch, 0, 0, false, true); + image->isMasked = DrawRealPatch(image->pixels, image->width, image->height, patch, abs(sprTex->extraOffset[0]), abs(sprTex->extraOffset[1]), false, true); if(freePatch) M_Free(tmp); @@ -2860,8 +2860,8 @@ if(!didDefer) else { int pw = M_CeilPow2(image.width), ph = M_CeilPow2(image.height); - tc[0] = image.width / (float) pw; - tc[1] = image.height / (float) ph; + tc[0] = (image.width-1) / (float) pw; + tc[1] = (image.height-1) / (float) ph; } } diff --git a/doomsday/engine/portable/src/r_things.c b/doomsday/engine/portable/src/r_things.c index 5d66c3251c..2276f168c6 100644 --- a/doomsday/engine/portable/src/r_things.c +++ b/doomsday/engine/portable/src/r_things.c @@ -499,6 +499,11 @@ void R_PreInitSprites(void) sprTex->width = SHORT(patch->width); sprTex->height = SHORT(patch->height); + // An extra offset is applied during drawing and the sprite + // loaded with an additional border to counteract GL edge + // filtering artefacts. + sprTex->extraOffset[0] = sprTex->extraOffset[1] = -1; + glTex = GL_CreateGLTexture(name, idx++, GLT_SPRITE); // Create a new material for this sprite patch. @@ -721,8 +726,8 @@ boolean R_GetSpriteInfo(int sprite, int frame, spriteinfo_t* info) info->flip = sprFrame->flip[0]; info->offset = sprTex->offX; info->topOffset = sprTex->offY; - info->width = ms.width; - info->height = ms.height; + info->width = ms.width + abs(sprTex->extraOffset[0])*2; + info->height = ms.height + abs(sprTex->extraOffset[1])*2; info->texCoord[0] = ms.units[MTU_PRIMARY].texInst->data.sprite.texCoord[0]; info->texCoord[1] = ms.units[MTU_PRIMARY].texInst->data.sprite.texCoord[1]; @@ -970,8 +975,8 @@ static void setupSpriteParamsForVisSprite(rendspriteparams_t *params, sprTex = spriteTextures[ms.units[MTU_PRIMARY].texInst->tex->ofTypeID]; - params->width = ms.width; - params->height = ms.height; + params->width = ms.width + fabs(sprTex->extraOffset[0])*2; + params->height = ms.height + fabs(sprTex->extraOffset[1])*2; params->center[VX] = x; params->center[VY] = y; @@ -980,7 +985,8 @@ static void setupSpriteParamsForVisSprite(rendspriteparams_t *params, params->srvo[VY] = visOffY; params->srvo[VZ] = visOffZ; params->distance = distance; - params->viewOffX = (float) sprTex->offX - ms.width / 2.0f; + params->viewOffX = (float) sprTex->offX - ms.width / 2.0f - sprTex->extraOffset[0]; + params->viewOffY = -sprTex->extraOffset[1]; params->subsector = ssec; params->viewAligned = viewAligned; params->noZWrite = noSpriteZWrite; diff --git a/doomsday/engine/portable/src/rend_sprite.c b/doomsday/engine/portable/src/rend_sprite.c index a7820819f7..85b190d239 100644 --- a/doomsday/engine/portable/src/rend_sprite.c +++ b/doomsday/engine/portable/src/rend_sprite.c @@ -272,11 +272,10 @@ static void setupPSpriteParams(rendpspriteparams_t* params, Material_Prepare(&ms, sprFrame->mats[0], true, &mparams); sprTex = spriteTextures[ms.units[MTU_PRIMARY].texInst->tex->ofTypeID]; - params->pos[VX] = psp->pos[VX] - sprTex->offX + pspOffset[VX]; - params->pos[VX] = psp->pos[VX] - sprTex->offX + pspOffset[VX]; - params->pos[VY] = offScaleY * (psp->pos[VY] - sprTex->offY) + pspOffset[VY]; - params->width = ms.width; - params->height = ms.height; + params->pos[VX] = psp->pos[VX] - sprTex->offX + pspOffset[VX] + sprTex->extraOffset[0]; + params->pos[VY] = offScaleY * (psp->pos[VY] - sprTex->offY) + pspOffset[VY] + sprTex->extraOffset[1]; + params->width = ms.width + fabs(sprTex->extraOffset[0])*2; + params->height = ms.height + fabs(sprTex->extraOffset[1])*2; // Calculate texture coordinates. params->texOffset[0] = ms.units[MTU_PRIMARY].texInst->data.sprite.texCoord[VX]; @@ -914,8 +913,8 @@ void Rend_RenderSprite(const rendspriteparams_t* params) v3[VX] = v4[VX]; v3[VY] = v4[VY]; - v1[VZ] = v4[VZ] = spriteCenter[VZ] - params->height / 2; - v2[VZ] = v3[VZ] = spriteCenter[VZ] + params->height / 2; + v1[VZ] = v4[VZ] = spriteCenter[VZ] - params->height / 2 + params->viewOffY; + v2[VZ] = v3[VZ] = spriteCenter[VZ] + params->height / 2 + params->viewOffY; // Calculate the surface normal. M_PointCrossProduct(v2, v1, v3, surfaceNormal);