diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cfd970d6d..8ad025527 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1097,6 +1097,7 @@ set (PCH_SOURCES textures/flattexture.cpp textures/imgztexture.cpp textures/jpegtexture.cpp + textures/md5check.cpp textures/multipatchtexture.cpp textures/patchtexture.cpp textures/pcxtexture.cpp diff --git a/src/doomtype.h b/src/doomtype.h index bd6c2112b..640aa2d6e 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -128,6 +128,11 @@ struct PalEntry return other; } } + int Luminance() const + { + return (r * 77 + g * 143 + b * 37) >> 8; + } + void Decolorize() // this for 'nocoloredspritelighting' and not the same as desaturation. The normal formula results in a value that's too dark. { int v = (r + g + b); @@ -168,6 +173,12 @@ struct PalEntry #endif }; +inline int Luminance(int r, int g, int b) +{ + return (r * 77 + g * 143 + b * 37) >> 8; +} + + class FTextureID { friend class FTextureManager; diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index f122745a0..5f17c9002 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -997,7 +997,7 @@ void R_InitTranslationTables () { IcePaletteRemap[i] = ColorMatcher.Pick (IcePalette[i][0], IcePalette[i][1], IcePalette[i][2]); } - FRemapTable *remap = translationtables[TRANSLATION_Standard][7]; + FRemapTable *remap = translationtables[TRANSLATION_Standard][STD_Ice]; remap->Remap[0] = 0; remap->Palette[0] = 0; for (i = 1; i < 256; ++i) @@ -1010,9 +1010,9 @@ void R_InitTranslationTables () remap->Palette[i] = PalEntry(255, IcePalette[v][0], IcePalette[v][1], IcePalette[v][2]); } - // The alphatexture translation. Since alphatextures use the red channel this is just a standard grayscale mapping. + // The alphatexture translation. This is just a standard index as gray mapping. PushIdentityTable(TRANSLATION_Standard); - remap = translationtables[TRANSLATION_Standard][8]; + remap = translationtables[TRANSLATION_Standard][STD_Gray]; remap->Remap[0] = 0; remap->Palette[0] = 0; for (i = 1; i < 256; i++) @@ -1020,6 +1020,23 @@ void R_InitTranslationTables () remap->Remap[i] = i; remap->Palette[i] = PalEntry(255, i, i, i); } + + // Palette to grayscale ramp. For internal use only, because the remap does not map to the palette. + PushIdentityTable(TRANSLATION_Standard); + remap = translationtables[TRANSLATION_Standard][STD_Grayscale]; + remap->Remap[0] = 0; + remap->Palette[0] = 0; + for (i = 1; i < 256; i++) + { + int r = GPalette.BaseColors[i].r; + int g = GPalette.BaseColors[i].g; + int b = GPalette.BaseColors[i].b; + int v = (r * 77 + g * 143 + b * 37) >> 8; + + remap->Remap[i] = v; + remap->Palette[i] = PalEntry(255, v, v, v); + } + } //---------------------------------------------------------------------------- diff --git a/src/r_data/r_translate.h b/src/r_data/r_translate.h index 143a8097e..da69745a4 100644 --- a/src/r_data/r_translate.h +++ b/src/r_data/r_translate.h @@ -24,6 +24,13 @@ enum NUM_TRANSLATION_TABLES }; +enum EStandardTranslations +{ + STD_Ice = 7, + STD_Gray = 8, // a 0-255 gray ramp + STD_Grayscale = 9, // desaturated version of the palette. +}; + struct FRemapTable { FRemapTable(int count=256); diff --git a/src/textures/automaptexture.cpp b/src/textures/automaptexture.cpp index c07eded6e..294548f2d 100644 --- a/src/textures/automaptexture.cpp +++ b/src/textures/automaptexture.cpp @@ -98,12 +98,13 @@ uint8_t *FAutomapTexture::MakeTexture (FRenderStyle style) auto Pixels = new uint8_t[Width * Height]; + const uint8_t *remap = GetRemap(style); for (x = 0; x < Width; ++x) { for (y = 0; y < Height; ++y) { auto p = indata[x + 320 * y]; - Pixels[x*Height + y] = (style.Flags & STYLEF_RedIsAlpha) ? p : GPalette.Remap[p]; + Pixels[x*Height + y] = remap[p]; } } return Pixels; diff --git a/src/textures/buildtexture.cpp b/src/textures/buildtexture.cpp index 96e24af21..370bffa05 100644 --- a/src/textures/buildtexture.cpp +++ b/src/textures/buildtexture.cpp @@ -95,7 +95,7 @@ uint8_t *FBuildTexture::MakeTexture(FRenderStyle style) for (int i = 0; i < Width*Height; i++) { auto c = RawPixels[i]; - Pixels[i] = (style.Flags & STYLEF_RedIsAlpha) ? Remap->Palette[c].r : Remap->Remap[c]; + Pixels[i] = (style.Flags & STYLEF_RedIsAlpha) ? Remap->Palette[c].Luminance() : Remap->Remap[c]; } return (uint8_t*)RawPixels; } diff --git a/src/textures/ddstexture.cpp b/src/textures/ddstexture.cpp index 313682f14..f1cfe606e 100644 --- a/src/textures/ddstexture.cpp +++ b/src/textures/ddstexture.cpp @@ -472,16 +472,9 @@ void FDDSTexture::ReadRGB (FileReader &lump, uint8_t *buffer, int pixelmode) if (amask == 0 || (c & amask)) { uint32_t r = (c & RMask) << RShiftL; r |= r >> RShiftR; - if (pixelmode == PIX_Palette) - { - uint32_t g = (c & GMask) << GShiftL; g |= g >> GShiftR; - uint32_t b = (c & BMask) << BShiftL; b |= b >> BShiftR; - *pixelp = RGB256k.RGB[r >> 26][g >> 26][b >> 26]; - } - else - { - *pixelp = uint8_t(r >> 24); - } + uint32_t g = (c & GMask) << GShiftL; g |= g >> GShiftR; + uint32_t b = (c & BMask) << BShiftL; b |= b >> BShiftR; + *pixelp = RGBToPalette(pixelmode == PIX_Palette, r >> 24, g >> 24, b >> 24); } else { @@ -567,10 +560,7 @@ void FDDSTexture::DecompressDXT1 (FileReader &lump, uint8_t *buffer, int pixelmo // Pick colors from the palette for each of the four colors. if (pixelmode != PIX_ARGB) for (i = 3; i >= 0; --i) { - if (pixelmode == PIX_Palette) - palcol[i] = color[i].a ? RGB256k.RGB[color[i].r >> 2][color[i].g >> 2][color[i].b >> 2] : 0; - else - palcol[i] = (color[i].a * color[i].r) / 255; // use the same logic as the hardware renderer. + palcol[i] = RGBToPalette(pixelmode == PIX_Palette, color[i]); } // Now decode this 4x4 block to the pixel buffer. for (y = 0; y < 4; ++y) @@ -650,10 +640,7 @@ void FDDSTexture::DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t // Pick colors from the palette for each of the four colors. if (pixelmode != PIX_ARGB) for (i = 3; i >= 0; --i) { - if (pixelmode == PIX_Palette) - palcol[i] = color[i].a ? RGB256k.RGB[color[i].r >> 2][color[i].g >> 2][color[i].b >> 2] : 0; - else - palcol[i] = (color[i].a * color[i].r) / 255; // use the same logic as the hardware renderer. + palcol[i] = RGBToPalette(pixelmode == PIX_Palette, color[i], false); } // Now decode this 4x4 block to the pixel buffer. @@ -759,10 +746,7 @@ void FDDSTexture::DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t // Pick colors from the palette for each of the four colors. if (pixelmode != PIX_ARGB) for (i = 3; i >= 0; --i) { - if (pixelmode == PIX_Palette) - palcol[i] = color[i].a ? RGB256k.RGB[color[i].r >> 2][color[i].g >> 2][color[i].b >> 2] : 0; - else - palcol[i] = (color[i].a * color[i].r) / 255; // use the same logic as the hardware renderer. + palcol[i] = RGBToPalette(pixelmode == PIX_Palette, color[i], false); } // Now decode this 4x4 block to the pixel buffer. for (y = 0; y < 4; ++y) @@ -787,11 +771,17 @@ void FDDSTexture::DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t { break; } - if (pixelmode == 8) + if (pixelmode == PIX_Palette) { buffer[oy + y + (ox + x) * Height] = alpha[((yalphaslice >> (x*3)) & 7)] < 128 ? (bMasked = true, 0) : palcol[(yslice >> (x + x)) & 3]; } + else if (pixelmode == PIX_Alphatex) + { + int alphaval = alpha[((yalphaslice >> (x * 3)) & 7)]; + int palval = palcol[(yslice >> (x + x)) & 3]; + buffer[oy + y + (ox + x) * Height] = palval * alphaval / 255; + } else { uint8_t * tcp = &buffer[(ox + x)*4 + (oy + y) * Width*4]; diff --git a/src/textures/flattexture.cpp b/src/textures/flattexture.cpp index 7581b3a6e..e3ea1ca89 100644 --- a/src/textures/flattexture.cpp +++ b/src/textures/flattexture.cpp @@ -112,8 +112,7 @@ uint8_t *FFlatTexture::MakeTexture (FRenderStyle style) { memset (Pixels + numread, 0xBB, Width*Height - numread); } - if (!(style.Flags & STYLEF_RedIsAlpha)) FTexture::FlipSquareBlockRemap (Pixels, Width, Height, GPalette.Remap); - else FTexture::FlipSquareBlock(Pixels, Width, Height); + FTexture::FlipSquareBlockRemap(Pixels, Width, Height, GetRemap(style)); return Pixels; } diff --git a/src/textures/imgztexture.cpp b/src/textures/imgztexture.cpp index e21074055..3f3d4c674 100644 --- a/src/textures/imgztexture.cpp +++ b/src/textures/imgztexture.cpp @@ -37,8 +37,12 @@ #include "files.h" #include "w_wad.h" #include "v_palette.h" +#include "v_video.h" +#include "bitmap.h" #include "textures/textures.h" +#include "r_data/r_translate.h" +bool checkIMGZPalette(FileReader &file); //========================================================================== // @@ -61,9 +65,15 @@ class FIMGZTexture : public FWorldTexture uint8_t Reserved[11]; }; + bool isalpha = true; + public: - FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t); + FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t, bool isalpha); uint8_t *MakeTexture (FRenderStyle style) override; + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) override; + + bool UseBasePalette() override { return !isalpha; } + FTextureFormat GetFormat() override { return isalpha ? TEX_RGB : TEX_Pal; } // should be TEX_Gray instead of TEX_RGB. Maybe later when all is working. }; @@ -78,6 +88,7 @@ FTexture *IMGZTexture_TryCreate(FileReader & file, int lumpnum) uint32_t magic = 0; uint16_t w, h; int16_t l, t; + bool ispalette; file.Seek(0, FileReader::SeekSet); if (file.Read(&magic, 4) != 4) return NULL; @@ -86,7 +97,8 @@ FTexture *IMGZTexture_TryCreate(FileReader & file, int lumpnum) h = file.ReadUInt16(); l = file.ReadInt16(); t = file.ReadInt16(); - return new FIMGZTexture(lumpnum, w, h, l, t); + ispalette = checkIMGZPalette(file); + return new FIMGZTexture(lumpnum, w, h, l, t, !ispalette); } //========================================================================== @@ -95,7 +107,7 @@ FTexture *IMGZTexture_TryCreate(FileReader & file, int lumpnum) // //========================================================================== -FIMGZTexture::FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t) +FIMGZTexture::FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t, bool _isalpha) : FWorldTexture(NULL, lumpnum) { Wads.GetLumpName (Name, lumpnum); @@ -103,6 +115,7 @@ FIMGZTexture::FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int1 Height = h; LeftOffset = l; TopOffset = t; + isalpha = _isalpha; CalcBitSize (); } @@ -134,15 +147,16 @@ uint8_t *FIMGZTexture::MakeTexture (FRenderStyle style) auto Pixels = new uint8_t[Width*Height]; dest_p = Pixels; - // Convert the source image from row-major to column-major format + const uint8_t *remap = GetRemap(style, isalpha); + + // Convert the source image from row-major to column-major format and remap it if (!imgz->Compression) { for (int y = Height; y != 0; --y) { for (int x = Width; x != 0; --x) { - auto p = *data; - *dest_p = (style.Flags & STYLEF_RedIsAlpha) ? p : GPalette.Remap[p]; + *dest_p = remap[*data]; dest_p += dest_adv; data++; } @@ -161,8 +175,7 @@ uint8_t *FIMGZTexture::MakeTexture (FRenderStyle style) { if (runlen != 0) { - auto p = *data; - *dest_p = (style.Flags & STYLEF_RedIsAlpha) ? p : GPalette.Remap[p]; + *dest_p = remap[*data]; dest_p += dest_adv; data++; x--; @@ -185,7 +198,7 @@ uint8_t *FIMGZTexture::MakeTexture (FRenderStyle style) else if (code != -128) { setlen = (-code) + 1; - setval = *data++; + setval = remap[*data++]; } } } @@ -195,3 +208,15 @@ uint8_t *FIMGZTexture::MakeTexture (FRenderStyle style) return Pixels; } +//========================================================================== +// +// +// +//========================================================================== + +int FIMGZTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) +{ + if (!isalpha) return FTexture::CopyTrueColorPixels(bmp, x, y, rotate, inf); + else return CopyTrueColorTranslated(bmp, x, y, rotate, translationtables[TRANSLATION_Standard][isalpha ? STD_Gray : STD_Grayscale]->Palette, inf); +} + diff --git a/src/textures/jpegtexture.cpp b/src/textures/jpegtexture.cpp index 33ecaf148..e20ce7759 100644 --- a/src/textures/jpegtexture.cpp +++ b/src/textures/jpegtexture.cpp @@ -321,21 +321,23 @@ uint8_t *FJPEGTexture::MakeTexture (FRenderStyle style) case JCS_RGB: for (int x = Width; x > 0; --x) { - *out = !doalpha? RGB256k.RGB[in[0] >> 2][in[1] >> 2][in[2] >> 2] : in[0]; + *out = RGBToPalette(doalpha, in[0], in[1], in[2]); out += Height; in += 3; } break; case JCS_GRAYSCALE: + { + auto remap = GetRemap(style, true); for (int x = Width; x > 0; --x) { - *out = !doalpha ? FTexture::GrayMap[in[0]] : in[0]; + *out = remap[in[0]]; out += Height; in += 1; } break; - + } case JCS_CMYK: // What are you doing using a CMYK image? :) for (int x = Width; x > 0; --x) @@ -343,13 +345,9 @@ uint8_t *FJPEGTexture::MakeTexture (FRenderStyle style) // To be precise, these calculations should use 255, but // 256 is much faster and virtually indistinguishable. int r = in[3] - (((256 - in[0])*in[3]) >> 8); - if (!doalpha) - { - int g = in[3] - (((256 - in[1])*in[3]) >> 8); - int b = in[3] - (((256 - in[2])*in[3]) >> 8); - *out = RGB256k.RGB[r >> 2][g >> 2][b >> 2]; - } - else *out = (uint8_t)r; + int g = in[3] - (((256 - in[1])*in[3]) >> 8); + int b = in[3] - (((256 - in[2])*in[3]) >> 8); + *out = RGBToPalette(doalpha, r, g, b); out += Height; in += 4; } @@ -361,13 +359,9 @@ uint8_t *FJPEGTexture::MakeTexture (FRenderStyle style) { double Y = in[0], Cb = in[1], Cr = in[2]; int r = clamp((int)(Y + 1.40200 * (Cr - 0x80)), 0, 255); - if (!doalpha) - { - int g = clamp((int)(Y - 0.34414 * (Cb - 0x80) - 0.71414 * (Cr - 0x80)), 0, 255); - int b = clamp((int)(Y + 1.77200 * (Cb - 0x80)), 0, 255); - *out = RGB256k.RGB[r >> 2][g >> 2][b >> 2]; - } - else *out = (uint8_t)r; + int g = clamp((int)(Y - 0.34414 * (Cb - 0x80) - 0.71414 * (Cr - 0x80)), 0, 255); + int b = clamp((int)(Y + 1.77200 * (Cb - 0x80)), 0, 255); + *out = RGBToPalette(doalpha, r, g, b); out += Height; in += 4; } diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 8571f820b..b2e684eff 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -416,13 +416,6 @@ uint8_t *FMultiPatchTexture::MakeTexture (FRenderStyle style) if (style.Flags & STYLEF_RedIsAlpha) { - // The rules here are as follows: - // A texture uses its palette index as alpha only if it reports to use the base palette. - // In summary this means: - // If a texture is marked 'complex', it will use the red channel. - // If a texture uses non-base-palette patches, it will use the red channel for all pixels, even those coming from a base palette patch. - // If a texture only uses base-palette patches and no compositing effects it will use the palette index. - // buildrgb = !UseBasePalette(); } else @@ -449,8 +442,7 @@ uint8_t *FMultiPatchTexture::MakeTexture (FRenderStyle style) { trans = GetBlendMap(Parts[i].Blend, blendwork); } - Parts[i].Texture->CopyToBlock (Pixels, Width, Height, - Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans, style); + Parts[i].Texture->CopyToBlock (Pixels, Width, Height, Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans, style); } } } @@ -469,7 +461,7 @@ uint8_t *FMultiPatchTexture::MakeTexture (FRenderStyle style) { if (*out == 0 && in[3] != 0) { - *out = (style.Flags & STYLEF_RedIsAlpha)? in[2]*in[3] : RGB256k.RGB[in[2]>>2][in[1]>>2][in[0]>>2]; + *out = RGBToPalette(style, in[2], in[1], in[0]); } out += Height; in += 4; diff --git a/src/textures/patchtexture.cpp b/src/textures/patchtexture.cpp index b4a8e3909..f6d396444 100644 --- a/src/textures/patchtexture.cpp +++ b/src/textures/patchtexture.cpp @@ -38,6 +38,8 @@ #include "w_wad.h" #include "templates.h" #include "v_palette.h" +#include "v_video.h" +#include "bitmap.h" #include "textures/textures.h" #include "r_data/r_translate.h" @@ -49,6 +51,7 @@ struct column_t uint8_t length; // length data bytes follows }; +bool checkPatchForAlpha(const void *buffer, uint32_t length); //========================================================================== // @@ -59,10 +62,15 @@ struct column_t class FPatchTexture : public FWorldTexture { bool badflag = false; + bool isalpha = false; public: - FPatchTexture (int lumpnum, patch_t *header); + FPatchTexture (int lumpnum, patch_t *header, bool isalphatex); uint8_t *MakeTexture (FRenderStyle style) override; + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) override; void DetectBadPatches(); + + bool UseBasePalette() override { return !isalpha; } + FTextureFormat GetFormat() override { return isalpha ? TEX_RGB : TEX_Pal; } // should be TEX_Gray instead of TEX_RGB. Maybe later when all is working. }; //========================================================================== @@ -71,7 +79,7 @@ public: // //========================================================================== -static bool CheckIfPatch(FileReader & file) +static bool CheckIfPatch(FileReader & file, bool &isalpha) { if (file.GetLength() < 13) return false; // minimum length of a valid Doom patch @@ -107,6 +115,12 @@ static bool CheckIfPatch(FileReader & file) } } delete [] data; + if (!gapAtStart) + { + // only check this if the texture passed validation. + // Here is a good point because we already have a valid buffer of the lump's data. + isalpha = checkPatchForAlpha(data, file.GetLength()); + } return !gapAtStart; } delete [] data; @@ -122,14 +136,15 @@ static bool CheckIfPatch(FileReader & file) FTexture *PatchTexture_TryCreate(FileReader & file, int lumpnum) { patch_t header; + bool isalpha; - if (!CheckIfPatch(file)) return NULL; + if (!CheckIfPatch(file, isalpha)) return NULL; file.Seek(0, FileReader::SeekSet); header.width = file.ReadUInt16(); header.height = file.ReadUInt16(); header.leftoffset = file.ReadInt16(); header.topoffset = file.ReadInt16(); - return new FPatchTexture(lumpnum, &header); + return new FPatchTexture(lumpnum, &header, isalpha); } //========================================================================== @@ -138,9 +153,10 @@ FTexture *PatchTexture_TryCreate(FileReader & file, int lumpnum) // //========================================================================== -FPatchTexture::FPatchTexture (int lumpnum, patch_t * header) +FPatchTexture::FPatchTexture (int lumpnum, patch_t * header, bool isalphatex) : FWorldTexture(NULL, lumpnum) { + isalpha = isalphatex; Width = header->width; Height = header->height; LeftOffset = header->leftoffset; @@ -169,20 +185,19 @@ uint8_t *FPatchTexture::MakeTexture (FRenderStyle style) if (style.Flags & STYLEF_RedIsAlpha) { - remap = translationtables[TRANSLATION_Standard][8]->Remap; + remap = translationtables[TRANSLATION_Standard][isalpha? STD_Gray : STD_Grayscale]->Remap; } else if (bNoRemap0) { - memcpy (remaptable, GPalette.Remap, 256); + memcpy(remaptable, GPalette.Remap, 256); remaptable[0] = 0; remap = remaptable; } else { - remap = GPalette.Remap; + remap = isalpha? GrayMap : GPalette.Remap; } - if (badflag) { auto Pixels = new uint8_t[Width * Height]; @@ -255,6 +270,17 @@ uint8_t *FPatchTexture::MakeTexture (FRenderStyle style) return Pixels; } +//========================================================================== +// +// +// +//========================================================================== + +int FPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) +{ + if (!isalpha) return FTexture::CopyTrueColorPixels(bmp, x, y, rotate, inf); + else return CopyTrueColorTranslated(bmp, x, y, rotate, translationtables[TRANSLATION_Standard][isalpha ? STD_Gray : STD_Grayscale]->Palette, inf); +} //========================================================================== // diff --git a/src/textures/pcxtexture.cpp b/src/textures/pcxtexture.cpp index f5635c7a3..76d933611 100644 --- a/src/textures/pcxtexture.cpp +++ b/src/textures/pcxtexture.cpp @@ -389,10 +389,9 @@ uint8_t *FPCXTexture::MakeTexture(FRenderStyle style) { if (bitcount < 8) { - for (int i=0;i<16;i++) + for (int i = 0; i < 16; i++) { - if (!alphatex) PaletteMap[i] = ColorMatcher.Pick(header.palette[i * 3], header.palette[i * 3 + 1], header.palette[i * 3 + 2]); - else PaletteMap[i] = header.palette[i * 3]; + PaletteMap[i] = RGBToPalettePrecise(alphatex, header.palette[i * 3], header.palette[i * 3 + 1], header.palette[i * 3 + 2]); } switch (bitcount) @@ -418,7 +417,7 @@ uint8_t *FPCXTexture::MakeTexture(FRenderStyle style) uint8_t r = lump.ReadUInt8(); uint8_t g = lump.ReadUInt8(); uint8_t b = lump.ReadUInt8(); - PaletteMap[i] = !alphatex? ColorMatcher.Pick(r,g,b) : r; + PaletteMap[i] = RGBToPalettePrecise(alphatex, r, g, b); } lump.Seek(sizeof(header), FileReader::SeekSet); ReadPCX8bits (Pixels, lump, &header); @@ -445,7 +444,7 @@ uint8_t *FPCXTexture::MakeTexture(FRenderStyle style) { for(int x=0; x < Width; x++) { - Pixels[y + Height * x] = !alphatex? RGB256k.RGB[row[0] >> 2][row[1] >> 2][row[2] >> 2] : row[0]; + Pixels[y + Height * x] = RGBToPalette(alphatex, row[0], row[1], row[2]); row+=3; } } diff --git a/src/textures/pngtexture.cpp b/src/textures/pngtexture.cpp index 00a7ba701..6dbd169aa 100644 --- a/src/textures/pngtexture.cpp +++ b/src/textures/pngtexture.cpp @@ -381,9 +381,9 @@ void FPNGTexture::ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap) for (int i = 0; i < PaletteSize; i++) { uint8_t r = lump->ReadUInt8(); - lump->ReadUInt8(); // Skip g and b. - lump->ReadUInt8(); - alpharemap[i] = PaletteMap[i] == 0? 0 : r; + uint8_t g = lump->ReadUInt8(); + uint8_t b = lump->ReadUInt8(); + alpharemap[i] = PaletteMap[i] == 0 ? 0 : Luminance(r, g, b); } lump->Seek(p, FileReader::SeekSet); } @@ -493,7 +493,7 @@ uint8_t *FPNGTexture::MakeTexture (FRenderStyle style) } else { - *out++ = alphatex? in[0] : RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2]; + *out++ = RGBToPalette(alphatex, in[0], in[1], in[2]); } in += pitch; } @@ -508,7 +508,7 @@ uint8_t *FPNGTexture::MakeTexture (FRenderStyle style) { for (y = Height; y > 0; --y) { - *out++ = alphatex? ((in[0] * in[1]) >> 8) : in[1] < 128 ? 0 : PaletteMap[in[0]]; + *out++ = alphatex? ((in[0] * in[1]) / 255) : in[1] < 128 ? 0 : PaletteMap[in[0]]; in += pitch; } in -= backstep; @@ -522,7 +522,7 @@ uint8_t *FPNGTexture::MakeTexture (FRenderStyle style) { for (y = Height; y > 0; --y) { - *out++ = alphatex? ((in[0] * in[3]) >> 8) : in[3] < 128 ? 0 : RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2]; + *out++ = RGBToPalette(alphatex, in[0], in[1], in[2], in[3]); in += pitch; } in -= backstep; diff --git a/src/textures/rawpagetexture.cpp b/src/textures/rawpagetexture.cpp index adf8abfff..50faa94b5 100644 --- a/src/textures/rawpagetexture.cpp +++ b/src/textures/rawpagetexture.cpp @@ -177,12 +177,14 @@ uint8_t *FRawPageTexture::MakeTexture (FRenderStyle style) auto Pixels = new uint8_t[Width*Height]; dest_p = Pixels; + const uint8_t *remap = GetRemap(style); + // Convert the source image from row-major to column-major format for (int y = 200; y != 0; --y) { for (int x = 320; x != 0; --x) { - *dest_p = (style.Flags & STYLEF_RedIsAlpha)? *source_p : GPalette.Remap[*source_p]; + *dest_p = remap[*source_p]; dest_p += 200; source_p++; } diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 2b6ec321c..83ea3cdd0 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -754,7 +754,7 @@ void FTexture::FillBuffer(uint8_t *buff, int pitch, int height, FTextureFormat f { case TEX_Pal: case TEX_Gray: - pix = GetPixels(DefaultRenderStyle()); + pix = GetPixels(fmt == TEX_Pal? DefaultRenderStyle() : LegacyRenderStyles[STYLE_Shaded]); stride = pitch - w; for (y = 0; y < h; ++y) { diff --git a/src/textures/textures.h b/src/textures/textures.h index f9aec0b9b..0c175f328 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -37,7 +37,11 @@ #include "doomtype.h" #include "vectors.h" +#include "v_palette.h" +#include "v_video.h" +#include "colormatcher.h" #include "r_data/renderstyle.h" +#include "r_data/r_translate.h" #include struct FloatRect @@ -308,6 +312,52 @@ protected: uint16_t Width, Height, WidthMask; static uint8_t GrayMap[256]; FNativeTexture *Native; + uint8_t *GetRemap(FRenderStyle style, bool srcisgrayscale = false) + { + if (style.Flags & STYLEF_RedIsAlpha) + { + return translationtables[TRANSLATION_Standard][srcisgrayscale ? STD_Gray : STD_Grayscale]->Remap; + } + else + { + return srcisgrayscale ? GrayMap : GPalette.Remap; + } + } + + uint8_t RGBToPalettePrecise(bool wantluminance, int r, int g, int b, int a = 255) + { + if (wantluminance) + { + return (uint8_t)Luminance(r, g, b) * a / 255; + } + else + { + return ColorMatcher.Pick(r, g, b); + } + } + + uint8_t RGBToPalette(bool wantluminance, int r, int g, int b, int a = 255) + { + if (wantluminance) + { + // This is the same formula the OpenGL renderer uses for grayscale textures with an alpha channel. + return (uint8_t)(Luminance(r, g, b) * a / 255); + } + else + { + return a < 128? 0 : RGB256k.RGB[r >> 2][g >> 2][b >> 2]; + } + } + + uint8_t RGBToPalette(bool wantluminance, PalEntry pe, bool hasalpha = true) + { + return RGBToPalette(wantluminance, pe.r, pe.g, pe.b, hasalpha? pe.a : 255); + } + + uint8_t RGBToPalette(FRenderStyle style, int r, int g, int b, int a = 255) + { + return RGBToPalette(!!(style.Flags & STYLEF_RedIsAlpha), r, g, b, a); + } FTexture (const char *name = NULL, int lumpnum = -1); diff --git a/src/textures/tgatexture.cpp b/src/textures/tgatexture.cpp index 4b6430837..1892d0b21 100644 --- a/src/textures/tgatexture.cpp +++ b/src/textures/tgatexture.cpp @@ -248,7 +248,7 @@ uint8_t *FTGATexture::MakeTexture (FRenderStyle style) r=g=b=a=0; break; } - PaletteMap[i] = !alphatex? (a>=128? ColorMatcher.Pick(r, g, b) : 0) : (r * a) >> 8; + PaletteMap[i] = RGBToPalettePrecise(r, g, b, a); } } @@ -307,7 +307,7 @@ uint8_t *FTGATexture::MakeTexture (FRenderStyle style) for(int x=0;x> 10) & 0x1f) * 2][((v >> 5) & 0x1f) * 2][(v & 0x1f) * 2] : ((v >> 10) & 0x1f) * 8; + Pixels[x*Height + y] = RGBToPalette(((v >> 10) & 0x1f) * 8, ((v >> 5) & 0x1f) * 8, (v & 0x1f) * 8); p+=step_x; } } @@ -319,7 +319,7 @@ uint8_t *FTGATexture::MakeTexture (FRenderStyle style) uint8_t * p = ptr + y * Pitch; for(int x=0;x> 2][p[1] >> 2][p[0] >> 2] : p[2]; + Pixels[x*Height + y] = RGBToPalette(p[2], p[1], p[0]); p+=step_x; } } @@ -333,7 +333,7 @@ uint8_t *FTGATexture::MakeTexture (FRenderStyle style) uint8_t * p = ptr + y * Pitch; for(int x=0;x> 2][p[1] >> 2][p[0] >> 2] : p[2]; + Pixels[x*Height + y] = RGBToPalette(p[2], p[1], p[0]); p+=step_x; } } @@ -345,7 +345,7 @@ uint8_t *FTGATexture::MakeTexture (FRenderStyle style) uint8_t * p = ptr + y * Pitch; for(int x=0;x= 128 ? RGB256k.RGB[p[2] >> 2][p[1] >> 2][p[0] >> 2] : 0) : (p[2] * p[3]) >> 8; + Pixels[x*Height + y] = RGBToPalette(p[2], p[1], p[0], p[3]); p+=step_x; } } @@ -358,37 +358,39 @@ uint8_t *FTGATexture::MakeTexture (FRenderStyle style) break; case 3: // Grayscale + { + auto remap = GetRemap(style, true); switch (hdr.bpp) { case 8: - for(int y=0;y