diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index 3f5b97243..6a71913bd 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -134,7 +134,6 @@ coltypef fogcol, fogtable[MAXPALOOKUPS]; static GLuint quadVertsID = 0; -#define PALSWAP_TEXTURE_SIZE 2048 int32_t r_useindexedcolortextures = -1; static FHardwareTexture *palswapTextureID = nullptr; @@ -364,7 +363,6 @@ static void polymost_bindPth(pthtyp const* const pPth, int sampler) FileReader GetBaseResource(const char* fn); -void uploadpalswap(int32_t palookupnum); // one-time initialization of OpenGL for polymost void polymost_glinit() @@ -378,8 +376,9 @@ void polymost_glinit() palswapTextureID = 0; for (int palookupnum = 0; palookupnum < MAXPALOOKUPS; ++palookupnum) { - uploadpalswap(palookupnum); - } + GLInterface.SetPalswapData(palookupnum, palookup[palookupnum]); + } + GLInterface.UpdatePalswaps(256, numshades+1); } ////////// VISIBILITY FOG ROUTINES ////////// @@ -709,47 +708,9 @@ void uploadpalswaps(int count, int32_t* swaps) { for (int i = 0; i < count; i++) { - uploadpalswap(i); + GLInterface.SetPalswapData(i, (uint8_t*)palookup[i]); } -} - -void uploadpalswap(int32_t palookupnum) -{ - if (!palookup[palookupnum]) - { - return; - } - - // No point porting this, it's too much work for a short lived solution. -#if 0 - char allocateTexture = !palswapTextureID; - if (allocateTexture) - { - G etTextureHandle(&palswapTextureID); - } - g lBindTexture(GL _TEXTURE_2D, palswapTextureID); - if (allocateTexture) - { - g lTexParameteri(GL _TEXTURE_2D, GL _TEXTURE_BASE_LEVEL, 0); - g lTexParameteri(GL _TEXTURE_2D, GL _TEXTURE_MAX_LEVEL, 0); - g lTexParameteri(GL _TEXTURE_2D, GL _TEXTURE_MAG_FILTER, GL _NEAREST); - g lTexParameteri(GL _TEXTURE_2D, GL _TEXTURE_MIN_FILTER, GL _NEAREST); - g lTexParameteri(GL _TEXTURE_2D, GL _TEXTURE_MAX_ANISOTROPY_EXT, 1); - g lTexParameteri(GL _TEXTURE_2D, GL _TEXTURE_WRAP_S, GL _CLAMP_TO_EDGE); - g lTexParameteri(GL _TEXTURE_2D, GL _TEXTURE_WRAP_T, GL _CLAMP_TO_EDGE); - g lTexImage2D(GL _TEXTURE_2D, 0, GL _RED, PALSWAP_TEXTURE_SIZE, PALSWAP_TEXTURE_SIZE, 0, GL _RED, GL _UNSIGNED_BYTE, NULL); - } - - int32_t column = palookupnum%(PALSWAP_TEXTURE_SIZE/256); - int32_t row = palookupnum/(PALSWAP_TEXTURE_SIZE/256); - int32_t rowOffset = (numshades+1)*row; - if (rowOffset > PALSWAP_TEXTURE_SIZE) - { - OSD_Printf("Polymost: palswaps are too large for palswap tilesheet!\n"); - return; - } - g lTexSubImage2D(GL _TEXTURE_2D, 0, 256*column, rowOffset, 256, numshades+1, GL _RED, GL _UNSIGNED_BYTE, palookup[palookupnum]); -#endif + GLInterface.UpdatePalswaps(256, numshades + 1); } diff --git a/source/glbackend/gl_palmanager.cpp b/source/glbackend/gl_palmanager.cpp index c195d5289..e3daaf6d1 100644 --- a/source/glbackend/gl_palmanager.cpp +++ b/source/glbackend/gl_palmanager.cpp @@ -43,7 +43,6 @@ #include "baselayer.h" #include "resourcefile.h" - //=========================================================================== // // The palette manager will contain all palettes being used for texture @@ -70,6 +69,8 @@ void PaletteManager::DeleteAll() if (pal.paltexture) delete pal.paltexture; } if (transientpalette.paltexture) delete transientpalette.paltexture; + if (palswapTexture) delete palswapTexture; + palswapTexture = nullptr; transientpalette.paltexture = nullptr; transientpalette.crc32 = -1; palettes.Reset(); @@ -77,6 +78,7 @@ void PaletteManager::DeleteAll() lastindex = -1; memset(palettemap, 0, sizeof(palettemap)); memset(palswapmap, 0, sizeof(palswapmap)); + } //=========================================================================== @@ -102,9 +104,35 @@ unsigned PaletteManager::FindPalette(const uint8_t *paldata) 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) +{ + auto crc32 = CalcCRC32(paldata, 256); + for (unsigned int i = 0; i < palswaps.Size(); i++) + { + if (crc32 == palswaps[i].crc32) + { + if (!memcmp(paldata, palswaps[i].swaps, 256)) + { + return i; + } + } + } + PalswapData pd; + memcpy(pd.swaps, paldata, 256); + pd.crc32 = crc32; + return palswaps.Push(pd); +} + //=========================================================================== // // @@ -174,38 +202,104 @@ void PaletteManager::BindPalette(int index) } +//=========================================================================== +// +// +// +//=========================================================================== + +void PaletteManager::SetPalswapData(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. + palswapmap[index] = FindPalswap(data); + +} + +void PaletteManager::UpdatePalswaps(int width, int height) +{ + if (palswapTexture) delete palswapTexture; + for (auto& pal : palettes) + { + pal.shadesdone = false; + } + // recreate it + + vec2f_t polymost1PalswapSize = { width * (1.f / PALSWAP_TEXTURE_SIZE), + height * (1.f / PALSWAP_TEXTURE_SIZE) }; + + vec2f_t polymost1PalswapInnerSize = { (width - 1) * (1.f / PALSWAP_TEXTURE_SIZE), + (height - 1) * (1.f / PALSWAP_TEXTURE_SIZE) }; + + inst->SetPalswapSize(&polymost1PalswapInnerSize.x); + +} + + +void GLInstance::SetPalswap(int index) +{ + float v1 = index * renderState.PalswapSize[0]; + float v2 = floorf(v1); + renderState.PalswapPos[0] = renderState.PalswapPos[0] - renderState.PalswapPos[1] + (0.5f / PALSWAP_TEXTURE_SIZE); + renderState.PalswapPos[1] = renderState.PalswapPos[1] * renderState.PalswapSize[1] + (0.5f / PALSWAP_TEXTURE_SIZE); +} #if 0 -static void polymost_setPalswap(uint32_t index) -{ - static uint32_t lastPalswapIndex; - - if (currentShaderProgramID != polymost1CurrentShaderProgramID) - return; - - lastPalswapIndex = index; - polymost1PalswapPos.x = index * polymost1PalswapSize.x; - polymost1PalswapPos.y = floorf(polymost1PalswapPos.x); - polymost1PalswapPos = { polymost1PalswapPos.x - polymost1PalswapPos.y + (0.5f / PALSWAP_TEXTURE_SIZE), - polymost1PalswapPos.y * polymost1PalswapSize.y + (0.5f / PALSWAP_TEXTURE_SIZE) }; - glUniform2f(polymost1PalswapPosLoc, polymost1PalswapPos.x, polymost1PalswapPos.y); -} - static void polymost_setPalswapSize(uint32_t width, uint32_t height) { if (currentShaderProgramID != polymost1CurrentShaderProgramID) return; - polymost1PalswapSize = { width * (1.f / PALSWAP_TEXTURE_SIZE), - height * (1.f / PALSWAP_TEXTURE_SIZE) }; - - polymost1PalswapInnerSize = { (width - 1) * (1.f / PALSWAP_TEXTURE_SIZE), - (height - 1) * (1.f / PALSWAP_TEXTURE_SIZE) }; - - glUniform2f(polymost1PalswapSizeLoc, polymost1PalswapInnerSize.x, polymost1PalswapInnerSize.y); } -#endif \ No newline at end of file +#endif + +// No point porting this, it's too much work for a short lived solution. +#if 0 +char allocateTexture = !palswapTextureID; +if (allocateTexture) +{ + G etTextureHandle(&palswapTextureID); +} +g lBindTexture(GL _TEXTURE_2D, palswapTextureID); +if (allocateTexture) +{ + g lTexParameteri(GL _TEXTURE_2D, GL _TEXTURE_BASE_LEVEL, 0); + g lTexParameteri(GL _TEXTURE_2D, GL _TEXTURE_MAX_LEVEL, 0); + g lTexParameteri(GL _TEXTURE_2D, GL _TEXTURE_MAG_FILTER, GL _NEAREST); + g lTexParameteri(GL _TEXTURE_2D, GL _TEXTURE_MIN_FILTER, GL _NEAREST); + g lTexParameteri(GL _TEXTURE_2D, GL _TEXTURE_MAX_ANISOTROPY_EXT, 1); + g lTexParameteri(GL _TEXTURE_2D, GL _TEXTURE_WRAP_S, GL _CLAMP_TO_EDGE); + g lTexParameteri(GL _TEXTURE_2D, GL _TEXTURE_WRAP_T, GL _CLAMP_TO_EDGE); + g lTexImage2D(GL _TEXTURE_2D, 0, GL _RED, PALSWAP_TEXTURE_SIZE, PALSWAP_TEXTURE_SIZE, 0, GL _RED, GL _UNSIGNED_BYTE, NULL); +} + +int32_t column = palookupnum % (PALSWAP_TEXTURE_SIZE / 256); +int32_t row = palookupnum / (PALSWAP_TEXTURE_SIZE / 256); +int32_t rowOffset = (numshades + 1) * row; +if (rowOffset > PALSWAP_TEXTURE_SIZE) +{ + OSD_Printf("Polymost: palswaps are too large for palswap tilesheet!\n"); + return; +} +g lTexSubImage2D(GL _TEXTURE_2D, 0, 256 * column, rowOffset, 256, numshades + 1, GL _RED, GL _UNSIGNED_BYTE, palookup[palookupnum]); + +polymost_setPalswapSize(256, numshades + 1); + +static void polymost_updatePalette() +{ + if (videoGetRenderMode() != REND_POLYMOST) + { + return; + } + + polymost_setPalswap(globalpal); + polymost_setShade(globalshade); + +} +#endif diff --git a/source/glbackend/gl_renderstate.h b/source/glbackend/gl_renderstate.h index 1ba5703ae..73ca79a6b 100644 --- a/source/glbackend/gl_renderstate.h +++ b/source/glbackend/gl_renderstate.h @@ -5,8 +5,8 @@ class PolymostShader; struct PolymostRenderState { int PalSwapIndex; - //float PalswapPos[2]; - //float PalswapSize[2]; + float PalswapPos[2]; + float PalswapSize[2]; float Clamp[2]; float Shade; float NumShades = 64.f; diff --git a/source/glbackend/gl_shader.h b/source/glbackend/gl_shader.h index 0ceb52873..3b4ed68b4 100644 --- a/source/glbackend/gl_shader.h +++ b/source/glbackend/gl_shader.h @@ -35,6 +35,7 @@ public: class PolymostShader : public FShader { public: + FBufferedUniform1f PalswapIndex; FBufferedUniform2f PalswapPos; FBufferedUniform2f PalswapSize; FBufferedUniform2f Clamp; diff --git a/source/glbackend/glbackend.cpp b/source/glbackend/glbackend.cpp index b7c94480c..ffa7cd12e 100644 --- a/source/glbackend/glbackend.cpp +++ b/source/glbackend/glbackend.cpp @@ -158,6 +158,7 @@ void GLInstance::Deinit() vpxShader = nullptr; activeShader = nullptr; palmanager.DeleteAll(); + lastPalswapIndex = -1; } std::pair GLInstance::AllocVertices(size_t num) @@ -455,5 +456,9 @@ void PolymostRenderState::Apply(PolymostShader* shader) shader->Brightness.Set(Brightness); shader->Fog.Set(Fog); shader->FogColor.Set(FogColor); + shader->PalswapPos.Set(PalswapPos); + shader->PalswapSize.Set(PalswapSize); + shader->PalswapIndex.Set(PalSwapIndex); + } diff --git a/source/glbackend/glbackend.h b/source/glbackend/glbackend.h index e8631c27f..13dae1864 100644 --- a/source/glbackend/glbackend.h +++ b/source/glbackend/glbackend.h @@ -20,9 +20,28 @@ struct PaletteData { int32_t crc32; PalEntry colors[256]; + float shades[512]; // two values (addshade and mulshade for each palswap.) + bool shadesdone; FHardwareTexture* paltexture; }; +struct PalShade +{ + int palindex; + float mulshade, addshade; +}; + +struct PalswapData +{ + int32_t crc32; + uint8_t swaps[256]; +}; + +enum +{ + PALSWAP_TEXTURE_SIZE = 2048 +}; + class PaletteManager { // The current engine limit is 256 palettes and 256 palswaps. @@ -36,12 +55,14 @@ class PaletteManager // All data is being stored in contiguous blocks that can be used as uniform buffers as-is. TArray palettes; - TArray palswaps; + TArray palswaps; + FHardwareTexture* palswapTexture = nullptr; GLInstance* const inst; //OpenGLRenderer::GLDataBuffer* palswapBuffer = nullptr; unsigned FindPalette(const uint8_t* paldata); + unsigned FindPalswap(const uint8_t* paldata); public: PaletteManager(GLInstance *inst_) : inst(inst_) @@ -49,7 +70,8 @@ public: ~PaletteManager(); void DeleteAll(); void SetPalette(int index, const uint8_t *data, bool transient); - void AddPalswap(const uint8_t* data); + void SetPalswapData(int index, const uint8_t* data); + void UpdatePalswaps(int w, int h); void BindPalette(int index); }; @@ -169,7 +191,9 @@ class GLInstance int currentindex = THCACHESIZE; int maxTextureSize; PaletteManager palmanager; - + int lastPalswapIndex = -1; + + VSMatrix matrices[NUMMATRICES]; PolymostRenderState renderState; FShader* activeShader; @@ -254,10 +278,22 @@ public: palmanager.SetPalette(index, data, transient); } - - void SetPalswap(uint32_t index) + void SetPalswapData(int index, const uint8_t* data) { - renderState.PalSwapIndex = index; + palmanager.SetPalswapData(index, data); + } + + void UpdatePalswaps(int w, int h) + { + palmanager.UpdatePalswaps(w, h); + } + + void SetPalswap(int index); + + void SetPalswapSize(float* pos) + { + renderState.PalswapSize[0] = pos[0]; + renderState.PalswapSize[1] = pos[1]; } int GetClamp()