- refactoring of the lookup tables.

This commit is contained in:
Christoph Oelckers 2020-05-23 14:40:54 +02:00
parent daf77e55f7
commit f929419a0a
23 changed files with 406 additions and 538 deletions

View File

@ -34,22 +34,22 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS
LOADITEM PLU[15] = {
{ 0, "NORMAL" },
{ 1, "SATURATE" },
{ 2, "BEAST" },
{ 3, "TOMMY" },
{ 4, "SPIDER3" },
{ 5, "GRAY" },
{ 6, "GRAYISH" },
{ 7, "SPIDER1" },
{ 8, "SPIDER2" },
{ 9, "FLAME" },
{ 10, "COLD" },
{ 11, "P1" },
{ 12, "P2" },
{ 13, "P3" },
{ 14, "P4" }
const char * PLU[15] = {
"NORMAL.PLU",
"SATURATE.PLU",
"BEAST.PLU",
"TOMMY.PLU",
"SPIDER3.PLU",
"GRAY.PLU",
"GRAYISH.PLU",
"SPIDER1.PLU",
"SPIDER2.PLU",
"FLAME.PLU",
"COLD.PLU",
"P1.PLU",
"P2.PLU",
"P3.PLU",
"P4.PLU"
};
const char *PAL[5] = {
@ -68,49 +68,39 @@ bool gFogMode = false;
void scrLoadPLUs(void)
{
// load default palookups
for (int i = 0; i < 15; i++)
// load lookup tables
for (int i = 0; i < MAXPALOOKUPS; i++)
{
DICTNODE *pPlu = gSysRes.Lookup(PLU[i].name, "PLU");
if (!pPlu)
ThrowError("%s.PLU not found", PLU[i].name);
if (pPlu->Size() / 256 != 64)
ThrowError("Incorrect PLU size");
lookuptables[PLU[i].id] = (char*)gSysRes.Lock(pPlu);
int lump = i <= 15 ? fileSystem.FindFile(PLU[i]) : fileSystem.FindResource(i, "PLU");
if (lump < 0)
{
if (i <= 15) I_FatalError("%s.PLU not found", PLU[i]);
else continue;
}
auto data = fileSystem.GetFileData(lump);
if (data.Size() != 64 * 256)
I_FatalError("Incorrect PLU size");
paletteSetLookupTable(i, data.Data());
}
// by NoOne: load user palookups
for (int i = kUserPLUStart; i < MAXPALOOKUPS; i++) {
DICTNODE* pPlu = gSysRes.Lookup(i, "PLU");
if (!pPlu) continue;
else if (pPlu->Size() / 256 != 64) { consoleSysMsg("Incorrect filesize of PLU#%d", i); }
else lookuptables[i] = (char*)gSysRes.Lock(pPlu);
}
#ifdef USE_OPENGL
palookupfog[1].r = 255;
palookupfog[1].g = 255;
palookupfog[1].b = 255;
palookupfog[1].f = 1;
#endif
}
#ifdef USE_OPENGL
glblend_t const bloodglblend =
{
{
{ 1.f/3.f, BLENDFACTOR_SRC_ALPHA, BLENDFACTOR_ONE_MINUS_SRC_ALPHA, 0 },
{ 2.f/3.f, BLENDFACTOR_SRC_ALPHA, BLENDFACTOR_ONE_MINUS_SRC_ALPHA, 0 },
{ 1.f/3.f, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 },
{ 2.f/3.f, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 },
},
};
#endif
void scrLoadPalette(void)
{
#ifdef USE_OPENGL
for (auto& x : glblend)
x = bloodglblend;
#endif
paletteloaded = 0;
Printf("Loading palettes\n");
@ -118,7 +108,7 @@ void scrLoadPalette(void)
{
auto pal = fileSystem.LoadFile(PAL[i]);
if (pal.Size() < 768) I_FatalError("%s: file too small", PAL[i]);
paletteSetColorTable(i, pal.Data());
paletteSetColorTable(i, pal.Data(), false, false);
}
numshades = 64;
paletteloaded |= PALETTE_MAIN;

View File

@ -540,9 +540,9 @@ EXTERN int32_t numframes, randomseed;
EXTERN int16_t sintable[2048];
EXTERN int16_t numshades;
EXTERN char *lookuptables[MAXPALOOKUPS];
EXTERN uint8_t paletteloaded;
EXTERN int32_t maxspritesonscreen;
enum {

View File

@ -28,6 +28,8 @@
#define NORMALPAL (MAXPALOOKUPS - 4)
#define BRIGHTPAL (MAXPALOOKUPS)
extern FString LookupTables[MAXPALOOKUPS];
enum
{
Translation_BasePalettes,
@ -35,35 +37,19 @@ enum
};
extern uint8_t curbasepal;
extern FixedBitArray<256> FullbrightIndices;
extern int32_t r_scenebrightness;
extern uint8_t PaletteIndexFullbrights[32];
inline bool IsPaletteIndexFullbright(uint8_t col)
{
return (PaletteIndexFullbrights[col >> 3] & (1u << (col & 7)));
}
inline void SetPaletteIndexFullbright(int col)
{
PaletteIndexFullbrights[col >> 3] |= (1u << (col & 7));
}
struct palette_t
{
uint8_t r, g, b, f;
};
typedef struct {
uint8_t r, g, b;
} rgb24_t;
extern palette_t palfadergb;
extern unsigned char palfadedelta;
extern PalEntry palfadergb;
void paletteMakeLookupTable(int32_t palnum, const char *remapbuf, uint8_t r, uint8_t g, uint8_t b, char noFloorPal);
void paletteSetColorTable(int32_t id, uint8_t const *table, bool notransparency = false);
void paletteSetColorTable(int32_t id, uint8_t const* table, bool notransparency, bool twodonly);
int32_t paletteSetLookupTable(int32_t palnum, const uint8_t *shtab);
void paletteFreeLookupTable(int32_t palnum);
#include "tflags.h"
enum ESetPalFlag
@ -79,10 +65,16 @@ inline void videoSetBrightness(int brightness)
typedef TFlags<ESetPalFlag> ESetPalFlags;
DEFINE_TFLAGS_OPERATORS(ESetPalFlags)
extern ESetPalFlags curpaletteflags;
void videoSetPalette(int dabrightness, int dapalid, ESetPalFlags flags);
void videoFadePalette(uint8_t r, uint8_t g, uint8_t b, uint8_t offset);
inline void videoFadePalette(uint8_t r, uint8_t g, uint8_t b, uint8_t offset)
{
palfadergb.r = r;
palfadergb.g = g;
palfadergb.b = b;
palfadergb.a = offset;
}
#ifdef USE_OPENGL
void videoTintBlood(int32_t r, int32_t g, int32_t b);
#endif
@ -91,7 +83,6 @@ extern int32_t globalpal;
extern int32_t globalblend;
extern void paletteLoadFromDisk(void);
extern void palettePostLoadTables(void);
extern int32_t curbrightness;
extern int32_t paletteLoadLookupTable(FileReader &fp);
extern void paletteSetupDefaultFog(void);
@ -106,21 +97,6 @@ extern char britable[16][256];
#ifdef USE_OPENGL
extern palette_t palookupfog[MAXPALOOKUPS];
enum
{
BLENDFACTOR_ZERO = 0,
BLENDFACTOR_ONE,
BLENDFACTOR_SRC_COLOR,
BLENDFACTOR_ONE_MINUS_SRC_COLOR,
BLENDFACTOR_SRC_ALPHA,
BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
BLENDFACTOR_DST_ALPHA,
BLENDFACTOR_ONE_MINUS_DST_ALPHA,
BLENDFACTOR_DST_COLOR,
BLENDFACTOR_ONE_MINUS_DST_COLOR,
NUMBLENDFACTORS,
};
typedef struct glblenddef_
{
float alpha;
@ -135,9 +111,9 @@ typedef struct glblend_
extern glblend_t const nullglblend, defaultglblend;
extern glblend_t glblend[MAXBLENDTABS];
FRenderStyle GetBlend(int blend, int def);
extern void handle_blend(uint8_t enable, uint8_t blend, uint8_t def);
float float_trans(uint32_t maskprops, uint8_t blend);
FRenderStyle GetRenderStyle(int blend, int def);
extern void SetRenderStyleFromBlend(uint8_t enable, uint8_t blend, uint8_t def);
float GetAlphaFromBlend(uint32_t maskprops, uint32_t blend);
#endif

View File

@ -24,7 +24,6 @@ void polymost_outputGLDebugMessage(uint8_t severity, const char* format, ...);
//void phex(char v, char *s);
void uploadbasepalette(int32_t basepalnum);
void uploadpalswaps(int count, int32_t *palookupnum);
void polymost_drawsprite(int32_t snum);
void polymost_drawmaskwall(int32_t damaskwallcnt);
void polymost_dorotatespritemodel(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, int32_t uniqid);

View File

@ -2040,7 +2040,7 @@ static int32_t defsparser(scriptfile *script)
// NOTE: all palookups are initialized, i.e. non-NULL!
// NOTE2: aliasing (pal==remappal) is OK
paletteMakeLookupTable(pal, lookuptables[remappal], red<<2, green<<2, blue<<2,
paletteMakeLookupTable(pal, LookupTables[remappal].GetChars(), red<<2, green<<2, blue<<2,
remappal==0 ? 1 : (nofloorpal == -1 ? g_noFloorPal[remappal] : nofloorpal));
}
break;
@ -2658,7 +2658,7 @@ static int32_t defsparser(scriptfile *script)
palbuf[k] <<= shiftleft;
}
paletteSetColorTable(id, palbuf.Data());
paletteSetColorTable(id, palbuf.Data(), false, false);
didLoadPal = 1;
break;
}
@ -2862,15 +2862,8 @@ static int32_t defsparser(scriptfile *script)
break;
}
uint8_t const * const sourcepal = (uint8_t *)lookuptables[source];
if (EDUKE32_PREDICT_FALSE(sourcepal == NULL))
{
Printf("Error: palookup: Source palookup does not exist on line %s:%d\n",
script->filename, scriptfile_getlinum(script,cmdtokptr));
break;
}
paletteSetLookupTable(id, sourcepal);
if (LookupTables[source].IsNotEmpty() || id > 0) // do not overwrite the base with an empty table.
LookupTables[id] = LookupTables[source];
didLoadShade = 1;
break;
}
@ -2993,8 +2986,7 @@ static int32_t defsparser(scriptfile *script)
}
case T_UNDEF:
{
paletteFreeLookupTable(id);
LookupTables[id] = "";
didLoadShade = 0;
if (id == 0)
paletteloaded &= ~PALETTE_SHADE;
@ -3228,16 +3220,16 @@ static int32_t defsparser(scriptfile *script)
uint8_t * const factor = glblenddeftoken == T_SRC ? &glbdef->src : &glbdef->dst;
switch (factortoken)
{
case T_ZERO: *factor = BLENDFACTOR_ZERO; break;
case T_ONE: *factor = BLENDFACTOR_ONE; break;
case T_SRC_COLOR: *factor = BLENDFACTOR_SRC_COLOR; break;
case T_ONE_MINUS_SRC_COLOR: *factor = BLENDFACTOR_ONE_MINUS_SRC_COLOR; break;
case T_SRC_ALPHA: *factor = BLENDFACTOR_SRC_ALPHA; break;
case T_ONE_MINUS_SRC_ALPHA: *factor = BLENDFACTOR_ONE_MINUS_SRC_ALPHA; break;
case T_DST_ALPHA: *factor = BLENDFACTOR_DST_ALPHA; break;
case T_ONE_MINUS_DST_ALPHA: *factor = BLENDFACTOR_ONE_MINUS_DST_ALPHA; break;
case T_DST_COLOR: *factor = BLENDFACTOR_DST_COLOR; break;
case T_ONE_MINUS_DST_COLOR: *factor = BLENDFACTOR_ONE_MINUS_DST_COLOR; break;
case T_ZERO: *factor = STYLEALPHA_Zero; break;
case T_ONE: *factor = STYLEALPHA_One; break;
case T_SRC_COLOR: *factor = STYLEALPHA_SrcCol; break;
case T_ONE_MINUS_SRC_COLOR: *factor = STYLEALPHA_InvSrcCol; break;
case T_SRC_ALPHA: *factor = STYLEALPHA_Src; break;
case T_ONE_MINUS_SRC_ALPHA: *factor = STYLEALPHA_InvSrc; break;
case T_DST_ALPHA: *factor = STYLEALPHA_Dst; break;
case T_ONE_MINUS_DST_ALPHA: *factor = STYLEALPHA_InvDst; break;
case T_DST_COLOR: *factor = STYLEALPHA_DstCol; break;
case T_ONE_MINUS_DST_COLOR: *factor = STYLEALPHA_InvDstCol; break;
}
#else
UNREFERENCED_PARAMETER(factortoken);
@ -3349,7 +3341,7 @@ static int32_t defsparser(scriptfile *script)
}
for (bssize_t i = id0; i <= id1; i++)
paletteFreeLookupTable(i);
LookupTables[i] = "";
if (id0 == 0)
paletteloaded &= ~PALETTE_SHADE;

View File

@ -69,7 +69,6 @@ bool playing_rr;
bool playing_blood;
int32_t rendmode=0;
int32_t glrendmode = REND_POLYMOST;
int32_t r_scenebrightness = 0;
int32_t r_rortexture = 0;
int32_t r_rortexturerange = 0;
int32_t r_rorphase = 0;
@ -2054,6 +2053,8 @@ int32_t enginePreInit(void)
}
void (*paletteLoadFromDisk_replace)(void) = NULL; // replacement hook for Blood.
//
// initengine
//
@ -2094,7 +2095,14 @@ int32_t engineInit(void)
maxspritesonscreen = MAXSPRITESONSCREEN;
paletteLoadFromDisk();
if (paletteLoadFromDisk_replace)
{
paletteLoadFromDisk_replace();
}
else
{
paletteLoadFromDisk();
}
#ifdef USE_OPENGL
if (!mdinited) mdinit();
@ -2123,7 +2131,6 @@ int32_t enginePostInit(void)
//
// uninitengine
//
void paletteFreeAll();
void engineUnInit(void)
{
@ -2138,8 +2145,6 @@ void engineUnInit(void)
TileFiles.CloseAll();
paletteFreeAll();
for (bssize_t i = 0; i < num_usermaphacks; i++)
{
Xfree(usermaphacks[i].mhkfile);

View File

@ -1602,7 +1602,7 @@ static int32_t polymost_md3draw(md3model_t *m, tspriteptr_t tspr)
pc[3] = (tspr->cstat&2) ? glblend[tspr->blend].def[!!(tspr->cstat&512)].alpha : 1.0f;
pc[3] *= 1.0f - sext->alpha;
handle_blend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512));
SetRenderStyleFromBlend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512));
if (m->usesalpha) //Sprites with alpha in texture
{

View File

@ -19,16 +19,16 @@
#include "palettecontainer.h"
#include "palutil.h"
#include "colormatcher.h"
#include "m_swap.h"
#include "../../glbackend/glbackend.h"
FMemArena lookuparena;
// FString is a nice and convenient way to have automatically managed shared storage.
FString LookupTables[MAXPALOOKUPS];
uint8_t curbasepal;
int32_t globalblend;
palette_t palfadergb = { 0, 0, 0, 0 };
unsigned char palfadedelta = 0;
ESetPalFlags curpaletteflags;
PalEntry palfadergb;
#if defined(USE_OPENGL)
palette_t palookupfog[MAXPALOOKUPS];
@ -39,32 +39,15 @@ palette_t palookupfog[MAXPALOOKUPS];
// NOTE: g_noFloorPal[0] is irrelevant as it's never checked.
int8_t g_noFloorPal[MAXPALOOKUPS];
int32_t curbrightness = 0;
FixedBitArray<256> FullbrightIndices;
void setBlendFactor(int index, int alpha);
//==========================================================================
//
// Adds a palette to the global list of base palettes
//
//==========================================================================
int DetermineTranslucency(const uint8_t *table)
{
uint8_t index;
PalEntry newcolor;
PalEntry newcolor2;
index = table[GPalette.BlackIndex * 256 + GPalette.WhiteIndex];
newcolor = GPalette.BaseColors[index];
index = table[GPalette.WhiteIndex * 256 + GPalette.BlackIndex];
newcolor2 = GPalette.BaseColors[index];
if (newcolor2.r == 255) // if black on white results in white it's either
// fully transparent or additive
{
return -newcolor.r;
}
return newcolor.r;
}
void paletteSetColorTable(int32_t id, uint8_t const* table, bool notransparency)
void paletteSetColorTable(int32_t id, uint8_t const* table, bool notransparency, bool twodonly)
{
if (id == 0)
{
@ -77,6 +60,7 @@ void paletteSetColorTable(int32_t id, uint8_t const* table, bool notransparency)
remap.Palette[255] = 0;
remap.Remap[255] = 255;
}
remap.Inactive = twodonly; // use Inactive as a marker for the postprocessing so that for pure 2D palettes the creation of shade tables can be skipped.
GPalette.UpdateTranslation(TRANSLATION(Translation_BasePalettes, id), &remap);
// Todo: remove this once the texture code can use GPalette directly
@ -85,45 +69,18 @@ void paletteSetColorTable(int32_t id, uint8_t const* table, bool notransparency)
#endif
}
void fullscreen_tint_gl(PalEntry pe);
static void alloc_palookup(int32_t pal)
{
// The asm functions vlineasm1, mvlineasm1 (maybe others?) access the next
// lookuptables[...] shade entry for tilesizy==512 tiles.
// See DEBUG_TILESIZY_512 and the comment in a.nasm: vlineasm1.
lookuptables[pal] = (char *) Xaligned_alloc(16, (numshades + 1) * 256);
memset(lookuptables[pal], 0, (numshades + 1) * 256);
}
static void maybe_alloc_palookup(int32_t palnum);
void (*paletteLoadFromDisk_replace)(void) = NULL;
inline bool read_and_test(FileReader& handle, void* buffer, int32_t leng)
{
return handle.Read(buffer, leng) != leng;
};
//==========================================================================
//
// loadpalette (internal)
// loads the main palette file.
//
//==========================================================================
void paletteLoadFromDisk(void)
{
GPalette.Init(MAXPALOOKUPS + 1); // one slot for each translation, plus a separate one for the base palettes.
#ifdef USE_OPENGL
for (auto & x : glblend)
x = defaultglblend;
#endif
if (paletteLoadFromDisk_replace)
{
paletteLoadFromDisk_replace();
return;
}
auto fil = fileSystem.OpenFileReader("palette.dat");
if (!fil.isOpen())
@ -139,16 +96,11 @@ void paletteLoadFromDisk(void)
for (unsigned char & k : palette)
k <<= 2;
paletteSetColorTable(0, palette);
paletteSetColorTable(0, palette, false, false);
paletteloaded |= PALETTE_MAIN;
// PALETTE_SHADES
if (2 != fil.Read(&numshades, 2))
return;
numshades = B_LITTLE16(numshades);
numshades = fil.ReadInt16();
if (numshades <= 1)
{
@ -157,397 +109,266 @@ void paletteLoadFromDisk(void)
return;
}
// Auto-detect LameDuke. Its PALETTE.DAT doesn't have a 'numshades' 16-bit
// int after the base palette, but starts directly with the shade tables.
// Thus, the first two bytes will be 00 01, which is 256 if read as
// little-endian int16_t.
int32_t lamedukep = 0;
if (numshades >= 256)
#if 0
// Reminder: Witchaven's shade table has no index and no easy means to autodetect.
if (numshades == 0 && (g_gameType & GAMEFLAG_WITCHAVEN))
{
uint16_t temp;
if (read_and_test(fil, &temp, 2))
return;
temp = B_LITTLE16(temp);
if (temp == 770 || numshades > 256) // 02 03
numshades = 32;
fil.Seek(-2, FileReader::SeekCur);
}
else
#endif
{
// LameDuke's is yet another variant.
if (numshades >= 256)
{
if (fil.Seek(-4, FileReader::SeekCur) < 0)
uint16_t temp = fil.ReadUInt16();
if (temp == 770 || numshades > 256) // 02 03
{
Printf("Warning: seek failed in loadpalette()!\n");
return;
fil.Seek(-4, FileReader::SeekCur);
numshades = 32;
}
numshades = 32;
lamedukep = 1;
}
else
{
if (fil.Seek(-2, FileReader::SeekCur) < 0)
else
{
Printf("Warning: seek failed in loadpalette()!\n");
return;
fil.Seek(-2, FileReader::SeekCur);
}
}
}
// Read base shade table (lookuptables 0).
maybe_alloc_palookup(0);
if (read_and_test(fil, lookuptables[0], numshades<<8))
int length = numshades * 256;
auto p = LookupTables[0].LockNewBuffer(length);
auto count = fil.Read(p, length);
LookupTables->UnlockBuffer();
if (count != length)
return;
paletteloaded |= PALETTE_SHADE;
paletteloaded |= PALETTE_TRANSLUC;
// additional blending tables
uint8_t magic[12];
if (!read_and_test(fil, magic, sizeof(magic)) && !Bmemcmp(magic, "MoreBlendTab", sizeof(magic)))
{
uint8_t addblendtabs;
if (read_and_test(fil, &addblendtabs, 1))
{
Printf("Warning: failed reading additional blending table count\n");
return;
}
uint8_t blendnum;
char *tab = (char *) Xmalloc(256*256);
for (bssize_t i=0; i<addblendtabs; i++)
{
if (read_and_test(fil, &blendnum, 1))
{
Printf("Warning: failed reading additional blending table index\n");
Xfree(tab);
return;
}
if (read_and_test(fil, tab, 256*256))
{
Printf("Warning: failed reading additional blending table\n");
Xfree(tab);
return;
}
setBlendFactor(blendnum, DetermineTranslucency((const uint8_t*)tab));
}
Xfree(tab);
// Read log2 of count of alpha blending tables.
uint8_t lognumalphatabs;
if (!read_and_test(fil, &lognumalphatabs, 1))
{
if (!(lognumalphatabs >= 1 && lognumalphatabs <= 7))
Printf("invalid lognumalphatabs value, must be in [1 .. 7]\n");
else
numalphatabs = 1<<lognumalphatabs;
}
}
}
uint8_t PaletteIndexFullbrights[32];
//==========================================================================
//
// postprocess the palette data after everything has been loaded
//
//==========================================================================
void palettePostLoadTables(void)
{
globalpal = 0;
char const * const palookup0 = lookuptables[0];
auto lookup = (const uint8_t*)LookupTables[0].GetChars();
ImageHelpers::SetPalette(GPalette.BaseColors);
// Bmemset(PaletteIndexFullbrights, 0, sizeof(PaletteIndexFullbrights));
for (bssize_t c = 0; c < 255; ++c) // skipping transparent color
for (int c = 0; c < 255; ++c) // skipping transparent color
{
uint8_t const index = palookup0[c];
uint8_t index = lookup[c];
PalEntry color = GPalette.BaseColors[index];
// don't consider #000000 fullbright
if (color.r == 0 && color.g == 0 && color.b == 0)
continue;
// don't consider black fullbright
if (color.isBlack()) continue;
for (size_t s = c + 256, s_end = 256*numshades; s < s_end; s += 256)
if (palookup0[s] != index)
goto PostLoad_NotFullbright;
bool isbright = true;
for (int i = 1; i < numshades; i++)
if (lookup[i * 256 + c] != index)
{
isbright = false;
break;
}
SetPaletteIndexFullbright(c);
PostLoad_NotFullbright: ;
if (isbright) FullbrightIndices.Set(c);
}
}
//==========================================================================
//
// Ensure that all lookups map 255 to itself to preserve transparency.
//
//==========================================================================
void paletteFixTranslucencyMask(void)
{
for (auto thispalookup : lookuptables)
for (auto &thispalookup : LookupTables)
{
if (thispalookup == NULL)
if (thispalookup.IsEmpty())
continue;
for (bssize_t j=0; j<numshades; j++)
thispalookup[(j<<8) + 255] = 255;
for (int j = 0; j < numshades; j++)
{
auto p = thispalookup.LockBuffer();
p[(j << 8) + 255] = 255;
thispalookup.UnlockBuffer();
}
}
}
// Load LOOKUP.DAT, which contains lookup tables and additional base palettes.
//==========================================================================
//
// <fp>: open file handle
// load the lookup tables from lookup.dat
//
// Returns:
// - on success, 0
// - on error, -1 (didn't read enough data)
// - -2: error, we already wrote an error message ourselves
//==========================================================================
int32_t paletteLoadLookupTable(FileReader &fp)
{
uint8_t numlookups;
char remapbuf[256];
if (1 != fp.Read(&numlookups, 1))
int numlookups = fp.ReadUInt8();
if (numlookups < 1)
return -1;
for (bssize_t j=0; j<numlookups; j++)
for (int j=0; j<numlookups; j++)
{
uint8_t palnum;
if (1 != fp.Read(&palnum, 1))
return -1;
if (palnum >= 256-RESERVEDPALS)
{
Printf("ERROR: attempt to load lookup at reserved pal %d\n", palnum);
return -2;
}
int palnum = fp.ReadUInt8();
if (256 != fp.Read(remapbuf, 256))
return -1;
paletteMakeLookupTable(palnum, remapbuf, 0, 0, 0, 0);
if (palnum >= 256 - RESERVEDPALS)
{
Printf("ERROR: attempt to load lookup at reserved pal %d\n", palnum);
}
else
paletteMakeLookupTable(palnum, remapbuf, 0, 0, 0, 0);
}
return 0;
}
//==========================================================================
//
// Find a gap of four consecutive unused pal numbers to generate fog shade tables.
//
//==========================================================================
void paletteSetupDefaultFog(void)
{
// Find a gap of four consecutive unused pal numbers to generate fog shade
// tables.
for (bssize_t j=1; j<=255-3; j++)
if (!lookuptables[j] && !lookuptables[j+1] && !lookuptables[j+2] && !lookuptables[j+3])
for (int j = 1; j <= 255 - 3; j++)
{
if (!LookupTables[j].IsEmpty() && !LookupTables[j + 1].IsEmpty() && !LookupTables[j + 2].IsEmpty() && !LookupTables[j + 3].IsEmpty())
{
paletteMakeLookupTable(j, NULL, 60, 60, 60, 1);
paletteMakeLookupTable(j+1, NULL, 60, 0, 0, 1);
paletteMakeLookupTable(j+2, NULL, 0, 60, 0, 1);
paletteMakeLookupTable(j+3, NULL, 0, 0, 60, 1);
paletteMakeLookupTable(j + 1, NULL, 60, 0, 0, 1);
paletteMakeLookupTable(j + 2, NULL, 0, 60, 0, 1);
paletteMakeLookupTable(j + 3, NULL, 0, 0, 60, 1);
break;
}
}
}
//==========================================================================
//
// post process the lookup tables once everything has been loaded
//
//==========================================================================
void palettePostLoadLookups(void)
{
// Alias remaining unused pal numbers to the base shade table.
for (bssize_t j=1; j<MAXPALOOKUPS; j++)
{
// If an existing lookup is identical to #0, free it.
if (lookuptables[j] && lookuptables[j] != lookuptables[0] && !Bmemcmp(lookuptables[0], lookuptables[j], 256*numshades))
paletteFreeLookupTable(j);
int numpalettes = GPalette.NumTranslations(Translation_BasePalettes);
if (numpalettes == 0) return;
auto basepalette = GPalette.GetTranslation(Translation_BasePalettes, 0);
if (!lookuptables[j])
paletteMakeLookupTable(j, NULL, 0, 0, 0, 1);
for (int l = 0; l < MAXPALOOKUPS; l++)
{
if (!LookupTables[l].IsEmpty())
{
const uint8_t* lookup = (uint8_t*)LookupTables[l].GetChars();
FRemapTable remap;
for (int i = 0; i < numpalettes; i++)
{
auto palette = GPalette.GetTranslation(Translation_BasePalettes, i);
if (!palette) continue;
if (i == 0 || (palette != basepalette && !palette->Inactive))
{
memcpy(remap.Remap, lookup, 256);
for (int j = 0; j < 256; j++)
{
remap.Palette[j] = palette->Palette[remap.Remap[j]];
}
remap.NumEntries = 256;
GPalette.UpdateTranslation(TRANSLATION(i + 1, l), &remap);
}
if (palette != basepalette) palette->Inactive = false; // clear the marker flag
}
}
}
// todo: at this point we should swap colors 0 and 255 so that paletted images being created here have their transparent color at index 0.
}
static int32_t palookup_isdefault(int32_t palnum) // KEEPINSYNC engine.lua
{
return (lookuptables[palnum] == NULL || (palnum!=0 && lookuptables[palnum] == lookuptables[0]));
}
static void maybe_alloc_palookup(int32_t palnum)
{
if (palookup_isdefault(palnum))
{
alloc_palookup(palnum);
if (lookuptables[palnum] == NULL)
Bexit(1);
}
}
#ifdef USE_OPENGL
glblend_t const nullglblend =
{
{
{ 1.f, BLENDFACTOR_ONE, BLENDFACTOR_ZERO, 0 },
{ 1.f, BLENDFACTOR_ONE, BLENDFACTOR_ZERO, 0 },
},
};
glblend_t const defaultglblend =
{
{
{ 2.f/3.f, BLENDFACTOR_SRC_ALPHA, BLENDFACTOR_ONE_MINUS_SRC_ALPHA, 0 },
{ 1.f/3.f, BLENDFACTOR_SRC_ALPHA, BLENDFACTOR_ONE_MINUS_SRC_ALPHA, 0 },
},
};
glblend_t glblend[MAXBLENDTABS];
void setBlendFactor(int index, int alpha)
{
if (index >= 0 && index < MAXBLENDTABS)
{
auto& myblend = glblend[index];
if (index >= 0)
{
myblend.def[0].alpha = index / 255.f;
myblend.def[1].alpha = 1.f - (index / 255.f);
myblend.def[0].src = myblend.def[1].src = BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
myblend.def[0].dst = myblend.def[1].dst = BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
}
else
{
myblend.def[0].alpha = 1;
myblend.def[1].alpha = 1;
myblend.def[0].src = myblend.def[1].src = BLENDFACTOR_ONE;
myblend.def[0].dst = myblend.def[1].dst = BLENDFACTOR_ONE;
}
}
}
FRenderStyle GetBlend(int blend, int def)
{
static uint8_t const blendFuncTokens[NUMBLENDFACTORS] =
{
STYLEALPHA_Zero,
STYLEALPHA_One,
STYLEALPHA_SrcCol,
STYLEALPHA_InvSrcCol,
STYLEALPHA_Src,
STYLEALPHA_InvSrc,
STYLEALPHA_Dst,
STYLEALPHA_InvDst,
STYLEALPHA_DstCol,
STYLEALPHA_InvDstCol,
};
FRenderStyle rs;
rs.BlendOp = STYLEOP_Add;
glblenddef_t const* const glbdef = glblend[blend].def + def;
rs.SrcAlpha = blendFuncTokens[glbdef->src];
rs.DestAlpha = blendFuncTokens[glbdef->dst];
rs.Flags = 0;
return rs;
}
void handle_blend(uint8_t enable, uint8_t blend, uint8_t def)
{
if (!enable)
{
GLInterface.SetRenderStyle(LegacyRenderStyles[STYLE_Translucent]);
return;
}
auto rs = GetBlend(blend, def);
GLInterface.SetRenderStyle(rs);
}
float float_trans(uint32_t maskprops, uint8_t blend)
{
switch (maskprops)
{
case DAMETH_TRANS1:
case DAMETH_TRANS2:
return glblend[blend].def[maskprops - 2].alpha;
default:
return 1.0f;
}
}
#endif
//==========================================================================
//
// set a lookup table from external data
//
//==========================================================================
int32_t paletteSetLookupTable(int32_t palnum, const uint8_t *shtab)
{
if (shtab != NULL)
{
maybe_alloc_palookup(palnum);
Bmemcpy(lookuptables[palnum], shtab, 256*numshades);
int length = numshades * 256;
auto p = LookupTables[palnum].LockNewBuffer(length);
memcpy(p, shtab, length);
LookupTables->UnlockBuffer();
}
return 0;
}
void paletteFreeLookupTable(int32_t const palnum)
{
if (palnum == 0 && lookuptables[palnum] != NULL)
{
for (bssize_t i = 1; i < MAXPALOOKUPS; i++)
if (lookuptables[i] == lookuptables[palnum])
lookuptables[i] = NULL;
ALIGNED_FREE_AND_NULL(lookuptables[palnum]);
}
else if (lookuptables[palnum] == lookuptables[0])
lookuptables[palnum] = NULL;
else
ALIGNED_FREE_AND_NULL(lookuptables[palnum]);
}
//==========================================================================
//
// makepalookup
// creates a lookup table from scratch
//
//==========================================================================
void paletteMakeLookupTable(int32_t palnum, const char *remapbuf, uint8_t r, uint8_t g, uint8_t b, char noFloorPal)
{
int32_t i, j;
static char idmap[256] = { 1 };
if (paletteloaded == 0)
return;
char idmap[256];
// NOTE: palnum==0 is allowed
if ((unsigned) palnum >= MAXPALOOKUPS)
if (paletteloaded == 0 || (unsigned)palnum >= MAXPALOOKUPS)
return;
g_noFloorPal[palnum] = noFloorPal;
if (remapbuf==NULL)
if (remapbuf == nullptr)
{
if ((r|g|b) == 0)
if (r == 0 || g == 0 || b == 0)
{
lookuptables[palnum] = lookuptables[0]; // Alias to base shade table!
LookupTables[palnum] = ""; // clear this entry so that later it can be filled with the base remap.
return;
}
if (idmap[0]==1) // init identity map
for (i=0; i<256; i++)
idmap[i] = i;
for (int i = 0; i < 256; i++) idmap[i] = i;
remapbuf = idmap;
}
maybe_alloc_palookup(palnum);
if ((r|g|b) == 0)
int length = numshades * 256;
auto p = LookupTables[palnum].LockNewBuffer(length);
if (r == 0 || g == 0 || b == 0)
{
// "black fog"/visibility case -- only remap color indices
for (j=0; j<numshades; j++)
for (i=0; i<256; i++)
auto src = (const uint8_t*)LookupTables[0].GetChars();
for (int j = 0; j < numshades; j++)
for (int i = 0; i < 256; i++)
{
const char *src = lookuptables[0];
lookuptables[palnum][256*j + i] = src[256*j + remapbuf[i]];
p[256 * j + i] = src[256 * j + remapbuf[i]];
}
}
else
{
// colored fog case
char *ptr2 = lookuptables[palnum];
for (i=0; i<numshades; i++)
for (int i = 0; i < numshades; i++)
{
int32_t palscale = divscale16(i, numshades-1);
for (j=0; j<256; j++)
for (int j = 0; j < 256; j++)
{
PalEntry pe = GPalette.BaseColors[remapbuf[j]];
*ptr2++ = ColorMatcher.Pick(pe.r + mulscale16(r-pe.r, palscale),
pe.g + mulscale16(g-pe.g, palscale),
pe.b + mulscale16(b-pe.b, palscale));
p[j] = ColorMatcher.Pick(
pe.r + Scale(r - pe.r, i, numshades - 1),
pe.g + Scale(g - pe.g, i, numshades - 1),
pe.b + Scale(b - pe.b, i, numshades - 1));
}
}
}
@ -560,50 +381,59 @@ void paletteMakeLookupTable(int32_t palnum, const char *remapbuf, uint8_t r, uin
#endif
}
//
// setbrightness
//
// flags:
// 1: don't setpalette(), not checked anymore.
// 2: don't gltexinvalidateall()
// 4: don't calc curbrightness from dabrightness, DON'T USE THIS FLAG!
// 8: don't gltexinvalidate8()
// 16: don't reset palfade*
void videoSetPalette(int dabrightness, int dapalid, ESetPalFlags flags)
void videoSetPalette(int dabrightness, int palid, ESetPalFlags flags)
{
if (GPalette.GetTranslation(Translation_BasePalettes, dapalid) == nullptr)
dapalid = 0;
curbasepal = dapalid;
if ((flags & Pal_DontResetFade) == 0)
{
palfadergb.r = palfadergb.g = palfadergb.b = 0;
palfadedelta = 0;
}
curpaletteflags = flags;
curbasepal = (GPalette.GetTranslation(Translation_BasePalettes, palid) == nullptr)? 0 : palid;
if ((flags & Pal_DontResetFade) == 0) palfadergb = 0;
}
//==========================================================================
//
// setpalettefade
// map Build blend definitions to actual render style / alpha combos.
//
void videoFadePalette(uint8_t r, uint8_t g, uint8_t b, uint8_t offset)
//==========================================================================
glblend_t const nullglblend =
{
palfadergb.r = r;
palfadergb.g = g;
palfadergb.b = b;
palfadedelta = offset;
{
{ 1.f, STYLEALPHA_One, STYLEALPHA_Zero, 0 },
{ 1.f, STYLEALPHA_One, STYLEALPHA_Zero, 0 },
},
};
glblend_t const defaultglblend =
{
{
{ 2.f / 3.f, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 },
{ 1.f / 3.f, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 },
},
};
glblend_t glblend[MAXBLENDTABS];
FRenderStyle GetRenderStyle(int blend, int def)
{
FRenderStyle rs;
rs.BlendOp = STYLEOP_Add;
auto glbdef = &glblend[blend].def[def];
rs.SrcAlpha = glbdef->src;
rs.DestAlpha = glbdef->dst;
rs.Flags = 0;
return rs;
}
void paletteFreeAll()
void SetRenderStyleFromBlend(uint8_t enable, uint8_t blend, uint8_t def)
{
paletteloaded = 0;
if (!enable)
{
GLInterface.SetRenderStyle(LegacyRenderStyles[STYLE_Translucent]);
return;
}
auto rs = GetRenderStyle(blend, def);
GLInterface.SetRenderStyle(rs);
}
for (bssize_t i = 0; i < MAXPALOOKUPS; i++)
if (i == 0 || lookuptables[i] != lookuptables[0])
{
// Take care of handling aliased ^^^ cases!
Xaligned_free(lookuptables[i]);
}
Bmemset(lookuptables, 0, sizeof(lookuptables));
}
float GetAlphaFromBlend(uint32_t method, uint32_t blend)
{
return method == DAMETH_TRANS1 || method == DAMETH_TRANS2 ? glblend[blend].def[method - DAMETH_TRANS1].alpha : 1.f;
}

View File

@ -92,6 +92,7 @@ static float dxb1[MAXWALLSB], dxb2[MAXWALLSB];
#define SOFTROTMAT 0
static int32_t r_pogoDebug = 0;
int32_t r_scenebrightness = 0;
static float gviewxrange;
static float ghoriz, ghoriz2;
@ -232,7 +233,7 @@ static void polymost_glinit()
}
for (int palookupnum = 0; palookupnum < MAXPALOOKUPS; ++palookupnum)
{
GLInterface.SetPalswapData(palookupnum, (uint8_t*)lookuptables[palookupnum], numshades+1, palookupfog[palookupnum]);
GLInterface.SetPalswapData(palookupnum, (uint8_t*)LookupTables[palookupnum].GetChars(), numshades+1, palookupfog[palookupnum]);
}
}
@ -289,22 +290,12 @@ void uploadbasepalette(int32_t basepalnum)
basepalWFullBrightInfo[i*4+0] = remap->Palette[i].b;
basepalWFullBrightInfo[i*4+1] = remap->Palette[i].g;
basepalWFullBrightInfo[i*4+2] = remap->Palette[i].r;
basepalWFullBrightInfo[i*4+3] = 0-(IsPaletteIndexFullbright(i) != 0);
basepalWFullBrightInfo[i*4+3] = 0-(FullbrightIndices[i] != 0);
}
GLInterface.SetPaletteData(basepalnum, basepalWFullBrightInfo);
}
// Used by RRRA fog hackery - the only place changing the palswaps at run time.
void uploadpalswaps(int count, int32_t* swaps)
{
for (int i = 0; i < count; i++)
{
GLInterface.SetPalswapData(i, (uint8_t*)lookuptables[i], numshades + 1, palookupfog[i]);
}
}
//(dpx,dpy) specifies an n-sided polygon. The polygon must be a convex clockwise loop.
// n must be <= 8 (assume clipping can double number of vertices)
//method: 0:solid, 1:masked(255 is transparent), 2:transluscent #1, 3:transluscent #2
@ -415,7 +406,7 @@ static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32
return;
}
if (lookuptables[globalpal] == NULL)
if (LookupTables[globalpal].IsEmpty())
globalpal = 0;
//Load texture (globalpicnum)
@ -521,7 +512,7 @@ static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32
if (method & DAMETH_MASKPROPS)
{
handle_blend((method & DAMETH_MASKPROPS) > DAMETH_MASK, drawpoly_blend, (method & DAMETH_MASKPROPS) == DAMETH_TRANS2);
SetRenderStyleFromBlend((method & DAMETH_MASKPROPS) > DAMETH_MASK, drawpoly_blend, (method & DAMETH_MASKPROPS) == DAMETH_TRANS2);
}
float pc[4];
@ -530,7 +521,7 @@ static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32
pc[0] = (float)globalr * (1.f / 255.f);
pc[1] = (float)globalg * (1.f / 255.f);
pc[2] = (float)globalb * (1.f / 255.f);
pc[3] = float_trans(method & DAMETH_MASKPROPS, drawpoly_blend) * (1.f - drawpoly_alpha);
pc[3] = GetAlphaFromBlend(method & DAMETH_MASKPROPS, drawpoly_blend) * (1.f - drawpoly_alpha);
if (skyzbufferhack_pass)
pc[3] = 0.01f;
@ -3532,7 +3523,7 @@ static void polymost_drawmaskwallinternal(int32_t wallIndex)
#else
uint8_t const blend = wallext[wallIndex].blend;
#endif
handle_blend(!!(wal->cstat & 128), blend, !!(wal->cstat & 512));
SetRenderStyleFromBlend(!!(wal->cstat & 128), blend, !!(wal->cstat & 512));
drawpoly_alpha = 0.f;
drawpoly_blend = blend;
@ -3839,7 +3830,7 @@ void polymost_drawsprite(int32_t snum)
if (tspr->cstat & 2)
method = DAMETH_CLAMPED | ((tspr->cstat & 512) ? DAMETH_TRANS2 : DAMETH_TRANS1);
handle_blend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512));
SetRenderStyleFromBlend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512));
drawpoly_alpha = spriteext[spritenum].alpha;
drawpoly_blend = tspr->blend;
@ -4610,7 +4601,7 @@ static void polymost_precache(int32_t dapicnum, int32_t dapalnum, int32_t datype
// while sprites are clamped
if (videoGetRenderMode() < REND_POLYMOST) return;
if ((dapalnum < (MAXPALOOKUPS - RESERVEDPALS)) && (lookuptables[dapalnum] == NULL)) return;//dapalnum = 0;
if ((dapalnum < (MAXPALOOKUPS - RESERVEDPALS)) && (LookupTables[dapalnum].IsEmpty())) return;//dapalnum = 0;
//Printf("precached %d %d type %d\n", dapicnum, dapalnum, datype);
hicprecaching = 1;

View File

@ -1098,7 +1098,7 @@ int32_t polymost_voxdraw(voxmodel_t *m, tspriteptr_t const tspr)
pc[3] = (tspr->cstat & 2) ? glblend[tspr->blend].def[!!(tspr->cstat & 512)].alpha : 1.0f;
pc[3] *= 1.0f - spriteext[tspr->owner].alpha;
handle_blend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512));
SetRenderStyleFromBlend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512));
if (!(tspr->cstat & 2) || spriteext[tspr->owner].alpha > 0.f || pc[3] < 1.0f)
GLInterface.EnableBlend(true); // else GLInterface.EnableBlend(false);

View File

@ -39,6 +39,7 @@
#include "colormatcher.h"
#include "templates.h"
#include "palettecontainer.h"
#include "files.h"
PaletteContainer GPalette;
FColorMatcher ColorMatcher;
@ -102,6 +103,35 @@ void PaletteContainer::Clear()
TranslationTables.Reset();
}
//===========================================================================
//
//
//
//===========================================================================
int PaletteContainer::DetermineTranslucency(FileReader& tranmap)
{
uint8_t index;
PalEntry newcolor;
PalEntry newcolor2;
if (!tranmap.isOpen()) return 255;
tranmap.Seek(GPalette.BlackIndex * 256 + GPalette.WhiteIndex, FileReader::SeekSet);
tranmap.Read(&index, 1);
newcolor = GPalette.BaseColors[GPalette.Remap[index]];
tranmap.Seek(GPalette.WhiteIndex * 256 + GPalette.BlackIndex, FileReader::SeekSet);
tranmap.Read(&index, 1);
newcolor2 = GPalette.BaseColors[GPalette.Remap[index]];
if (newcolor2.r == 255) // if black on white results in white it's either
// fully transparent or additive
{
return -newcolor.r;
}
return newcolor.r;
}
//----------------------------------------------------------------------------
//
//

View File

@ -4,6 +4,8 @@
#include "memarena.h"
#include "palentry.h"
class FileReader;
struct FRemapTable
{
FRemapTable(int count = 256) { NumEntries = count; }
@ -81,6 +83,7 @@ public:
void Init(int numslots); // This cannot be a constructor!!!
void SetPalette(const uint8_t* colors, int transparent_index = -1);
void Clear();
int DetermineTranslucency(FileReader& file);
FRemapTable* AddRemap(FRemapTable* remap);
void UpdateTranslation(int trans, FRemapTable* remap);
int AddTranslation(int slot, FRemapTable* remap, int count = 1);

View File

@ -650,7 +650,7 @@ void F2DDrawer::rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16
else
method |= DAMETH_MASK;
dg.mRenderStyle = GetBlend(dablend, (dastat & RS_TRANS2) ? 1 : 0);
dg.mRenderStyle = GetRenderStyle(dablend, (dastat & RS_TRANS2) ? 1 : 0);
}
else
{
@ -664,7 +664,7 @@ void F2DDrawer::rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16
dg.mVertIndex = (int)mVertices.Reserve(4);
auto ptr = &mVertices[dg.mVertIndex];
float drawpoly_alpha = daalpha * (1.0f / 255.0f);
float alpha = float_trans(method, dablend) * (1.f - drawpoly_alpha); // Hmmm...
float alpha = GetAlphaFromBlend(method, dablend) * (1.f - drawpoly_alpha); // Hmmm...
p.a = (uint8_t)(alpha * 255);
vec2_16_t const siz = dg.mTexture->GetSize();
@ -749,8 +749,8 @@ void F2DDrawer::AddPoly(FTexture* img, FVector4* vt, size_t vtcount, unsigned in
PalEntry p = 0xffffffff;
if (maskprops > DAMETH_MASK)
{
dg.mRenderStyle = GetBlend(0, maskprops == DAMETH_TRANS2);
p.a = (uint8_t)(float_trans(maskprops, 0) * 255);
dg.mRenderStyle = GetRenderStyle(0, maskprops == DAMETH_TRANS2);
p.a = (uint8_t)(GetAlphaFromBlend(maskprops, 0) * 255);
}
dg.mTexture = img;
dg.mRemapIndex = palette | (shade << 16);

View File

@ -369,6 +369,8 @@ void V_InitScreen()
void V_Init2()
{
palettePostLoadLookups();
float gamma = static_cast<DDummyFrameBuffer *>(screen)->Gamma;
{

View File

@ -50,7 +50,6 @@ enum
MAXARTFILES_TOTAL = 220
};
extern char* lookuptables[];
BuildTiles TileFiles;
@ -556,10 +555,10 @@ void tileCopy(int tile, int source, int pal, int xoffset, int yoffset, int flags
if (pal != -1)
{
auto remap = lookuptables[pal];
auto remap = (const uint8_t*)LookupTables[pal].GetChars();
for (auto& pixel : buffer)
{
pixel = lookuptables[pal][pixel];
pixel = remap[pixel];
}
}
tex = new FLooseTile(buffer, tex->GetWidth(), tex->GetHeight());

View File

@ -133,7 +133,7 @@ void G_LoadLookups(void)
for (unsigned char & k : paldata)
k <<= 2;
paletteSetColorTable(basepalnum, paldata, basepalnum == DREALMSPAL || basepalnum == ENDINGPAL);
paletteSetColorTable(basepalnum, paldata, basepalnum == DREALMSPAL || basepalnum == ENDINGPAL, basepalnum < DREALMSPAL);
}
}

View File

@ -5262,8 +5262,6 @@ static void G_PostLoadPalette(void)
if (!(duke3d_globalflags & DUKE3D_NO_PALETTE_CHANGES))
paletteFixTranslucencyMask();
palettePostLoadLookups();
}
#define SETFLAG(Tilenum, Flag) g_tile[Tilenum].flags |= Flag

View File

@ -1003,7 +1003,7 @@ void uploadCinemaPalettes()
hFile.Read(palette, 768);
for (auto& c : palette)
c <<= 2;
paletteSetColorTable(ANIMPAL+i, palette);
paletteSetColorTable(ANIMPAL+i, palette, false, true);
}
}

View File

@ -40,6 +40,7 @@
#include "textures.h"
#include "bitmap.h"
#include "v_font.h"
#include "palettecontainer.h"
#include "../../glbackend/glbackend.h"
// Test CVARs.
@ -152,6 +153,61 @@ FHardwareTexture* GLInstance::LoadTexture(FTexture* tex, int textype, int palid)
//
//===========================================================================
struct TexturePick
{
FTexture* texture; // which texture to use
int translation; // which translation table to use
int tintFlags; // which shader tinting options to use
PalEntry tintColor; // Tint color
PalEntry basepalTint; // can the base palette be done with a global tint effect?
};
TexturePick PickTexture(int tilenum, int basepal, int palette)
{
TexturePick pick = { nullptr, 0, -1, 0xffffff, 0xffffff };
int usepalette = fixpalette >= 0 ? fixpalette : basepal;
int usepalswap = fixpalswap >= 0 ? fixpalswap : palette;
auto& h = hictinting[palette];
auto tex = TileFiles.tiles[tilenum];
auto rep = (hw_hightile && !(h.f & HICTINT_ALWAYSUSEART)) ? tex->FindReplacement(usepalswap) : nullptr;
// Canvas textures must be treated like hightile replacements in the following code.
bool truecolor = rep || tex->GetUseType() == FTexture::Canvas;
bool applytint = false;
if (truecolor)
{
if (usepalette != 0)
{
// This is a global setting for the entire scene, so let's do it here, right at the start. (Fixme: Store this in a static table instead of reusing the same entry for all palettes.)
auto& hh = hictinting[MAXPALOOKUPS - 1];
// This sets a tinting color for global palettes, e.g. water or slime - only used for hires replacements (also an option for low-resource hardware where duplicating the textures may be problematic.)
pick.basepalTint = hh.tint;
}
if (rep)
{
tex = rep->faces[0];
}
if (!rep || rep->palnum != palette || (h.f & HICTINT_APPLYOVERALTPAL)) applytint = true;
}
else
{
// Tinting is not used on indexed textures, unless explicitly requested
if (h.f & (HICTINT_ALWAYSUSEART | HICTINT_USEONART))
{
applytint = true;
if (!(h.f & HICTINT_APPLYOVERPALSWAP)) usepalswap = 0;
}
pick.translation = TRANSLATION(usepalette + 1, usepalswap);
}
pick.texture = tex;
if (applytint && h.f)
{
pick.tintFlags = h.f;
pick.tintColor = h.tint;
}
return pick;
}
bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int method, int sampleroverride, FTexture *det, float detscale, FTexture *glow)
{
if (tex->GetWidth() <= 0 || tex->GetHeight() <= 0) return false;

View File

@ -241,8 +241,7 @@ void GLInstance::Draw2D(F2DDrawer *drawer)
static int32_t tint_blood_r = 0, tint_blood_g = 0, tint_blood_b = 0;
extern palette_t palfadergb;
extern unsigned char palfadedelta ;
extern PalEntry palfadergb;
void DrawFullscreenBlends()
{
@ -255,11 +254,11 @@ void DrawFullscreenBlends()
GLInterface.EnableBlend(true);
GLInterface.UseColorOnly(true);
if (palfadedelta > 0)
if (palfadergb.a > 0)
{
// Todo: reroute to the 2D drawer
GLInterface.SetRenderStyle(LegacyRenderStyles[STYLE_Translucent]);
GLInterface.SetColorub(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
GLInterface.SetColorub(palfadergb.r, palfadergb.g, palfadergb.b, palfadergb.a);
GLInterface.Draw(DT_TRIANGLE_STRIP, FFlatVertexBuffer::PRESENT_INDEX, 4);
}
if (tint_blood_r | tint_blood_g | tint_blood_b)

View File

@ -132,7 +132,7 @@ void G_LoadLookups(void)
for (bssize_t k = 0; k < 768; k++)
paldata[k] <<= 2;
paletteSetColorTable(basepalnum, paldata, basepalnum == DREALMSPAL || basepalnum == ENDINGPAL);
paletteSetColorTable(basepalnum, paldata, basepalnum == DREALMSPAL || basepalnum == ENDINGPAL, basepalnum < DREALMSPAL);
}
for (int i = 0; i < 256; i++)
@ -142,7 +142,7 @@ void G_LoadLookups(void)
paldata[i * 3+1] = GPalette.BaseColors[i].g;
paldata[i * 3+2] = GPalette.BaseColors[i].r;
}
paletteSetColorTable(DRUGPAL, paldata); // todo: implement this as a shader effect
paletteSetColorTable(DRUGPAL, paldata, false, false); // todo: implement this as a shader effect (swap R and B in postprocessing.)
if (RR)
{
@ -186,7 +186,7 @@ void G_LoadLookups(void)
{
paletteMakeLookupTable(50, NULL, 12 * 4, 12 * 4, 12 * 4, 0);
paletteMakeLookupTable(51, NULL, 12 * 4, 12 * 4, 12 * 4, 0);
paletteMakeLookupTable(54, lookuptables[8], 32 * 4, 32 * 4, 32 * 4, 0);
paletteMakeLookupTable(54, LookupTables[8].GetChars(), 32 * 4, 32 * 4, 32 * 4, 0);
}
}
}

View File

@ -6606,8 +6606,6 @@ static void G_PostLoadPalette(void)
if (!(duke3d_globalflags & DUKE3D_NO_PALETTE_CHANGES))
paletteFixTranslucencyMask();
palettePostLoadLookups();
}
#define SETFLAG(Tilenum, Flag) g_tile[Tilenum].flags |= Flag

View File

@ -730,7 +730,7 @@ bool InitGame()
for (auto& c : pal)
c <<= 2;
paletteSetColorTable(DREALMSPAL, pal.Data(), true);
paletteSetColorTable(DREALMSPAL, pal.Data(), true, true);
}
}
@ -844,7 +844,7 @@ bool InitGame()
enginePostInit();
palettePostLoadLookups();
paletteFixTranslucencyMask();
V_Init2();
DemoModeMenuInit = TRUE;