Browse Source

palette_update_quest_palette: tone map 1 color (#8027)

Co-authored-by: Stephen C. Wills <swills@gridprotectionalliance.org>
pull/8031/head
Gleb Mazovetskiy 10 months ago committed by GitHub
parent
commit
c3d8595b72
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      Source/DiabloUI/diabloui.cpp
  2. 82
      Source/engine/palette.cpp
  3. 3
      Source/engine/palette.h
  4. 2
      Source/interfac.cpp

4
Source/DiabloUI/diabloui.cpp

@ -653,7 +653,7 @@ Sint16 GetCenterOffset(Sint16 w, Sint16 bw)
void UiLoadDefaultPalette()
{
LoadPalette("ui_art\\diablo.pal", /*blend=*/false);
ApplyToneMapping(logical_palette, orig_palette, 256);
ApplyToneMapping(logical_palette, orig_palette);
}
bool UiLoadBlackBackground()
@ -673,7 +673,7 @@ void LoadBackgroundArt(const char *pszFile, int frames)
return;
LoadPalInMem(pPal);
ApplyToneMapping(logical_palette, orig_palette, 256);
ApplyToneMapping(logical_palette, orig_palette);
UiOnBackgroundChange();
}

82
Source/engine/palette.cpp

@ -5,7 +5,10 @@
*/
#include "engine/palette.h"
#include <algorithm>
#include <array>
#include <cstdint>
#include <span>
#include <fmt/core.h>
@ -79,48 +82,50 @@ void CycleColorsReverse(int from, int to)
#endif
}
} // namespace
// When brightness==0, then a==0 (identity mapping)
// When brightness==100, then a==-MaxAdjustment (maximum brightening)
constexpr float CalculateToneMappingParameter(int brightness)
{
// Maximum adjustment factor (tweak this constant to change the effect strength)
constexpr float MaxAdjustment = 2.0F;
return -(brightness / 100.0f) * MaxAdjustment;
}
void palette_update(int first, int ncolor)
constexpr uint8_t MapTone(float a, uint8_t color)
{
if (HeadlessMode)
return;
const auto x = static_cast<float>(color / 255.0f);
// Our quadratic tone mapping: f(x) = a*x^2 + (1-a)*x.
const float y = std::clamp(a * x * x + (1.0f - a) * x, 0.0f, 1.0f);
return static_cast<uint8_t>(y * 255.0f + 0.5f);
}
assert(Palette);
if (SDLC_SetSurfaceAndPaletteColors(PalSurface, Palette.get(), system_palette.data(), first, ncolor) < 0) {
ErrSdl();
}
pal_surface_palette_version++;
void ApplyToneMappingSingleColor(SDL_Color &dst, const SDL_Color &src)
{
const float a = CalculateToneMappingParameter(*GetOptions().Graphics.brightness);
dst.r = MapTone(a, src.r);
dst.g = MapTone(a, src.g);
dst.b = MapTone(a, src.b);
}
} // namespace
// Applies a tone mapping curve based on the brightness slider value.
// The brightness value is in the range [0, 100] where 0 is neutral (no change)
// and 100 produces maximum brightening.
void ApplyToneMapping(std::array<SDL_Color, 256> &dst,
const std::array<SDL_Color, 256> &src,
int n)
void ApplyToneMapping(std::array<SDL_Color, 256> &dst, std::span<const SDL_Color, 256> src)
{
// Get the brightness slider value (0 = neutral, 100 = max brightening)
int brightnessSlider = *GetOptions().Graphics.brightness; // New brightness setting.
// Maximum adjustment factor (tweak this constant to change the effect strength)
const float maxAdjustment = 2.0f;
// Compute the quadratic parameter:
// When brightnessSlider==0, then a==0 (identity mapping)
// When brightnessSlider==100, then a== -maxAdjustment (maximum brightening)
float a = -(brightnessSlider / 100.0f) * maxAdjustment;
const int brightnessSlider = *GetOptions().Graphics.brightness;
// Precompute a lookup table for speed.
const float a = CalculateToneMappingParameter(brightnessSlider);
uint8_t toneMap[256];
for (int i = 0; i < 256; i++) {
float x = i / 255.0f;
// Our quadratic tone mapping: f(x) = a*x^2 + (1-a)*x.
const float y = std::clamp(a * x * x + (1.0f - a) * x, 0.0f, 1.0f);
toneMap[i] = static_cast<uint8_t>(y * 255.0f + 0.5f);
toneMap[i] = MapTone(a, i);
}
// Apply the lookup table to each color channel in the palette.
for (int i = 0; i < n; i++) {
for (int i = 0; i < 256; i++) {
dst[i].r = toneMap[src[i].r];
dst[i].g = toneMap[src[i].g];
dst[i].b = toneMap[src[i].b];
@ -128,6 +133,18 @@ void ApplyToneMapping(std::array<SDL_Color, 256> &dst,
RedrawEverything();
}
void palette_update(int first, int ncolor)
{
if (HeadlessMode)
return;
assert(Palette);
if (SDLC_SetSurfaceAndPaletteColors(PalSurface, Palette.get(), system_palette.data(), first, ncolor) < 0) {
ErrSdl();
}
pal_surface_palette_version++;
}
void palette_init()
{
LoadBrightness();
@ -206,7 +223,7 @@ void IncreaseBrightness()
if (brightnessValue < 100) {
int newBrightness = std::min(brightnessValue + 5, 100);
GetOptions().Graphics.brightness.SetValue(newBrightness);
ApplyToneMapping(system_palette, logical_palette, 256);
ApplyToneMapping(system_palette, logical_palette);
palette_update();
}
}
@ -217,7 +234,7 @@ void DecreaseBrightness()
if (brightnessValue > 0) {
int newBrightness = std::max(brightnessValue - 5, 0);
GetOptions().Graphics.brightness.SetValue(newBrightness);
ApplyToneMapping(system_palette, logical_palette, 256);
ApplyToneMapping(system_palette, logical_palette);
palette_update();
}
}
@ -226,7 +243,7 @@ int UpdateBrightness(int brightness)
{
if (brightness >= 0) {
GetOptions().Graphics.brightness.SetValue(brightness);
ApplyToneMapping(system_palette, logical_palette, 256);
ApplyToneMapping(system_palette, logical_palette);
palette_update();
}
@ -267,7 +284,7 @@ void PaletteFadeIn(int fr, const std::array<SDL_Color, 256> &srcPalette)
if (demo::IsRunning())
fr = 0;
ApplyToneMapping(logical_palette, srcPalette, 256);
ApplyToneMapping(logical_palette, srcPalette);
if (fr > 0) {
const uint32_t tc = SDL_GetTicks();
@ -368,10 +385,11 @@ void palette_update_hive()
void palette_update_quest_palette(int n)
{
int i = 32 - n;
// n is in [1, 32], so `i` is in [0, 31].
const int i = 32 - n;
logical_palette[i] = orig_palette[i];
ApplyToneMapping(system_palette, logical_palette, 32);
palette_update(0, 31);
ApplyToneMappingSingleColor(system_palette[i], logical_palette[i]);
palette_update(i, 1);
UpdateBlendedLookupTableSingleColor(i, logical_palette.data(), /*skipFrom=*/1, /*skipTo=*/31);
}

3
Source/engine/palette.h

@ -7,6 +7,7 @@
#include <array>
#include <cstdint>
#include <span>
#include <SDL.h>
@ -43,7 +44,7 @@ void palette_init();
void LoadPalette(const char *pszFileName, bool blend = true);
void LoadRndLvlPal(dungeon_type l);
void IncreaseBrightness();
void ApplyToneMapping(std::array<SDL_Color, 256> &dst, const std::array<SDL_Color, 256> &src, int n);
void ApplyToneMapping(std::array<SDL_Color, 256> &dst, std::span<const SDL_Color, 256> src);
void DecreaseBrightness();
int UpdateBrightness(int sliderValue);
void BlackPalette();

2
Source/interfac.cpp

@ -479,7 +479,7 @@ void ProgressEventHandler(const SDL_Event &event, uint16_t modState)
if (RenderDirectlyToOutputSurface && PalSurface != nullptr) {
// The loading thread sets `orig_palette`, so we make sure to use
// our own palette for drawing the foreground.
ApplyToneMapping(logical_palette, ProgressEventHandlerState.palette, 256);
ApplyToneMapping(logical_palette, ProgressEventHandlerState.palette);
// Ensure that all back buffers have the full progress bar.
const void *initialPixels = PalSurface->pixels;

Loading…
Cancel
Save