From b580b635eb752ba6cc60d34495f6a1ef39819762 Mon Sep 17 00:00:00 2001 From: staphen Date: Wed, 12 May 2021 23:33:10 -0400 Subject: [PATCH] Optimize blended transparency calculations at the end of Poisoned Water Supply. --- Source/diablo.cpp | 2 ++ Source/palette.cpp | 71 ++++++++++++++++++++++++++++------------------ Source/palette.h | 2 +- Source/quests.cpp | 17 +++++++---- Source/quests.h | 1 + 5 files changed, 60 insertions(+), 33 deletions(-) diff --git a/Source/diablo.cpp b/Source/diablo.cpp index d60118122..1c0d886f9 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1960,6 +1960,8 @@ void diablo_color_cyc_logic() palette_update_crypt(); } else if (currlevel >= 17) { palette_update_hive(); + } else if (setlevel && setlvlnum == quests[Q_PWATER]._qslvl) { + UpdatePWaterPalette(); } else if (leveltype == DTYPE_CAVES) { palette_update_caves(); } diff --git a/Source/palette.cpp b/Source/palette.cpp index fa493a5b2..72f5a5ef9 100644 --- a/Source/palette.cpp +++ b/Source/palette.cpp @@ -65,6 +65,26 @@ void palette_init() InitPalette(); } +static Uint8 FindBestMatchForColor(SDL_Color *palette, SDL_Color color, int skipFrom, int skipTo) +{ + Uint8 best; + Uint32 bestDiff = SDL_MAX_UINT32; + for (int i = 0; i < 256; i++) { + if (i >= skipFrom && i <= skipTo) + continue; + int diffr = palette[i].r - color.r; + int diffg = palette[i].g - color.g; + int diffb = palette[i].b - color.b; + Uint32 diff = diffr * diffr + diffg * diffg + diffb * diffb; + + if (bestDiff > diff) { + best = i; + bestDiff = diff; + } + } + return best; +} + /** * @brief Generate lookup table for transparency * @@ -94,30 +114,17 @@ static void GenerateBlendedLookupTable(SDL_Color *palette, int skipFrom, int ski continue; } - Uint8 r = ((int)palette[i].r + (int)palette[j].r) / 2; - Uint8 g = ((int)palette[i].g + (int)palette[j].g) / 2; - Uint8 b = ((int)palette[i].b + (int)palette[j].b) / 2; - Uint8 best; - Uint32 bestDiff = SDL_MAX_UINT32; - for (int k = 0; k < 256; k++) { - if (k >= skipFrom && k <= skipTo) - continue; - int diffr = palette[k].r - r; - int diffg = palette[k].g - g; - int diffb = palette[k].b - b; - Uint32 diff = diffr * diffr + diffg * diffg + diffb * diffb; - - if (bestDiff > diff) { - best = k; - bestDiff = diff; - } - } + SDL_Color blendedColor; + blendedColor.r = ((int)palette[i].r + (int)palette[j].r) / 2; + blendedColor.g = ((int)palette[i].g + (int)palette[j].g) / 2; + blendedColor.b = ((int)palette[i].b + (int)palette[j].b) / 2; + Uint8 best = FindBestMatchForColor(palette, blendedColor, skipFrom, skipTo); paletteTransparencyLookup[i][j] = best; } } } -void LoadPalette(const char *pszFileName) +void LoadPalette(const char *pszFileName, bool blend /*= true*/) { assert(pszFileName); @@ -140,7 +147,7 @@ void LoadPalette(const char *pszFileName) #endif } - if (sgOptions.Graphics.bBlendedTransparancy) { + if (blend && sgOptions.Graphics.bBlendedTransparancy) { if (leveltype == DTYPE_CAVES || leveltype == DTYPE_CRYPT) { GenerateBlendedLookupTable(orig_palette, 1, 31); } else if (leveltype == DTYPE_NEST) { @@ -374,15 +381,25 @@ void palette_update_hive() void palette_update_quest_palette(int n) { - int i; - - for (i = 32 - n; i >= 0; i--) { - logical_palette[i] = orig_palette[i]; - } + int i = 32 - n; + logical_palette[i] = orig_palette[i]; ApplyGamma(system_palette, logical_palette, 32); palette_update(); - if (sgOptions.Graphics.bBlendedTransparancy) - GenerateBlendedLookupTable(logical_palette, 1, 31, 32 - n); // Possible optimization would be to only update color 0 as only the UI can overlap with transparency in this quest + if (sgOptions.Graphics.bBlendedTransparancy) { + // Update blended transparency, but only for the color that was updated + for (int j = 0; j < 256; j++) { + if (i == j) { // No need to calculate transparency between 2 identical colors + paletteTransparencyLookup[i][j] = j; + continue; + } + SDL_Color blendedColor; + blendedColor.r = ((int)logical_palette[i].r + (int)logical_palette[j].r) / 2; + blendedColor.g = ((int)logical_palette[i].g + (int)logical_palette[j].g) / 2; + blendedColor.b = ((int)logical_palette[i].b + (int)logical_palette[j].b) / 2; + Uint8 best = FindBestMatchForColor(logical_palette, blendedColor, 1, 31); + paletteTransparencyLookup[i][j] = paletteTransparencyLookup[j][i] = best; + } + } } } // namespace devilution diff --git a/Source/palette.h b/Source/palette.h index 44e19b45c..4aa334528 100644 --- a/Source/palette.h +++ b/Source/palette.h @@ -36,7 +36,7 @@ extern Uint8 paletteTransparencyLookup[256][256]; void palette_update(); void palette_init(); -void LoadPalette(const char *pszFileName); +void LoadPalette(const char *pszFileName, bool blend = true); void LoadRndLvlPal(dungeon_type l); void ResetPal(); void IncreaseGamma(); diff --git a/Source/quests.cpp b/Source/quests.cpp index af7fd97d9..6ae95d502 100644 --- a/Source/quests.cpp +++ b/Source/quests.cpp @@ -240,13 +240,10 @@ void CheckQuests() && quests[Q_PWATER]._qactive != QUEST_DONE) { quests[Q_PWATER]._qactive = QUEST_DONE; PlaySfxLoc(IS_QUESTDN, plr[myplr].position.tile.x, plr[myplr].position.tile.y); - LoadPalette("Levels\\L3Data\\L3pwater.pal"); + LoadPalette("Levels\\L3Data\\L3pwater.pal", false); + UpdatePWaterPalette(); WaterDone = 32; } - if (WaterDone > 0) { - palette_update_quest_palette(WaterDone); - WaterDone--; - } } else if (plr[myplr]._pmode == PM_STAND) { for (i = 0; i < MAXQUESTS; i++) { if (currlevel == quests[i]._qlevel @@ -584,6 +581,16 @@ void LoadPWaterPalette() LoadPalette("Levels\\L3Data\\L3pfoul.pal"); } +void UpdatePWaterPalette() +{ + if (WaterDone > 0) { + palette_update_quest_palette(WaterDone); + WaterDone--; + return; + } + palette_update_caves(); +} + void ResyncMPQuests() { if (gbIsSpawn) diff --git a/Source/quests.h b/Source/quests.h index 5dc4bef79..5c1035d10 100644 --- a/Source/quests.h +++ b/Source/quests.h @@ -83,6 +83,7 @@ void DRLG_CheckQuests(int x, int y); void SetReturnLvlPos(); void GetReturnLvlPos(); void LoadPWaterPalette(); +void UpdatePWaterPalette(); void ResyncMPQuests(); void ResyncQuests(); void DrawQuestLog(const CelOutputBuffer &out);