Browse Source

Optimize blended transparency calculations at the end of Poisoned Water Supply.

pull/1938/head
staphen 5 years ago committed by Anders Jenbo
parent
commit
b580b635eb
  1. 2
      Source/diablo.cpp
  2. 71
      Source/palette.cpp
  3. 2
      Source/palette.h
  4. 17
      Source/quests.cpp
  5. 1
      Source/quests.h

2
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();
}

71
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

2
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();

17
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)

1
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);

Loading…
Cancel
Save