From c4f67e9d95ff9ac7f988595bc41205da9212dadc Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 17 Oct 2016 18:43:44 +0100 Subject: [PATCH] Use lightfx palette transform --- src/drawing/lightfx.c | 195 +++++++++++++++++++++++++++++++++++++++++- src/drawing/lightfx.h | 2 + src/platform/shared.c | 22 +++-- 3 files changed, 208 insertions(+), 11 deletions(-) diff --git a/src/drawing/lightfx.c b/src/drawing/lightfx.c index 7c4ebcd302..811b23748c 100644 --- a/src/drawing/lightfx.c +++ b/src/drawing/lightfx.c @@ -14,12 +14,14 @@ *****************************************************************************/ #pragma endregion -#include "lightfx.h" -#include "drawing.h" +#include "../game.h" #include "../rct2.h" -#include "../interface/window.h" #include "../interface/viewport.h" +#include "../interface/window.h" #include "../paint/map_element/map_element.h" +#include "../world/climate.h" +#include "drawing.h" +#include "lightfx.h" static uint8 _bakedLightTexture_lantern_0[32*32]; static uint8 _bakedLightTexture_lantern_1[64*64]; @@ -66,6 +68,12 @@ static uint8 _current_view_rotation_back = 0; static uint8 _current_view_zoom_back = 0; static uint8 _current_view_zoom_back_delay = 0; +static SDL_Color gPalette_light[256]; + +static uint8 soft_light(uint8 a, uint8 b); +static uint8 lerp(uint8 a, uint8 b, float t); +static float flerp(float a, float b, float t); + uint8 calc_light_intensity_lantern(sint32 x, sint32 y) { double distance = (double)(x * x + y * y); @@ -776,4 +784,183 @@ void lightfx_add_lights_magic_vehicles() }; } } -} \ No newline at end of file +} + +void lightfx_apply_palette_filter(uint8 i, uint8 *r, uint8 *g, uint8 *b) +{ + float night = (float)(pow(gDayNightCycle, 1.5)); + + float natLightR = 1.0f; + float natLightG = 1.0f; + float natLightB = 1.0f; + + float elecMultR = 1.0f; + float elecMultG = 0.95f; + float elecMultB = 0.45f; + + static float wetness = 0.0f; + static float fogginess = 0.0f; + static float lightPolution = 0.0f; + + float sunLight = max(0.0f, min(1.0f, 2.0f - night * 3.0f)); + + // Night version + natLightR = flerp(natLightR * 4.0f, 0.635f, (float)(pow(night, 0.035f + sunLight * 10.50f))); + natLightG = flerp(natLightG * 4.0f, 0.650f, (float)(pow(night, 0.100f + sunLight * 5.50f))); + natLightB = flerp(natLightB * 4.0f, 0.850f, (float)(pow(night, 0.200f + sunLight * 1.5f))); + + float lightAvg = (natLightR + natLightG + natLightB) / 3.0f; + float lightMax = (natLightR + natLightG + natLightB) / 3.0f; + float overExpose = 0.0f; + + // overExpose += ((lightMax - lightAvg) / lightMax) * 0.01f; + + if (gClimateCurrentTemperature > 20) { + float offset = ((float)(gClimateCurrentTemperature - 20)) * 0.04f; + offset *= 1.0f - night; + lightAvg /= 1.0f + offset; + // overExpose += offset * 0.1f; + } + + // lightAvg += (lightMax - lightAvg) * 0.6f; + + if (lightAvg > 1.0f) { + natLightR /= lightAvg; + natLightG /= lightAvg; + natLightB /= lightAvg; + } + + natLightR *= 1.0f + overExpose; + natLightG *= 1.0f + overExpose; + natLightB *= 1.0f + overExpose; + overExpose *= 255.0f; + + float targetFogginess = (float)(gClimateCurrentRainLevel) / 8.0f; + targetFogginess += (night * night) * 0.15f; + + if (gClimateCurrentTemperature < 10) { + targetFogginess += ((float)(10 - gClimateCurrentTemperature)) * 0.01f; + } + + fogginess -= (fogginess - targetFogginess) * 0.00001f; + + wetness *= 0.999995f; + wetness += fogginess * 0.001f; + wetness = min(wetness, 1.0f); + + float boost = 1.0f; + float envFog = fogginess; + float lightFog = envFog; + + float addLightNatR = 0.0f; + float addLightNatG = 0.0f; + float addLightNatB = 0.0f; + + float reduceColourNat = 1.0f; + float reduceColourLit = 1.0f; + + reduceColourLit *= night / (float)pow(max(1.01f, 0.4f + lightAvg), 2.0); + + float targetLightPollution = reduceColourLit * max(0.0f, 0.0f + 0.000001f * (float)lightfx_get_light_polution()); + lightPolution -= (lightPolution - targetLightPollution) * 0.001f; + + // lightPollution /= 1.0f + fogginess * 1.0f; + + natLightR /= 1.0f + lightPolution * 20.0f; + natLightG /= 1.0f + lightPolution * 20.0f; + natLightB /= 1.0f + lightPolution * 20.0f; + natLightR += elecMultR * 0.6f * lightPolution; + natLightG += elecMultG * 0.6f * lightPolution; + natLightB += elecMultB * 0.6f * lightPolution; + natLightR /= 1.0f + lightPolution; + natLightG /= 1.0f + lightPolution; + natLightB /= 1.0f + lightPolution; + + reduceColourLit += (float)(gClimateCurrentRainLevel) / 2.0f; + + reduceColourNat /= 1.0f + fogginess; + reduceColourLit /= 1.0f + fogginess; + + lightFog *= reduceColourLit; + + reduceColourNat *= 1.0f - envFog; + reduceColourLit *= 1.0f - lightFog; + + float fogR = 35.5f * natLightR * 1.3f; + float fogG = 45.0f * natLightG * 1.3f; + float fogB = 50.0f * natLightB * 1.3f; + lightFog *= 10.0f; + + float wetnessBoost = 1.0f;//1.0f + wetness * wetness * 0.1f; + + if (night >= 0 && gClimateLightningFlash != 1) { + *r = lerp(*r, soft_light(*r, 8), night); + *g = lerp(*g, soft_light(*g, 8), night); + *b = lerp(*b, soft_light(*b, 128), night); + + // if (i == 32) + // boost = 300000.0f; + if ((i % 32) == 0) + boost = 1.01f * wetnessBoost; + else if ((i % 16) < 7) + boost = 1.001f * wetnessBoost; + if (i > 230 && i < 232) + boost = ((float)(*b)) / 64.0f; + + if (false) { + // This experiment shifts the colour of pixels as-if they are wet, but it is not a pretty solution at all + if ((i % 16)) { + float iVal = ((float)((i + 12) % 16)) / 16.0f; + float eff = (wetness * ((float)pow(iVal, 1.5) * 0.85f)); + reduceColourNat *= 1.0f - eff; + addLightNatR += fogR * eff * 3.95f; + addLightNatG += fogR * eff * 3.95f; + addLightNatB += fogR * eff * 3.95f; + } + } + + addLightNatR *= 1.0f - envFog; + addLightNatG *= 1.0f - envFog; + addLightNatB *= 1.0f - envFog; + + *r = (uint8)(min(255.0f, max(0.0f, (-overExpose + (float)(*r) * reduceColourNat * natLightR + envFog * fogR + addLightNatR)))); + *g = (uint8)(min(255.0f, max(0.0f, (-overExpose + (float)(*g) * reduceColourNat * natLightG + envFog * fogG + addLightNatG)))); + *b = (uint8)(min(255.0f, max(0.0f, (-overExpose + (float)(*b) * reduceColourNat * natLightB + envFog * fogB + addLightNatB)))); + gPalette_light[i].r = (uint8)(min(0xFF, ((float)(*r) * reduceColourLit * boost + lightFog) * elecMultR)); + gPalette_light[i].g = (uint8)(min(0xFF, ((float)(*g) * reduceColourLit * boost + lightFog) * elecMultG)); + gPalette_light[i].b = (uint8)(min(0xFF, ((float)(*b) * reduceColourLit * boost + lightFog) * elecMultB)); + } +} + +static uint8 soft_light(uint8 a, uint8 b) +{ + float fa = a / 255.0f; + float fb = b / 255.0f; + float fr; + if (fb < 0.5f) { + fr = (2 * fa * fb) + ((fa * fa) * (1 - (2 * fb))); + } else { + fr = (2 * fa * (1 - fb)) + (sqrtf(fa) * ((2 * fb) - 1)); + } + return (uint8)(clamp(0.0f, fr, 1.0f) * 255.0f); +} + +static uint8 lerp(uint8 a, uint8 b, float t) +{ + if (t <= 0) return a; + if (t >= 1) return b; + + int range = b - a; + int amount = (int)(range * t); + return (uint8)(a + amount); +} + +static float flerp(float a, float b, float t) +{ + if (t <= 0) return a; + if (t >= 1) return b; + + float range = b - a; + float amount = range * t; + return a + amount; +} diff --git a/src/drawing/lightfx.h b/src/drawing/lightfx.h index c39cb44f8d..3e5adf46ab 100644 --- a/src/drawing/lightfx.h +++ b/src/drawing/lightfx.h @@ -63,5 +63,7 @@ extern void lightfx_add_lights_magic_vehicles(); extern uint32 lightfx_get_light_polution(); +void lightfx_apply_palette_filter(uint8 i, uint8 *r, uint8 *g, uint8 *b); + #endif #endif \ No newline at end of file diff --git a/src/platform/shared.c b/src/platform/shared.c index f71e61ecc5..fea87b087e 100644 --- a/src/platform/shared.c +++ b/src/platform/shared.c @@ -18,6 +18,7 @@ #include "../audio/mixer.h" #include "../config.h" #include "../drawing/drawing.h" +#include "../drawing/lightfx.h" #include "../game.h" #include "../input.h" #include "../interface/console.h" @@ -254,18 +255,25 @@ void platform_update_palette(const uint8* colours, int start_index, int num_colo colours += start_index * 4; for (int i = start_index; i < num_colours + start_index; i++) { - gPalette[i].r = colours[2]; - gPalette[i].g = colours[1]; - gPalette[i].b = colours[0]; - gPalette[i].a = 0; + uint8 r = colours[2]; + uint8 g = colours[1]; + uint8 b = colours[0]; +#ifdef STOUT_EXPANDED_RENDERING_LIGHT + lightfx_apply_palette_filter(i, &r, &g, &b); +#else float night = gDayNightCycle; if (night >= 0 && gClimateLightningFlash == 0) { - gPalette[i].r = lerp(gPalette[i].r, soft_light(gPalette[i].r, 8), night); - gPalette[i].g = lerp(gPalette[i].g, soft_light(gPalette[i].g, 8), night); - gPalette[i].b = lerp(gPalette[i].b, soft_light(gPalette[i].b, 128), night); + r = lerp(r, soft_light(r, 8), night); + g = lerp(g, soft_light(g, 8), night); + b = lerp(b, soft_light(b, 128), night); } +#endif + gPalette[i].r = r; + gPalette[i].g = g; + gPalette[i].b = b; + gPalette[i].a = 0; colours += 4; if (gBufferTextureFormat != NULL) { gPaletteHWMapped[i] = SDL_MapRGB(gBufferTextureFormat, gPalette[i].r, gPalette[i].g, gPalette[i].b);