- adjustments and fixes for alphatextures:

* Instead of using the red channel it now uses the grayscale value. While slower in a few situations, it is also more precise and makes the feature more useful.
* For paletted textures do not use the index as alpha anymore but the actual grayscaled color. This is again to make the feature more consistent and useful.
* To compensate for the above there is now a list of hashes for known alpha textures in patch format, so that they don't get broken.
* IMGZ is now considered a grayscale format. There's only two known textures that use IMGZ for something else than crosshairs and those are explicitly handled.
* several smaller fixes.
* the actual color conversion functions for paletted output are now consolidated in a small number of inlines so that future changes are easier to do.

Note: This hasn't been tested yet and will need further changes in the hardware rendering code. As it is it is not production-ready.
This commit is contained in:
Christoph Oelckers 2018-03-22 00:29:01 +01:00
parent b0c96ac43d
commit b473838627
18 changed files with 220 additions and 104 deletions

View file

@ -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

View file

@ -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;

View file

@ -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);
}
}
//----------------------------------------------------------------------------

View file

@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -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];

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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);
}
//==========================================================================
//

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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++;
}

View file

@ -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)
{

View file

@ -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 <vector>
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);

View file

@ -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<Width;x++)
{
int v = LittleShort(*p);
Pixels[x*Height + y] = !alphatex ? RGB256k.RGB[((v >> 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<Width;x++)
{
Pixels[x*Height + y] = !alphatex ? RGB256k.RGB[p[2] >> 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<Width;x++)
{
Pixels[x*Height + y] = !alphatex ? RGB256k.RGB[p[2] >> 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<Width;x++)
{
Pixels[x*Height + y] = !alphatex ? (p[3] >= 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<Height;y++)
for (int y = 0; y < Height; y++)
{
uint8_t * p = ptr + y * Pitch;
for(int x=0;x<Width;x++)
for (int x = 0; x < Width; x++)
{
Pixels[x*Height+y] = !alphatex? FTexture::GrayMap[*p] : *p;
p+=step_x;
Pixels[x*Height + y] = remap[*p];
p += step_x;
}
}
break;
case 16:
for(int y=0;y<Height;y++)
for (int y = 0; y < Height; y++)
{
uint8_t * p = ptr + y * Pitch;
for(int x=0;x<Width;x++)
for (int x = 0; x < Width; x++)
{
Pixels[x*Height+y] = !alphatex ? FTexture::GrayMap[p[1]] : p[1]; // only use the high byte
p+=step_x;
Pixels[x*Height + y] = remap[p[1]]; // only use the high byte
p += step_x;
}
}
break;
default:
break;
}
break;
}
default:
break;
}