diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index fb25dc58e..5eb6d9104 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -60,48 +60,6 @@ static const INT32 format2bpp[16] = 2, //14 GR_TEXFMT_AP_88 }; -static RGBA_t astblendpixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha) -{ - RGBA_t output; - output.s.alpha = 0xFF; - - if (style == AST_TRANSLUCENT) - { - if (alpha == 0) - output.rgba = background.rgba; - else if (alpha == 0xFF) - output.rgba = foreground.rgba; - else if (alpha < 0xFF) - { - UINT8 beta = (0xFF - alpha); - output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF; - output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF; - output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF; - } - // write foreground pixel alpha - // if there's no pixel in here - if (!background.rgba) - output.s.alpha = foreground.s.alpha; - } - - return output; -} - -static UINT8 astblendpixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 alpha) -{ - if ((style == AST_TRANSLUCENT) && (alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency? - { - UINT8 *mytransmap; - if (alpha < 255/11) // Is the patch way too translucent? Don't render then. - return background; - // The equation's not exact but it works as intended. I'll call it a day for now. - mytransmap = transtables + ((8*(alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); - if (background != 0xFF) - return *(mytransmap + (background<<8) + foreground); - } - return background; -} - // This code was originally placed directly in HWR_DrawPatchInCache. // It is now split from it for my sanity! (and the sanity of others) // -- Monster Iestyn (13/02/19) @@ -180,34 +138,34 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm switch (bpp) { case 2 : // uhhhhhhhh.......... - if ((originPatch != NULL) && originPatch->style) - texel = astblendpixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + texel = ASTBlendPixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha); texelu16 = (UINT16)((alpha<<8) | texel); memcpy(dest, &texelu16, sizeof(UINT16)); break; case 3 : colortemp = V_GetColor(texel); - if ((originPatch != NULL) && originPatch->style) + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) { RGBA_t rgbatexel; rgbatexel.rgba = *(UINT32 *)dest; - colortemp = astblendpixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); } memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); break; case 4 : colortemp = V_GetColor(texel); colortemp.s.alpha = alpha; - if ((originPatch != NULL) && originPatch->style) + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) { RGBA_t rgbatexel; rgbatexel.rgba = *(UINT32 *)dest; - colortemp = astblendpixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); } memcpy(dest, &colortemp, sizeof(RGBA_t)); break; // default is 1 default: - if ((originPatch != NULL) && originPatch->style) - *dest = astblendpixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + *dest = ASTBlendPixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha); else *dest = texel; break; @@ -294,34 +252,34 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, switch (bpp) { case 2 : // uhhhhhhhh.......... - if ((originPatch != NULL) && originPatch->style) - texel = astblendpixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + texel = ASTBlendPixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha); texelu16 = (UINT16)((alpha<<8) | texel); memcpy(dest, &texelu16, sizeof(UINT16)); break; case 3 : colortemp = V_GetColor(texel); - if ((originPatch != NULL) && originPatch->style) + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) { RGBA_t rgbatexel; rgbatexel.rgba = *(UINT32 *)dest; - colortemp = astblendpixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); } memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); break; case 4 : colortemp = V_GetColor(texel); colortemp.s.alpha = alpha; - if ((originPatch != NULL) && originPatch->style) + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) { RGBA_t rgbatexel; rgbatexel.rgba = *(UINT32 *)dest; - colortemp = astblendpixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); } memcpy(dest, &colortemp, sizeof(RGBA_t)); break; // default is 1 default: - if ((originPatch != NULL) && originPatch->style) - *dest = astblendpixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + *dest = ASTBlendPixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha); else *dest = texel; break; @@ -410,16 +368,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, if (texture->width <= 0 || texture->height <= 0) return; - /*if ((patch->style == AST_TRANSLUCENT) && (patch->alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency? - { - if (patch->alpha < 255/11) // Is the patch way too translucent? Don't render then. - continue; - ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawTransFlippedColumnInCache : HWR_DrawTransColumnInCache; - } - else*/ - { - ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache; - } + ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache; x1 = patch->originx; width = SHORT(realpatch->width); diff --git a/src/r_data.c b/src/r_data.c index 6889bddde..335a390d0 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -220,15 +220,110 @@ static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, tex } } +RGBA_t ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha) +{ + RGBA_t output; + if (style == AST_TRANSLUCENT) + { + if (alpha == 0) + output.rgba = background.rgba; + else if (alpha == 0xFF) + output.rgba = foreground.rgba; + else if (alpha < 0xFF) + { + UINT8 beta = (0xFF - alpha); + output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF; + output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF; + output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF; + } + // write foreground pixel alpha + // if there's no pixel in here + if (!background.rgba) + output.s.alpha = foreground.s.alpha; + } +#define clamp(c) max(min(c, 0xFF), 0x00); + else + { + float falpha = ((float)alpha / 256.0f); + float fr = ((float)foreground.s.red * falpha); + float fg = ((float)foreground.s.green * falpha); + float fb = ((float)foreground.s.blue * falpha); + if (style == AST_ADD) + { + output.s.red = clamp((int)(background.s.red + fr)); + output.s.green = clamp((int)(background.s.green + fg)); + output.s.blue = clamp((int)(background.s.blue + fb)); + } + else if (style == AST_SUBTRACT) + { + output.s.red = clamp((int)(background.s.red - fr)); + output.s.green = clamp((int)(background.s.green - fg)); + output.s.blue = clamp((int)(background.s.blue - fb)); + } + else if (style == AST_REVERSESUBTRACT) + { + output.s.red = clamp((int)((-background.s.red) + fr)); + output.s.green = clamp((int)((-background.s.green) + fg)); + output.s.blue = clamp((int)((-background.s.blue) + fb)); + } + else if (style == AST_MODULATE) + { + fr = ((float)foreground.s.red / 256.0f); + fg = ((float)foreground.s.green / 256.0f); + fb = ((float)foreground.s.blue / 256.0f); + output.s.red = clamp((int)(background.s.red * fr)); + output.s.green = clamp((int)(background.s.green * fg)); + output.s.blue = clamp((int)(background.s.blue * fb)); + } + // just copy the pixel + else if (style == AST_COPY) + return background; + } +#undef clamp + // unimplemented blend modes return the background pixel + output = background; + output.s.alpha = 0xFF; + return output; +} + +UINT8 ASTBlendPixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 alpha) +{ + if ((style == AST_TRANSLUCENT) && (alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency? + { + UINT8 *mytransmap; + if (alpha < 255/11) // Is the patch way too translucent? Don't render then. + return background; + // The equation's not exact but it works as intended. I'll call it a day for now. + mytransmap = transtables + ((8*(alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); + if (background != 0xFF) + return *(mytransmap + (background<<8) + foreground); + } + // just copy the pixel + else if (style == AST_COPY) + return background; + // use ASTBlendPixel for all other blend modes + // and find the nearest colour in the palette + else if (style != AST_TRANSLUCENT) + { + RGBA_t texel; + RGBA_t bg = V_GetColor(background); + RGBA_t fg = V_GetColor(foreground); + texel = ASTBlendPixel(bg, fg, style, alpha); + return NearestColor(texel.s.red, texel.s.green, texel.s.blue); + } + // fallback if all above fails, somehow + // return the background pixel + return background; +} + // -// R_DrawTransColumnInCache +// R_DrawBlendColumnInCache // Draws a translucent column into the cache, applying a half-cooked equation to get a proper translucency value (Needs code in R_GenerateTexture()). // -static inline void R_DrawTransColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +static inline void R_DrawBlendColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) { INT32 count, position; UINT8 *source, *dest; - UINT8 *mytransmap = transtables + ((8*(originPatch->alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); // The equation's not exact but it works as intended. I'll call it a day for now. INT32 topdelta, prevdelta = -1; INT32 originy = originPatch->originy; @@ -258,7 +353,8 @@ static inline void R_DrawTransColumnInCache(column_t *patch, UINT8 *cache, texpa if (count > 0) { for (; dest < cache + position + count; source++, dest++) - if (*dest != 0xFF) *dest = *(mytransmap + ((*dest)<<8) + (*source)); + if (*dest != 0xFF) + *dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha); } patch = (column_t *)((UINT8 *)patch + patch->length + 4); @@ -269,11 +365,10 @@ static inline void R_DrawTransColumnInCache(column_t *patch, UINT8 *cache, texpa // R_DrawTransColumnInCache // Similar to the one above except that the column is inverted. // -static inline void R_DrawTransFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) { INT32 count, position; UINT8 *source, *dest; - UINT8 *mytransmap = transtables + ((8*(originPatch->alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); // The equation's not exact but it works as intended. I'll call it a day for now. INT32 topdelta, prevdelta = -1; INT32 originy = originPatch->originy; @@ -302,7 +397,8 @@ static inline void R_DrawTransFlippedColumnInCache(column_t *patch, UINT8 *cache if (count > 0) { for (; dest < cache + position + count; --source, dest++) - if (*dest != 0xFF) *dest = *(mytransmap + ((*dest)<<8) + (*source)); + if (*dest != 0xFF) + *dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha); } patch = (column_t *)((UINT8 *)patch + patch->length + 4); @@ -422,16 +518,10 @@ static UINT8 *R_GenerateTexture(size_t texnum) for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { static void (*ColumnDrawerPointer)(column_t *, UINT8 *, texpatch_t *, INT32, INT32); // Column drawing function pointer. - if ((patch->style == AST_TRANSLUCENT) && (patch->alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency? - { - if (patch->alpha < 255/11) // Is the patch way too translucent? Don't render then. - continue; - ColumnDrawerPointer = (patch->flip & 2) ? R_DrawTransFlippedColumnInCache : R_DrawTransColumnInCache; - } + if (patch->style != AST_COPY) + ColumnDrawerPointer = (patch->flip & 2) ? R_DrawBlendFlippedColumnInCache : R_DrawBlendColumnInCache; else - { ColumnDrawerPointer = (patch->flip & 2) ? R_DrawFlippedColumnInCache : R_DrawColumnInCache; - } realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); x1 = patch->originx; @@ -848,8 +938,16 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) { Z_Free(texturesToken); texturesToken = M_GetToken(NULL); - if(stricmp(texturesToken, "TRANSLUCENT")==0) + if (stricmp(texturesToken, "TRANSLUCENT")==0) style = AST_TRANSLUCENT; + else if (stricmp(texturesToken, "ADD")==0) + style = AST_ADD; + else if (stricmp(texturesToken, "SUBTRACT")==0) + style = AST_SUBTRACT; + else if (stricmp(texturesToken, "REVERSESUBTRACT")==0) + style = AST_REVERSESUBTRACT; + else if (stricmp(texturesToken, "MODULATE")==0) + style = AST_MODULATE; } else if (stricmp(texturesToken, "FLIPX")==0) flip |= 1; @@ -1615,7 +1713,6 @@ extracolormap_t *R_ColormapForName(char *name) // static double deltas[256][3], map[256][3]; -static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); static int RoundUp(double number); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) @@ -2027,7 +2124,7 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex // Thanks to quake2 source! // utils3/qdata/images.c -static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) { int dr, dg, db; int distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i; diff --git a/src/r_data.h b/src/r_data.h index b6b0a16a1..af1c9114a 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -22,7 +22,12 @@ #endif // Possible alpha types for a patch. -enum patchalphastyle {AST_COPY, AST_TRANSLUCENT}; // , AST_ADD, AST_SUBTRACT, AST_REVERSESUBTRACT, AST_MODULATE, AST_OVERLAY}; +enum patchalphastyle {AST_COPY, AST_TRANSLUCENT, AST_ADD, AST_SUBTRACT, AST_REVERSESUBTRACT, AST_MODULATE, AST_OVERLAY}; + +RGBA_t ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha); +UINT8 ASTBlendPixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 alpha); + +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); // moved here for r_sky.c (texpatch_t is used)