- stripped down the palette manager in the GL backend and let it use the data that's managed elsewhere.

This class is only needed to manage the palette textures used by the indexed render mode, all the rest is available globally.
This commit is contained in:
Christoph Oelckers 2020-05-25 00:31:05 +02:00
parent 4178d48fb6
commit 758e4ad7cb
9 changed files with 53 additions and 333 deletions

View file

@ -23,7 +23,6 @@ extern void Polymost_prepare_loadboard(void);
void polymost_outputGLDebugMessage(uint8_t severity, const char* format, ...); 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 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

@ -65,11 +65,6 @@ void paletteSetColorTable(int32_t id, uint8_t const* table, bool notransparency,
} }
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. 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
#ifdef USE_OPENGL
uploadbasepalette(id);
#endif
} }
//========================================================================== //==========================================================================

View file

@ -225,20 +225,6 @@ void polymost_glreset()
FileReader GetBaseResource(const char* fn); FileReader GetBaseResource(const char* fn);
// one-time initialization of OpenGL for polymost
static void polymost_glinit()
{
for (int basepalnum = 0; basepalnum < MAXBASEPALS; ++basepalnum)
{
uploadbasepalette(basepalnum);
}
for (int palookupnum = 0; palookupnum < MAXPALOOKUPS; ++palookupnum)
{
GLInterface.SetPalswapData(palookupnum, paletteGetLookupTable(palookupnum), numshades+1, palookupfog[palookupnum]);
}
}
static void resizeglcheck(void) static void resizeglcheck(void)
{ {
//FUK //FUK
@ -277,26 +263,6 @@ static void resizeglcheck(void)
GLInterface.SetIdentityMatrix(Matrix_Model); GLInterface.SetIdentityMatrix(Matrix_Model);
} }
void uploadbasepalette(int32_t basepalnum)
{
auto remap = GPalette.GetTranslation(Translation_BasePalettes, basepalnum);
if (!remap)
{
return;
}
uint8_t basepalWFullBrightInfo[4*256];
for (int i = 0; i < 256; ++i)
{
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] = remap->Palette[i].a;
}
GLInterface.SetPaletteData(basepalnum, basepalWFullBrightInfo);
}
//(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
@ -4659,6 +4625,5 @@ static void PolymostProcessVoxels(void)
void Polymost_Startup() void Polymost_Startup()
{ {
polymost_glinit();
PolymostProcessVoxels(); PolymostProcessVoxels();
} }

View file

@ -1136,14 +1136,14 @@ int32_t polymost_voxdraw(voxmodel_t *m, tspriteptr_t const tspr)
int prevClamp = GLInterface.GetClamp(); int prevClamp = GLInterface.GetClamp();
GLInterface.SetClamp(0); GLInterface.SetClamp(0);
#if 1 #if 1
int palId = GLInterface.LookupPalette(curbasepal, globalpal, false); int palId = TRANSLATION(Translation_Remap + curbasepal, globalpal);
auto palette = GLInterface.GetPaletteData(palId); auto palette = GPalette.TranslationToTable(palId);
if (!m->texIds) m->texIds = new TMap<int, FHardwareTexture*>; if (!m->texIds) m->texIds = new TMap<int, FHardwareTexture*>;
auto pTex = m->texIds->CheckKey(palId); auto pTex = m->texIds->CheckKey(palId);
FHardwareTexture* htex; FHardwareTexture* htex;
if (!pTex) if (!pTex)
{ {
htex = gloadtex(m->mytex, m->mytexx, m->mytexy, m->is8bit, palette); htex = gloadtex(m->mytex, m->mytexx, m->mytexy, m->is8bit, palette->Palette);
m->texIds->Insert(palId, htex); m->texIds->Insert(palId, htex);
} }
else else

View file

@ -45,8 +45,14 @@ private:
TranslatedTexture * GetTexID(int translation, bool expanded) TranslatedTexture * GetTexID(int translation, bool expanded)
{ {
auto remap = GPalette.TranslationToTable(translation); // Allow negative indices to pass through unchanged.
translation = remap == nullptr ? 0 : remap->Index; // This is needed for allowing the client to allocate slots that aren't matched to a palette, e.g. Build's indexed variants.
if (translation >= 0)
{
auto remap = GPalette.TranslationToTable(translation);
translation = remap == nullptr ? 0 : remap->Index;
}
else translation &= ~0x7fffffff;
if (translation == 0) if (translation == 0)
{ {

View file

@ -42,12 +42,11 @@
#include "imagehelpers.h" #include "imagehelpers.h"
#include "v_font.h" #include "v_font.h"
#include "palette.h" #include "palette.h"
#include "build.h"
//=========================================================================== //===========================================================================
// //
// The palette manager will contain all palettes being used for texture // This class manages the hardware data for the indexed render mode.
// creation. It is also responsible for creating palette textures for indexed
// rendering.
// //
//=========================================================================== //===========================================================================
@ -62,149 +61,20 @@ PaletteManager::~PaletteManager()
// //
//=========================================================================== //===========================================================================
void PaletteManager::DeleteAllTextures()
{
for (auto& pal : palettes)
{
if (pal.paltexture) delete pal.paltexture;
pal.paltexture = nullptr;
}
for (auto& pal : palswaps)
{
if (pal.swaptexture) delete pal.swaptexture;
pal.swaptexture = nullptr;
}
if (palswapTexture) delete palswapTexture;
palswapTexture = nullptr;
}
void PaletteManager::DeleteAll() void PaletteManager::DeleteAll()
{ {
DeleteAllTextures(); for (auto& pal : palettetextures)
palettes.Reset(); {
palswaps.Reset(); if (pal) delete pal;
pal = nullptr;
}
for (auto& pal : palswaptextures)
{
if (pal) delete pal;
pal = nullptr;
}
lastindex = ~0u; lastindex = ~0u;
lastsindex = ~0u; lastsindex = ~0u;
memset(palettemap, 0, sizeof(palettemap));
memset(palswapmap, 0, sizeof(palswapmap));
numshades = 1;
}
//===========================================================================
//
// Adds a new palette while looking for duplicates.
//
//===========================================================================
unsigned PaletteManager::FindPalette(const uint8_t *paldata)
{
auto crc32 = CalcCRC32(paldata, 1024);
for (unsigned int i = 0; i< palettes.Size(); i++)
{
if (crc32 == palettes[i].crc32)
{
if (!memcmp(paldata, palettes[i].colors, 1024))
{
return i;
}
}
}
PaletteData pd;
memcpy(pd.colors, paldata, 1024);
pd.crc32 = crc32;
pd.paltexture = nullptr;
pd.shadesdone = false;
return palettes.Push(pd);
}
//===========================================================================
//
// Adds a new palette while looking for duplicates.
//
//===========================================================================
unsigned PaletteManager::FindPalswap(const uint8_t* paldata, palette_t &fadecolor)
{
if (paldata == nullptr) return 0;
auto crc32 = CalcCRC32(paldata, 256 * numshades);
for (unsigned int i = 0; i < palswaps.Size(); i++)
{
if (crc32 == palswaps[i].crc32)
{
if (!memcmp(paldata, palswaps[i].lookup, 256 * numshades))
{
return i;
}
}
}
PalswapData pd;
pd.lookup = paldata;
pd.crc32 = crc32;
pd.swaptexture = nullptr;
memset(pd.brightcolors, 0, 256);
pd.isbright = false;
for (int i = 0; i < 255; i++)
{
int firstmap = paldata[i];
int lastmap = paldata[i + 256 * (numshades - 2)];
PalEntry color1 = palettes[palettemap[0]].colors[firstmap];
PalEntry color2 = palettes[palettemap[0]].colors[lastmap];
int lum1 = color1.Amplitude();
int lum2 = color2.Amplitude();
if (lum1 > 40 && lum2 * 10 >= lum1 * 9)
{
pd.brightcolors[i] = 255;
pd.isbright = true;
}
}
if (fadecolor.f == 0)
{
// Find what index maps to black (or the darkest available color)
int found = -1;
PalEntry foundColor = 0xffffffff;
for (int i = 0; i < 255; i++)
{
int map = paldata[i];
PalEntry color = palettes[palettemap[0]].colors[map];
if (color.Luminance() < foundColor.Luminance())
{
foundColor = color;
found = i;
}
}
// Determine the fade color. We pick what black, or the darkest color, maps to in the lowest shade level.
int map = paldata[(numshades - 2) * 256 + found]; // do not look in the latest shade level because it doesn't always contain useful data for this.
pd.fadeColor = palettes[palettemap[0]].colors[map];
if (pd.fadeColor.Luminance() < 10) pd.fadeColor = 0; // Account for the inability to check the last fade level by using a higher threshold for determining black fog.
}
else
{
pd.fadeColor = PalEntry(fadecolor.r, fadecolor.g, fadecolor.b);
}
return palswaps.Push(pd);
}
//===========================================================================
//
//
//
//===========================================================================
void PaletteManager::SetPalette(int index, const uint8_t* data)
{
// New palettes may only be added if declared transient or on startup.
// Otherwise this would require a renderer reset to flush out the textures affected by the change.
if (index < 0 || index > 255) return; // invalid index - ignore.
palettemap[index] = FindPalette(data);
} }
//=========================================================================== //===========================================================================
@ -215,21 +85,28 @@ void PaletteManager::SetPalette(int index, const uint8_t* data)
void PaletteManager::BindPalette(int index) void PaletteManager::BindPalette(int index)
{ {
if (palettemap[index] < palettes.Size()) auto palettedata = GPalette.GetTranslation(Translation_BasePalettes, index);
if (palettedata == nullptr)
{ {
auto uindex = palettemap[index]; index = 0;
if (uindex != lastindex) palettedata = GPalette.GetTranslation(Translation_BasePalettes, index);
};
if (palettedata)
{
if (index != lastindex)
{ {
lastindex = uindex; lastindex = index;
if (palettes[uindex].paltexture == nullptr)
if (palettetextures[index] == nullptr)
{ {
auto p = GLInterface.NewTexture(); auto p = GLInterface.NewTexture();
p->CreateTexture(256, 1, FHardwareTexture::TrueColor, false); p->CreateTexture(256, 1, FHardwareTexture::TrueColor, false);
p->LoadTexture((uint8_t*)palettes[uindex].colors); p->LoadTexture((uint8_t*)palettedata->Palette);
p->SetSampler(SamplerNoFilterClampXY); p->SetSampler(SamplerNoFilterClampXY);
palettes[uindex].paltexture = p; palettetextures[index] = p;
} }
inst->BindTexture(2, palettes[uindex].paltexture); inst->BindTexture(2, palettetextures[index]);
} }
} }
@ -241,92 +118,27 @@ void PaletteManager::BindPalette(int index)
// //
//=========================================================================== //===========================================================================
void PaletteManager::SetPalswapData(int index, const uint8_t* data, int numshades_, palette_t &fadecolor)
{
if (index < 0 || index > 255) return; // invalid index - ignore.
numshades = numshades_;
palswapmap[index] = FindPalswap(data, fadecolor);
}
//===========================================================================
//
//
//
//===========================================================================
void PaletteManager::BindPalswap(int index) void PaletteManager::BindPalswap(int index)
{ {
if (palswapmap[index] < palswaps.Size()) if (LookupTables[index].Len() == 0) index = 0;
if (LookupTables[index].Len() > 0)
{ {
auto uindex = palswapmap[index]; if (index != lastsindex)
if (uindex != lastsindex)
{ {
lastsindex = uindex; lastsindex = index;
auto& ps = palswaps[uindex]; if (palswaptextures[index] == nullptr)
if (ps.swaptexture == nullptr)
{ {
auto p = GLInterface.NewTexture(); auto p = GLInterface.NewTexture();
p->CreateTexture(256, numshades, FHardwareTexture::Indexed, false); p->CreateTexture(256, numshades, FHardwareTexture::Indexed, false);
p->LoadTexture((uint8_t*)ps.lookup); p->LoadTexture((uint8_t*)LookupTables[index].GetChars());
p->SetSampler(SamplerNoFilterClampXY); p->SetSampler(SamplerNoFilterClampXY);
ps.swaptexture = p; palswaptextures[index] = p;
} }
inst->BindTexture(1, ps.swaptexture); inst->BindTexture(1, palswaptextures[index]);
inst->SetFadeColor(ps.fadeColor); inst->SetFadeColor(PalEntry(palookupfog[index].r, palookupfog[index].g, palookupfog[index].b));
} }
} }
} }
int PaletteManager::LookupPalette(int palette, int palswap, bool brightmap, bool nontransparent255)
{
int realpal = palettemap[palette];
int realswap = palswapmap[palswap];
int combined = (nontransparent255? 0x2000000 : 0) + (brightmap? 0x1000000 : 0) + realpal * 0x10000 + realswap;
int* combinedindex = swappedpalmap.CheckKey(combined);
if (combinedindex) return *combinedindex;
PaletteData* paldata = &palettes[realpal];
PalswapData* swapdata = &palswaps[realswap];
PalEntry swappedpalette[256];
int end = paldata->colors[255].a == 255 ? 256 : 255;
if (!brightmap)
{
for (int i = 0; i < end; i++)
{
int swapi = swapdata->lookup[i];
swappedpalette[i] = paldata->colors[swapi];
swappedpalette[i].a = 255;
}
}
else
{
if (!swapdata->isbright)
{
swappedpalmap.Insert(combined, -1);
return -1;
}
bool found = false;
memset(swappedpalette, 0, sizeof(swappedpalette));
for (int i = 0; i < 255; i++)
{
int swapi = swapdata->brightcolors[i];
if (swapi)
{
found = true;
swappedpalette[i] = 0xffffffff;
}
}
if (!found)
{
swappedpalmap.Insert(combined, -1);
return -1;
}
}
if (end == 255) swappedpalette[255] = 0;
int palid = FindPalette((uint8_t*)swappedpalette);
swappedpalmap.Insert(combined, palid);
return palid;
}

View file

@ -149,7 +149,7 @@ void GLInstance::Deinit()
if (surfaceShader) delete surfaceShader; if (surfaceShader) delete surfaceShader;
surfaceShader = nullptr; surfaceShader = nullptr;
activeShader = nullptr; activeShader = nullptr;
palmanager.DeleteAllTextures(); palmanager.DeleteAll();
lastPalswapIndex = -1; lastPalswapIndex = -1;
} }

View file

@ -20,25 +20,6 @@ class F2DDrawer;
struct palette_t; struct palette_t;
extern int xdim, ydim; extern int xdim, ydim;
struct PaletteData
{
int32_t crc32;
PalEntry colors[256];
bool shadesdone;
int whiteindex, blackindex;
FHardwareTexture* paltexture;
};
struct PalswapData
{
int32_t crc32;
bool isbright;
const uint8_t *lookup; // points to the original data. This is static so no need to copy
FHardwareTexture* swaptexture;
PalEntry fadeColor;
uint8_t brightcolors[255];
};
enum enum
{ {
PALSWAP_TEXTURE_SIZE = 2048 PALSWAP_TEXTURE_SIZE = 2048
@ -46,18 +27,12 @@ enum
class PaletteManager class PaletteManager
{ {
// The current engine limit is 256 palettes and 256 palswaps. FHardwareTexture* palettetextures[256] = {};
uint32_t palettemap[256] = {}; FHardwareTexture* palswaptextures[256] = {};
uint32_t palswapmap[256] = {};
uint32_t lastindex = ~0u; uint32_t lastindex = ~0u;
uint32_t lastsindex = ~0u; uint32_t lastsindex = ~0u;
int numshades = 1;
// All data is being stored in contiguous blocks that can be used as uniform buffers as-is.
TArray<PaletteData> palettes;
TArray<PalswapData> palswaps;
TMap<int, int> swappedpalmap;
FHardwareTexture* palswapTexture = nullptr;
GLInstance* const inst; GLInstance* const inst;
//OpenGLRenderer::GLDataBuffer* palswapBuffer = nullptr; //OpenGLRenderer::GLDataBuffer* palswapBuffer = nullptr;
@ -69,17 +44,8 @@ public:
{} {}
~PaletteManager(); ~PaletteManager();
void DeleteAll(); void DeleteAll();
void DeleteAllTextures();
void SetPalette(int index, const uint8_t *data);
void SetPalswapData(int index, const uint8_t* data, int numshades, palette_t &fadecolor);
void BindPalette(int index); void BindPalette(int index);
void BindPalswap(int index); void BindPalswap(int index);
int ActivePalswap() const { return lastsindex; }
int LookupPalette(int palette, int palswap, bool brightmap, bool nontransparent255 = false);
const PalEntry *GetPaletteData(int palid) const { return palettes[palid].colors; }
unsigned FindPalette(const uint8_t* paldata);
}; };
@ -230,16 +196,6 @@ public:
renderState.mBias.mChanged = true; renderState.mBias.mChanged = true;
} }
void SetPaletteData(int index, const uint8_t* data)
{
palmanager.SetPalette(index, data);
}
void SetPalswapData(int index, const uint8_t* data, int numshades, palette_t& fadecolor)
{
palmanager.SetPalswapData(index, data, numshades, fadecolor);
}
void SetPalswap(int index); void SetPalswap(int index);
int GetClamp() int GetClamp()
@ -508,11 +464,6 @@ public:
renderState.fullscreenTint = color; renderState.fullscreenTint = color;
} }
int GetPaletteIndex(PalEntry* palette)
{
return palmanager.FindPalette((uint8_t*)palette);
}
void EnableAlphaTest(bool on) void EnableAlphaTest(bool on)
{ {
renderState.AlphaTest = on; renderState.AlphaTest = on;
@ -523,13 +474,6 @@ public:
renderState.AlphaThreshold = al; renderState.AlphaThreshold = al;
} }
int LookupPalette(int palette, int palswap, bool brightmap, bool nontransparent255 = false)
{
return palmanager.LookupPalette(palette, palswap, brightmap, nontransparent255);
}
const PalEntry* GetPaletteData(int palid) const { return palmanager.GetPaletteData(palid); }
FHardwareTexture* CreateIndexedTexture(FTexture* tex); FHardwareTexture* CreateIndexedTexture(FTexture* tex);
FHardwareTexture* CreateTrueColorTexture(FTexture* tex, int palid, bool checkfulltransparency = false, bool rgb8bit = false); FHardwareTexture* CreateTrueColorTexture(FTexture* tex, int palid, bool checkfulltransparency = false, bool rgb8bit = false);
FHardwareTexture *LoadTexture(FTexture* tex, int texturetype, int palid); FHardwareTexture *LoadTexture(FTexture* tex, int texturetype, int palid);

View file

@ -198,11 +198,10 @@ void main()
palettedColor.rgb = mix(palettedColor.rgb, palettedColorNext.rgb, shadeFrac); palettedColor.rgb = mix(palettedColor.rgb, palettedColorNext.rgb, shadeFrac);
} }
fullbright = palettedColor.a; // This only gets set for paletted rendering. palettedColor.a = color.r == 0.0? 0.0 : 1.0;// c_one-floor(color.r);
palettedColor.a = c_one-floor(color.r);
color = palettedColor; color = palettedColor;
color.rgb *= detailColor.rgb; // with all this palettizing, this can only be applied afterward, even though it is wrong to do it this way. color.rgb *= detailColor.rgb; // with all this palettizing, this can only be applied afterward, even though it is wrong to do it this way.
if (fullbright == 0.0) color.rgb *= v_color.rgb; // Well, this is dead wrong but unavoidable. For colored fog it applies the light to the fog as well... color.rgb *= v_color.rgb; // Well, this is dead wrong but unavoidable. For colored fog it applies the light to the fog as well...
} }
else else
{ {