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

View file

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

View file

@ -28,6 +28,8 @@
#define NORMALPAL (MAXPALOOKUPS - 4) #define NORMALPAL (MAXPALOOKUPS - 4)
#define BRIGHTPAL (MAXPALOOKUPS) #define BRIGHTPAL (MAXPALOOKUPS)
extern FString LookupTables[MAXPALOOKUPS];
enum enum
{ {
Translation_BasePalettes, Translation_BasePalettes,
@ -35,35 +37,19 @@ enum
}; };
extern uint8_t curbasepal; extern uint8_t curbasepal;
extern FixedBitArray<256> FullbrightIndices;
extern int32_t r_scenebrightness; 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 struct palette_t
{ {
uint8_t r, g, b, f; 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 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); int32_t paletteSetLookupTable(int32_t palnum, const uint8_t *shtab);
void paletteFreeLookupTable(int32_t palnum);
#include "tflags.h" #include "tflags.h"
enum ESetPalFlag enum ESetPalFlag
@ -79,10 +65,16 @@ inline void videoSetBrightness(int brightness)
typedef TFlags<ESetPalFlag> ESetPalFlags; typedef TFlags<ESetPalFlag> ESetPalFlags;
DEFINE_TFLAGS_OPERATORS(ESetPalFlags) DEFINE_TFLAGS_OPERATORS(ESetPalFlags)
extern ESetPalFlags curpaletteflags;
void videoSetPalette(int dabrightness, int dapalid, ESetPalFlags flags); 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 #ifdef USE_OPENGL
void videoTintBlood(int32_t r, int32_t g, int32_t b); void videoTintBlood(int32_t r, int32_t g, int32_t b);
#endif #endif
@ -91,7 +83,6 @@ extern int32_t globalpal;
extern int32_t globalblend; extern int32_t globalblend;
extern void paletteLoadFromDisk(void); extern void paletteLoadFromDisk(void);
extern void palettePostLoadTables(void); extern void palettePostLoadTables(void);
extern int32_t curbrightness;
extern int32_t paletteLoadLookupTable(FileReader &fp); extern int32_t paletteLoadLookupTable(FileReader &fp);
extern void paletteSetupDefaultFog(void); extern void paletteSetupDefaultFog(void);
@ -106,21 +97,6 @@ extern char britable[16][256];
#ifdef USE_OPENGL #ifdef USE_OPENGL
extern palette_t palookupfog[MAXPALOOKUPS]; 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_ typedef struct glblenddef_
{ {
float alpha; float alpha;
@ -135,9 +111,9 @@ typedef struct glblend_
extern glblend_t const nullglblend, defaultglblend; extern glblend_t const nullglblend, defaultglblend;
extern glblend_t glblend[MAXBLENDTABS]; extern glblend_t glblend[MAXBLENDTABS];
FRenderStyle GetBlend(int blend, int def); FRenderStyle GetRenderStyle(int blend, int def);
extern void handle_blend(uint8_t enable, uint8_t blend, uint8_t def); extern void SetRenderStyleFromBlend(uint8_t enable, uint8_t blend, uint8_t def);
float float_trans(uint32_t maskprops, uint8_t blend); float GetAlphaFromBlend(uint32_t maskprops, uint32_t blend);
#endif #endif

View file

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

View file

@ -69,7 +69,6 @@ bool playing_rr;
bool playing_blood; bool playing_blood;
int32_t rendmode=0; int32_t rendmode=0;
int32_t glrendmode = REND_POLYMOST; int32_t glrendmode = REND_POLYMOST;
int32_t r_scenebrightness = 0;
int32_t r_rortexture = 0; int32_t r_rortexture = 0;
int32_t r_rortexturerange = 0; int32_t r_rortexturerange = 0;
int32_t r_rorphase = 0; int32_t r_rorphase = 0;
@ -2054,6 +2053,8 @@ int32_t enginePreInit(void)
} }
void (*paletteLoadFromDisk_replace)(void) = NULL; // replacement hook for Blood.
// //
// initengine // initengine
// //
@ -2094,7 +2095,14 @@ int32_t engineInit(void)
maxspritesonscreen = MAXSPRITESONSCREEN; maxspritesonscreen = MAXSPRITESONSCREEN;
paletteLoadFromDisk(); if (paletteLoadFromDisk_replace)
{
paletteLoadFromDisk_replace();
}
else
{
paletteLoadFromDisk();
}
#ifdef USE_OPENGL #ifdef USE_OPENGL
if (!mdinited) mdinit(); if (!mdinited) mdinit();
@ -2123,7 +2131,6 @@ int32_t enginePostInit(void)
// //
// uninitengine // uninitengine
// //
void paletteFreeAll();
void engineUnInit(void) void engineUnInit(void)
{ {
@ -2138,8 +2145,6 @@ void engineUnInit(void)
TileFiles.CloseAll(); TileFiles.CloseAll();
paletteFreeAll();
for (bssize_t i = 0; i < num_usermaphacks; i++) for (bssize_t i = 0; i < num_usermaphacks; i++)
{ {
Xfree(usermaphacks[i].mhkfile); 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] = (tspr->cstat&2) ? glblend[tspr->blend].def[!!(tspr->cstat&512)].alpha : 1.0f;
pc[3] *= 1.0f - sext->alpha; 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 if (m->usesalpha) //Sprites with alpha in texture
{ {

View file

@ -19,16 +19,16 @@
#include "palettecontainer.h" #include "palettecontainer.h"
#include "palutil.h" #include "palutil.h"
#include "colormatcher.h" #include "colormatcher.h"
#include "m_swap.h"
#include "../../glbackend/glbackend.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; uint8_t curbasepal;
int32_t globalblend; int32_t globalblend;
palette_t palfadergb = { 0, 0, 0, 0 }; PalEntry palfadergb;
unsigned char palfadedelta = 0;
ESetPalFlags curpaletteflags;
#if defined(USE_OPENGL) #if defined(USE_OPENGL)
palette_t palookupfog[MAXPALOOKUPS]; palette_t palookupfog[MAXPALOOKUPS];
@ -39,32 +39,15 @@ palette_t palookupfog[MAXPALOOKUPS];
// NOTE: g_noFloorPal[0] is irrelevant as it's never checked. // NOTE: g_noFloorPal[0] is irrelevant as it's never checked.
int8_t g_noFloorPal[MAXPALOOKUPS]; 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
//
//==========================================================================
void paletteSetColorTable(int32_t id, uint8_t const* table, bool notransparency, bool twodonly)
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)
{ {
if (id == 0) if (id == 0)
{ {
@ -77,6 +60,7 @@ void paletteSetColorTable(int32_t id, uint8_t const* table, bool notransparency)
remap.Palette[255] = 0; remap.Palette[255] = 0;
remap.Remap[255] = 255; 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); GPalette.UpdateTranslation(TRANSLATION(Translation_BasePalettes, id), &remap);
// Todo: remove this once the texture code can use GPalette directly // 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 #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) void paletteLoadFromDisk(void)
{ {
GPalette.Init(MAXPALOOKUPS + 1); // one slot for each translation, plus a separate one for the base palettes. GPalette.Init(MAXPALOOKUPS + 1); // one slot for each translation, plus a separate one for the base palettes.
#ifdef USE_OPENGL
for (auto & x : glblend) for (auto & x : glblend)
x = defaultglblend; x = defaultglblend;
#endif
if (paletteLoadFromDisk_replace)
{
paletteLoadFromDisk_replace();
return;
}
auto fil = fileSystem.OpenFileReader("palette.dat"); auto fil = fileSystem.OpenFileReader("palette.dat");
if (!fil.isOpen()) if (!fil.isOpen())
@ -139,16 +96,11 @@ void paletteLoadFromDisk(void)
for (unsigned char & k : palette) for (unsigned char & k : palette)
k <<= 2; k <<= 2;
paletteSetColorTable(0, palette); paletteSetColorTable(0, palette, false, false);
paletteloaded |= PALETTE_MAIN; paletteloaded |= PALETTE_MAIN;
// PALETTE_SHADES // PALETTE_SHADES
numshades = fil.ReadInt16();
if (2 != fil.Read(&numshades, 2))
return;
numshades = B_LITTLE16(numshades);
if (numshades <= 1) if (numshades <= 1)
{ {
@ -157,397 +109,266 @@ void paletteLoadFromDisk(void)
return; return;
} }
// Auto-detect LameDuke. Its PALETTE.DAT doesn't have a 'numshades' 16-bit #if 0
// int after the base palette, but starts directly with the shade tables. // Reminder: Witchaven's shade table has no index and no easy means to autodetect.
// Thus, the first two bytes will be 00 01, which is 256 if read as if (numshades == 0 && (g_gameType & GAMEFLAG_WITCHAVEN))
// little-endian int16_t.
int32_t lamedukep = 0;
if (numshades >= 256)
{ {
uint16_t temp; numshades = 32;
if (read_and_test(fil, &temp, 2)) fil.Seek(-2, FileReader::SeekCur);
return; }
temp = B_LITTLE16(temp); else
if (temp == 770 || numshades > 256) // 02 03 #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"); fil.Seek(-4, FileReader::SeekCur);
return; numshades = 32;
} }
else
numshades = 32;
lamedukep = 1;
}
else
{
if (fil.Seek(-2, FileReader::SeekCur) < 0)
{ {
Printf("Warning: seek failed in loadpalette()!\n"); fil.Seek(-2, FileReader::SeekCur);
return;
} }
} }
} }
// Read base shade table (lookuptables 0). // Read base shade table (lookuptables 0).
maybe_alloc_palookup(0); int length = numshades * 256;
if (read_and_test(fil, lookuptables[0], numshades<<8)) auto p = LookupTables[0].LockNewBuffer(length);
auto count = fil.Read(p, length);
LookupTables->UnlockBuffer();
if (count != length)
return; return;
paletteloaded |= PALETTE_SHADE; paletteloaded |= PALETTE_SHADE;
paletteloaded |= PALETTE_TRANSLUC; 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) void palettePostLoadTables(void)
{ {
globalpal = 0; globalpal = 0;
char const * const palookup0 = lookuptables[0]; auto lookup = (const uint8_t*)LookupTables[0].GetChars();
ImageHelpers::SetPalette(GPalette.BaseColors); ImageHelpers::SetPalette(GPalette.BaseColors);
// Bmemset(PaletteIndexFullbrights, 0, sizeof(PaletteIndexFullbrights)); for (int c = 0; c < 255; ++c) // skipping transparent color
for (bssize_t c = 0; c < 255; ++c) // skipping transparent color
{ {
uint8_t const index = palookup0[c]; uint8_t index = lookup[c];
PalEntry color = GPalette.BaseColors[index]; PalEntry color = GPalette.BaseColors[index];
// don't consider #000000 fullbright // don't consider black fullbright
if (color.r == 0 && color.g == 0 && color.b == 0) if (color.isBlack()) continue;
continue;
for (size_t s = c + 256, s_end = 256*numshades; s < s_end; s += 256) bool isbright = true;
if (palookup0[s] != index) for (int i = 1; i < numshades; i++)
goto PostLoad_NotFullbright; if (lookup[i * 256 + c] != index)
{
isbright = false;
break;
}
SetPaletteIndexFullbright(c); if (isbright) FullbrightIndices.Set(c);
PostLoad_NotFullbright: ;
} }
} }
//==========================================================================
//
// Ensure that all lookups map 255 to itself to preserve transparency.
//
//==========================================================================
void paletteFixTranslucencyMask(void) void paletteFixTranslucencyMask(void)
{ {
for (auto thispalookup : lookuptables) for (auto &thispalookup : LookupTables)
{ {
if (thispalookup == NULL) if (thispalookup.IsEmpty())
continue; continue;
for (bssize_t j=0; j<numshades; j++) for (int j = 0; j < numshades; j++)
thispalookup[(j<<8) + 255] = 255; {
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) int32_t paletteLoadLookupTable(FileReader &fp)
{ {
uint8_t numlookups;
char remapbuf[256]; char remapbuf[256];
int numlookups = fp.ReadUInt8();
if (1 != fp.Read(&numlookups, 1)) if (numlookups < 1)
return -1; return -1;
for (bssize_t j=0; j<numlookups; j++) for (int j=0; j<numlookups; j++)
{ {
uint8_t palnum; int palnum = fp.ReadUInt8();
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;
}
if (256 != fp.Read(remapbuf, 256)) if (256 != fp.Read(remapbuf, 256))
return -1; 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; return 0;
} }
//==========================================================================
//
// Find a gap of four consecutive unused pal numbers to generate fog shade tables.
//
//==========================================================================
void paletteSetupDefaultFog(void) void paletteSetupDefaultFog(void)
{ {
// Find a gap of four consecutive unused pal numbers to generate fog shade for (int j = 1; j <= 255 - 3; j++)
// tables. {
for (bssize_t j=1; j<=255-3; j++) if (!LookupTables[j].IsEmpty() && !LookupTables[j + 1].IsEmpty() && !LookupTables[j + 2].IsEmpty() && !LookupTables[j + 3].IsEmpty())
if (!lookuptables[j] && !lookuptables[j+1] && !lookuptables[j+2] && !lookuptables[j+3])
{ {
paletteMakeLookupTable(j, NULL, 60, 60, 60, 1); paletteMakeLookupTable(j, NULL, 60, 60, 60, 1);
paletteMakeLookupTable(j+1, NULL, 60, 0, 0, 1); paletteMakeLookupTable(j + 1, NULL, 60, 0, 0, 1);
paletteMakeLookupTable(j+2, NULL, 0, 60, 0, 1); paletteMakeLookupTable(j + 2, NULL, 0, 60, 0, 1);
paletteMakeLookupTable(j+3, NULL, 0, 0, 60, 1); paletteMakeLookupTable(j + 3, NULL, 0, 0, 60, 1);
break; break;
} }
}
} }
//==========================================================================
//
// post process the lookup tables once everything has been loaded
//
//==========================================================================
void palettePostLoadLookups(void) void palettePostLoadLookups(void)
{ {
// Alias remaining unused pal numbers to the base shade table. int numpalettes = GPalette.NumTranslations(Translation_BasePalettes);
for (bssize_t j=1; j<MAXPALOOKUPS; j++) if (numpalettes == 0) return;
{ auto basepalette = GPalette.GetTranslation(Translation_BasePalettes, 0);
// 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);
if (!lookuptables[j]) for (int l = 0; l < MAXPALOOKUPS; l++)
paletteMakeLookupTable(j, NULL, 0, 0, 0, 1); {
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])); // set a lookup table from external data
} //
//==========================================================================
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
int32_t paletteSetLookupTable(int32_t palnum, const uint8_t *shtab) int32_t paletteSetLookupTable(int32_t palnum, const uint8_t *shtab)
{ {
if (shtab != NULL) if (shtab != NULL)
{ {
maybe_alloc_palookup(palnum); int length = numshades * 256;
Bmemcpy(lookuptables[palnum], shtab, 256*numshades); auto p = LookupTables[palnum].LockNewBuffer(length);
memcpy(p, shtab, length);
LookupTables->UnlockBuffer();
} }
return 0; 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) void paletteMakeLookupTable(int32_t palnum, const char *remapbuf, uint8_t r, uint8_t g, uint8_t b, char noFloorPal)
{ {
int32_t i, j; char idmap[256];
static char idmap[256] = { 1 };
if (paletteloaded == 0)
return;
// NOTE: palnum==0 is allowed // NOTE: palnum==0 is allowed
if ((unsigned) palnum >= MAXPALOOKUPS) if (paletteloaded == 0 || (unsigned)palnum >= MAXPALOOKUPS)
return; return;
g_noFloorPal[palnum] = noFloorPal; 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; return;
} }
if (idmap[0]==1) // init identity map for (int i = 0; i < 256; i++) idmap[i] = i;
for (i=0; i<256; i++)
idmap[i] = i;
remapbuf = idmap; remapbuf = idmap;
} }
maybe_alloc_palookup(palnum); int length = numshades * 256;
auto p = LookupTables[palnum].LockNewBuffer(length);
if ((r|g|b) == 0) if (r == 0 || g == 0 || b == 0)
{ {
// "black fog"/visibility case -- only remap color indices // "black fog"/visibility case -- only remap color indices
for (j=0; j<numshades; j++) auto src = (const uint8_t*)LookupTables[0].GetChars();
for (i=0; i<256; i++)
for (int j = 0; j < numshades; j++)
for (int i = 0; i < 256; i++)
{ {
const char *src = lookuptables[0]; p[256 * j + i] = src[256 * j + remapbuf[i]];
lookuptables[palnum][256*j + i] = src[256*j + remapbuf[i]];
} }
} }
else else
{ {
// colored fog case // colored fog case
char *ptr2 = lookuptables[palnum]; for (int i = 0; i < numshades; i++)
for (i=0; i<numshades; i++)
{ {
int32_t palscale = divscale16(i, numshades-1); for (int j = 0; j < 256; j++)
for (j=0; j<256; j++)
{ {
PalEntry pe = GPalette.BaseColors[remapbuf[j]]; PalEntry pe = GPalette.BaseColors[remapbuf[j]];
*ptr2++ = ColorMatcher.Pick(pe.r + mulscale16(r-pe.r, palscale), p[j] = ColorMatcher.Pick(
pe.g + mulscale16(g-pe.g, palscale), pe.r + Scale(r - pe.r, i, numshades - 1),
pe.b + mulscale16(b-pe.b, palscale)); 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 #endif
} }
//
// setbrightness void videoSetPalette(int dabrightness, int palid, ESetPalFlags flags)
//
// 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)
{ {
if (GPalette.GetTranslation(Translation_BasePalettes, dapalid) == nullptr) curbasepal = (GPalette.GetTranslation(Translation_BasePalettes, palid) == nullptr)? 0 : palid;
dapalid = 0; if ((flags & Pal_DontResetFade) == 0) palfadergb = 0;
curbasepal = dapalid;
if ((flags & Pal_DontResetFade) == 0)
{
palfadergb.r = palfadergb.g = palfadergb.b = 0;
palfadedelta = 0;
}
curpaletteflags = flags;
} }
//==========================================================================
// //
// 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; { 1.f, STYLEALPHA_One, STYLEALPHA_Zero, 0 },
palfadergb.b = b; { 1.f, STYLEALPHA_One, STYLEALPHA_Zero, 0 },
palfadedelta = offset; },
};
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++) float GetAlphaFromBlend(uint32_t method, uint32_t blend)
if (i == 0 || lookuptables[i] != lookuptables[0]) {
{ return method == DAMETH_TRANS1 || method == DAMETH_TRANS2 ? glblend[blend].def[method - DAMETH_TRANS1].alpha : 1.f;
// Take care of handling aliased ^^^ cases! }
Xaligned_free(lookuptables[i]);
}
Bmemset(lookuptables, 0, sizeof(lookuptables));
}

View file

@ -92,6 +92,7 @@ static float dxb1[MAXWALLSB], dxb2[MAXWALLSB];
#define SOFTROTMAT 0 #define SOFTROTMAT 0
static int32_t r_pogoDebug = 0; static int32_t r_pogoDebug = 0;
int32_t r_scenebrightness = 0;
static float gviewxrange; static float gviewxrange;
static float ghoriz, ghoriz2; static float ghoriz, ghoriz2;
@ -232,7 +233,7 @@ static void polymost_glinit()
} }
for (int palookupnum = 0; palookupnum < MAXPALOOKUPS; ++palookupnum) 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+0] = remap->Palette[i].b;
basepalWFullBrightInfo[i*4+1] = remap->Palette[i].g; basepalWFullBrightInfo[i*4+1] = remap->Palette[i].g;
basepalWFullBrightInfo[i*4+2] = remap->Palette[i].r; 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); 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. //(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) // 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 //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; return;
} }
if (lookuptables[globalpal] == NULL) if (LookupTables[globalpal].IsEmpty())
globalpal = 0; globalpal = 0;
//Load texture (globalpicnum) //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) 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]; 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[0] = (float)globalr * (1.f / 255.f);
pc[1] = (float)globalg * (1.f / 255.f); pc[1] = (float)globalg * (1.f / 255.f);
pc[2] = (float)globalb * (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) if (skyzbufferhack_pass)
pc[3] = 0.01f; pc[3] = 0.01f;
@ -3532,7 +3523,7 @@ static void polymost_drawmaskwallinternal(int32_t wallIndex)
#else #else
uint8_t const blend = wallext[wallIndex].blend; uint8_t const blend = wallext[wallIndex].blend;
#endif #endif
handle_blend(!!(wal->cstat & 128), blend, !!(wal->cstat & 512)); SetRenderStyleFromBlend(!!(wal->cstat & 128), blend, !!(wal->cstat & 512));
drawpoly_alpha = 0.f; drawpoly_alpha = 0.f;
drawpoly_blend = blend; drawpoly_blend = blend;
@ -3839,7 +3830,7 @@ void polymost_drawsprite(int32_t snum)
if (tspr->cstat & 2) if (tspr->cstat & 2)
method = DAMETH_CLAMPED | ((tspr->cstat & 512) ? DAMETH_TRANS2 : DAMETH_TRANS1); 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_alpha = spriteext[spritenum].alpha;
drawpoly_blend = tspr->blend; 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 // while sprites are clamped
if (videoGetRenderMode() < REND_POLYMOST) return; 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); //Printf("precached %d %d type %d\n", dapicnum, dapalnum, datype);
hicprecaching = 1; 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] = (tspr->cstat & 2) ? glblend[tspr->blend].def[!!(tspr->cstat & 512)].alpha : 1.0f;
pc[3] *= 1.0f - spriteext[tspr->owner].alpha; 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) if (!(tspr->cstat & 2) || spriteext[tspr->owner].alpha > 0.f || pc[3] < 1.0f)
GLInterface.EnableBlend(true); // else GLInterface.EnableBlend(false); GLInterface.EnableBlend(true); // else GLInterface.EnableBlend(false);

View file

@ -39,6 +39,7 @@
#include "colormatcher.h" #include "colormatcher.h"
#include "templates.h" #include "templates.h"
#include "palettecontainer.h" #include "palettecontainer.h"
#include "files.h"
PaletteContainer GPalette; PaletteContainer GPalette;
FColorMatcher ColorMatcher; FColorMatcher ColorMatcher;
@ -102,6 +103,35 @@ void PaletteContainer::Clear()
TranslationTables.Reset(); 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 "memarena.h"
#include "palentry.h" #include "palentry.h"
class FileReader;
struct FRemapTable struct FRemapTable
{ {
FRemapTable(int count = 256) { NumEntries = count; } FRemapTable(int count = 256) { NumEntries = count; }
@ -81,6 +83,7 @@ public:
void Init(int numslots); // This cannot be a constructor!!! void Init(int numslots); // This cannot be a constructor!!!
void SetPalette(const uint8_t* colors, int transparent_index = -1); void SetPalette(const uint8_t* colors, int transparent_index = -1);
void Clear(); void Clear();
int DetermineTranslucency(FileReader& file);
FRemapTable* AddRemap(FRemapTable* remap); FRemapTable* AddRemap(FRemapTable* remap);
void UpdateTranslation(int trans, FRemapTable* remap); void UpdateTranslation(int trans, FRemapTable* remap);
int AddTranslation(int slot, FRemapTable* remap, int count = 1); 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 else
method |= DAMETH_MASK; method |= DAMETH_MASK;
dg.mRenderStyle = GetBlend(dablend, (dastat & RS_TRANS2) ? 1 : 0); dg.mRenderStyle = GetRenderStyle(dablend, (dastat & RS_TRANS2) ? 1 : 0);
} }
else 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); dg.mVertIndex = (int)mVertices.Reserve(4);
auto ptr = &mVertices[dg.mVertIndex]; auto ptr = &mVertices[dg.mVertIndex];
float drawpoly_alpha = daalpha * (1.0f / 255.0f); 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); p.a = (uint8_t)(alpha * 255);
vec2_16_t const siz = dg.mTexture->GetSize(); 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; PalEntry p = 0xffffffff;
if (maskprops > DAMETH_MASK) if (maskprops > DAMETH_MASK)
{ {
dg.mRenderStyle = GetBlend(0, maskprops == DAMETH_TRANS2); dg.mRenderStyle = GetRenderStyle(0, maskprops == DAMETH_TRANS2);
p.a = (uint8_t)(float_trans(maskprops, 0) * 255); p.a = (uint8_t)(GetAlphaFromBlend(maskprops, 0) * 255);
} }
dg.mTexture = img; dg.mTexture = img;
dg.mRemapIndex = palette | (shade << 16); dg.mRemapIndex = palette | (shade << 16);

View file

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

View file

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

View file

@ -133,7 +133,7 @@ void G_LoadLookups(void)
for (unsigned char & k : paldata) for (unsigned char & k : paldata)
k <<= 2; 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)) if (!(duke3d_globalflags & DUKE3D_NO_PALETTE_CHANGES))
paletteFixTranslucencyMask(); paletteFixTranslucencyMask();
palettePostLoadLookups();
} }
#define SETFLAG(Tilenum, Flag) g_tile[Tilenum].flags |= Flag #define SETFLAG(Tilenum, Flag) g_tile[Tilenum].flags |= Flag

View file

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

View file

@ -40,6 +40,7 @@
#include "textures.h" #include "textures.h"
#include "bitmap.h" #include "bitmap.h"
#include "v_font.h" #include "v_font.h"
#include "palettecontainer.h"
#include "../../glbackend/glbackend.h" #include "../../glbackend/glbackend.h"
// Test CVARs. // 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) 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; 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; static int32_t tint_blood_r = 0, tint_blood_g = 0, tint_blood_b = 0;
extern palette_t palfadergb; extern PalEntry palfadergb;
extern unsigned char palfadedelta ;
void DrawFullscreenBlends() void DrawFullscreenBlends()
{ {
@ -255,11 +254,11 @@ void DrawFullscreenBlends()
GLInterface.EnableBlend(true); GLInterface.EnableBlend(true);
GLInterface.UseColorOnly(true); GLInterface.UseColorOnly(true);
if (palfadedelta > 0) if (palfadergb.a > 0)
{ {
// Todo: reroute to the 2D drawer // Todo: reroute to the 2D drawer
GLInterface.SetRenderStyle(LegacyRenderStyles[STYLE_Translucent]); 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); GLInterface.Draw(DT_TRIANGLE_STRIP, FFlatVertexBuffer::PRESENT_INDEX, 4);
} }
if (tint_blood_r | tint_blood_g | tint_blood_b) 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++) for (bssize_t k = 0; k < 768; k++)
paldata[k] <<= 2; 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++) 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+1] = GPalette.BaseColors[i].g;
paldata[i * 3+2] = GPalette.BaseColors[i].r; 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) if (RR)
{ {
@ -186,7 +186,7 @@ void G_LoadLookups(void)
{ {
paletteMakeLookupTable(50, NULL, 12 * 4, 12 * 4, 12 * 4, 0); paletteMakeLookupTable(50, NULL, 12 * 4, 12 * 4, 12 * 4, 0);
paletteMakeLookupTable(51, 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)) if (!(duke3d_globalflags & DUKE3D_NO_PALETTE_CHANGES))
paletteFixTranslucencyMask(); paletteFixTranslucencyMask();
palettePostLoadLookups();
} }
#define SETFLAG(Tilenum, Flag) g_tile[Tilenum].flags |= Flag #define SETFLAG(Tilenum, Flag) g_tile[Tilenum].flags |= Flag

View file

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