From baf749e5c3ebae915011fa94f4bb49080457b462 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Sun, 8 Mar 2026 13:15:13 -0400 Subject: [PATCH] Lua colorlib: extracolormap support --- src/CMakeLists.txt | 1 + src/hardware/hw_defs.h | 3 - src/hardware/hw_main.c | 8 +- src/hardware/hw_shaders.h | 2 +- src/lua_baselib.c | 6 +- src/lua_colorlib.c | 334 ++++++++++++++++++++++++++++++++++++++ src/lua_libs.h | 3 + src/lua_maplib.c | 5 + src/lua_script.c | 1 + src/m_misc.cpp | 34 ++++ src/m_misc.h | 4 + src/r_data.c | 244 +++++++++++----------------- src/r_data.h | 1 + 13 files changed, 486 insertions(+), 160 deletions(-) create mode 100644 src/lua_colorlib.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dd7eb65ee..5f81a30f4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -118,6 +118,7 @@ add_executable(BLANKART MACOSX_BUNDLE WIN32 lua_botvarslib.c lua_hudlib.c lua_hudlib_drawlist.c + lua_colorlib.c lua_followerlib.c lua_terrainlib.c lua_waypointslib.c diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index b2843728d..381f13a57 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -299,9 +299,6 @@ struct FSurfaceInfo }; typedef struct FSurfaceInfo FSurfaceInfo; -#define GL_DEFAULTMIX 0x00000000 -#define GL_DEFAULTFOG 0x19000000 - // Various settings and states for the rendering backend. enum hwdsetspecialstate { diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index ea9bfb591..e45f36ffb 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -398,8 +398,8 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col RGBA_t poly_color, tint_color, fade_color; poly_color.rgba = 0xFFFFFFFF; - tint_color.rgba = (colormap != NULL) ? (UINT32)colormap->rgba : GL_DEFAULTMIX; - fade_color.rgba = (colormap != NULL) ? (UINT32)colormap->fadergba : GL_DEFAULTFOG; + tint_color.rgba = (colormap != NULL) ? (UINT32)colormap->rgba : 0x00000000; + fade_color.rgba = (colormap != NULL) ? (UINT32)colormap->fadergba : 0xFF000000; // Crappy backup coloring if you can't do shaders if (!HWR_UseShader()) @@ -413,7 +413,7 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col blue = (float)poly_color.s.blue; // 48 is just an arbritrary value that looked relatively okay. - tint_alpha = (float)(sqrt(tint_color.s.alpha) * 48) / 255.0f; + tint_alpha = (float)(sqrt((float)tint_color.s.alpha / 10.2) * 48) / 255.0f; // 8 is roughly the brightness of the "close" color in Software, and 16 the brightness of the "far" color. // 8 is too bright for dark levels, and 16 is too dark for bright levels. @@ -469,7 +469,7 @@ UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap) // Let's see if RGBA_t realcolor, surfcolor; INT32 alpha; - realcolor.rgba = (colormap != NULL) ? colormap->rgba : GL_DEFAULTMIX; + realcolor.rgba = (colormap != NULL) ? colormap->rgba : 0x00000000; if (HWR_UseShader()) { diff --git a/src/hardware/hw_shaders.h b/src/hardware/hw_shaders.h index 4abf8e3ad..e92cc969f 100644 --- a/src/hardware/hw_shaders.h +++ b/src/hardware/hw_shaders.h @@ -101,7 +101,7 @@ #define GLSL_SOFTWARE_TINT_EQUATION \ "if (mix(tint_color.a, 0.0, brightmap_mix) > 0.0) {\n" \ "float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \ - "float strength = sqrt(9.0 * mix(tint_color.a, 0.0, brightmap_mix));\n" \ + "float strength = sqrt(mix(tint_color.a, 0.0, brightmap_mix));\n" \ "final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \ "final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \ "final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \ diff --git a/src/lua_baselib.c b/src/lua_baselib.c index d38d5d41d..63f9c331f 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -232,6 +232,8 @@ static const struct { {META_PATCH, "patch_t"}, {META_COLORMAP, "colormap"}, + {META_EXTRACOLORMAP,"extracolormap_t"}, + {META_LIGHTTABLE, "lighttable_t"}, {META_CAMERA, "camera_t"}, {META_ACTION, "action"}, @@ -1793,7 +1795,6 @@ static int lib_pGetSectorLightLevelAt(lua_State *L) return 1; } -/* Maybe color lib someday.... static int lib_pGetSectorColormapAt(lua_State *L) { boolean has_sector = false; @@ -1817,7 +1818,6 @@ static int lib_pGetSectorColormapAt(lua_State *L) LUA_PushUserdata(L, exc, META_EXTRACOLORMAP); return 1; } -*/ static int lib_pDoSpring(lua_State *L) { @@ -5589,7 +5589,7 @@ static luaL_Reg lib[] = { {"P_FloorzAtPos",lib_pFloorzAtPos}, {"P_CeilingzAtPos",lib_pCeilingzAtPos}, {"P_GetSectorLightLevelAt",lib_pGetSectorLightLevelAt}, - //{"P_GetSectorColormapAt",lib_pGetSectorColormapAt}, + {"P_GetSectorColormapAt",lib_pGetSectorColormapAt}, {"P_DoSpring",lib_pDoSpring}, // p_inter diff --git a/src/lua_colorlib.c b/src/lua_colorlib.c new file mode 100644 index 000000000..b60245f30 --- /dev/null +++ b/src/lua_colorlib.c @@ -0,0 +1,334 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2021-2022 by "Lactozilla". +// Copyright (C) 2014-2023 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file lua_colorlib.c +/// \brief color and colormap libraries for Lua scripting + +#include "doomdef.h" +#include "fastcmp.h" +#include "r_data.h" + +#include "lua_script.h" +#include "lua_libs.h" + +#include "k_color.h" + +#define IS_HEX_CHAR(x) ((x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F')) +#define ARE_HEX_CHARS(str, i) IS_HEX_CHAR(str[i]) && IS_HEX_CHAR(str[i + 1]) + +static UINT32 hex2int(char x) +{ + if (x >= '0' && x <= '9') + return x - '0'; + else if (x >= 'a' && x <= 'f') + return x - 'a' + 10; + else if (x >= 'A' && x <= 'F') + return x - 'A' + 10; + + return 0; +} + +static UINT8 ParseHTMLColor(const char *str, UINT8 *rgba, size_t numc) +{ + const char *hex = str; + + if (hex[0] == '#') + hex++; + else if (!IS_HEX_CHAR(hex[0])) + return 0; + + size_t len = strlen(hex); + + if (len == 3) + { + // Shorthand like #09C + for (unsigned i = 0; i < 3; i++) + { + if (!IS_HEX_CHAR(hex[i])) + return 0; + + UINT32 hx = hex2int(hex[i]); + *rgba++ = (hx * 16) + hx; + } + + return 3; + } + else if (len == 6 || len == 8) + { + if (numc != 4) + len = 6; + + // A triplet like #0099CC + for (unsigned i = 0; i < len; i += 2) + { + if (!ARE_HEX_CHARS(hex, i)) + return false; + + *rgba++ = (hex2int(hex[i]) * 16) + hex2int(hex[i + 1]); + } + + return len; + } + + return 0; +} + +///////////////////////// +// extracolormap userdata +///////////////////////// + +enum extracolormap_e { + extracolormap_red = 0, + extracolormap_green, + extracolormap_blue, + extracolormap_alpha, + extracolormap_color, + extracolormap_fade_red, + extracolormap_fade_green, + extracolormap_fade_blue, + extracolormap_fade_alpha, + extracolormap_fade_color, + extracolormap_fade_start, + extracolormap_fade_end, + extracolormap_colormap +}; + +static const char *const extracolormap_opt[] = { + "red", + "green", + "blue", + "alpha", + "color", + "fade_red", + "fade_green", + "fade_blue", + "fade_alpha", + "fade_color", + "fade_start", + "fade_end", + "colormap", + NULL}; + +static int extracolormap_get(lua_State *L) +{ + extracolormap_t *exc = *((extracolormap_t **)luaL_checkudata(L, 1, META_EXTRACOLORMAP)); + enum extracolormap_e field = luaL_checkoption(L, 2, NULL, extracolormap_opt); + + switch (field) + { + case extracolormap_red: + lua_pushinteger(L, R_GetRgbaR(exc->rgba)); + break; + case extracolormap_green: + lua_pushinteger(L, R_GetRgbaG(exc->rgba)); + break; + case extracolormap_blue: + lua_pushinteger(L, R_GetRgbaB(exc->rgba)); + break; + case extracolormap_alpha: + lua_pushinteger(L, R_GetRgbaA(exc->rgba)); + break; + case extracolormap_color: + lua_pushinteger(L, R_GetRgbaR(exc->rgba)); + lua_pushinteger(L, R_GetRgbaG(exc->rgba)); + lua_pushinteger(L, R_GetRgbaB(exc->rgba)); + lua_pushinteger(L, R_GetRgbaA(exc->rgba)); + return 4; + case extracolormap_fade_red: + lua_pushinteger(L, R_GetRgbaR(exc->fadergba)); + break; + case extracolormap_fade_green: + lua_pushinteger(L, R_GetRgbaG(exc->fadergba)); + break; + case extracolormap_fade_blue: + lua_pushinteger(L, R_GetRgbaB(exc->fadergba)); + break; + case extracolormap_fade_alpha: + lua_pushinteger(L, R_GetRgbaA(exc->fadergba)); + break; + case extracolormap_fade_color: + lua_pushinteger(L, R_GetRgbaR(exc->fadergba)); + lua_pushinteger(L, R_GetRgbaG(exc->fadergba)); + lua_pushinteger(L, R_GetRgbaB(exc->fadergba)); + lua_pushinteger(L, R_GetRgbaA(exc->fadergba)); + return 4; + case extracolormap_fade_start: + lua_pushinteger(L, exc->fadestart); + break; + case extracolormap_fade_end: + lua_pushinteger(L, exc->fadeend); + break; + case extracolormap_colormap: + LUA_PushUserdata(L, exc->colormap, META_LIGHTTABLE); + break; + } + return 1; +} + +static void GetExtraColormapRGBA(lua_State *L, UINT8 *rgba, int arg) +{ + if (lua_type(L, arg) == LUA_TSTRING) + { + const char *str = lua_tostring(L, arg); + UINT8 parsed = ParseHTMLColor(str, rgba, 4); + if (!parsed) + luaL_error(L, "Malformed HTML color '%s'", str); + } + else + { + UINT32 colors = lua_tointeger(L, arg); + if (colors > 0xFFFFFF) + { + rgba[0] = (colors >> 24) & 0xFF; + rgba[1] = (colors >> 16) & 0xFF; + rgba[2] = (colors >> 8) & 0xFF; + rgba[3] = colors & 0xFF; + } + else + { + rgba[0] = (colors >> 16) & 0xFF; + rgba[1] = (colors >> 8) & 0xFF; + rgba[2] = colors & 0xFF; + rgba[3] = 0xFF; + } + } +} + +static int extracolormap_set(lua_State *L) +{ + extracolormap_t *exc = *((extracolormap_t **)luaL_checkudata(L, 1, META_EXTRACOLORMAP)); + enum extracolormap_e field = luaL_checkoption(L, 2, NULL, extracolormap_opt); + + UINT8 r = R_GetRgbaR(exc->rgba); + UINT8 g = R_GetRgbaG(exc->rgba); + UINT8 b = R_GetRgbaB(exc->rgba); + UINT8 a = R_GetRgbaA(exc->rgba); + + UINT8 fr = R_GetRgbaR(exc->fadergba); + UINT8 fg = R_GetRgbaG(exc->fadergba); + UINT8 fb = R_GetRgbaB(exc->fadergba); + UINT8 fa = R_GetRgbaA(exc->fadergba); + + UINT8 rgba[4]; + + INT32 old_rgba = exc->rgba, old_fade_rgba = exc->fadergba; // It's not unsigned? + UINT8 old_fade_start = exc->fadestart, old_fade_end = exc->fadeend; + +#define val luaL_checkinteger(L, 3) + + switch(field) + { + case extracolormap_red: + exc->rgba = R_PutRgbaRGBA(val, g, b, a); + break; + case extracolormap_green: + exc->rgba = R_PutRgbaRGBA(r, val, b, a); + break; + case extracolormap_blue: + exc->rgba = R_PutRgbaRGBA(r, g, val, a); + break; + case extracolormap_alpha: + exc->rgba = R_PutRgbaRGBA(r, g, b, val); + break; + case extracolormap_color: + rgba[0] = r; + rgba[1] = g; + rgba[2] = b; + rgba[3] = a; + GetExtraColormapRGBA(L, rgba, 3); + exc->rgba = R_PutRgbaRGBA(rgba[0], rgba[1], rgba[2], rgba[3]); + break; + case extracolormap_fade_red: + exc->fadergba = R_PutRgbaRGBA(val, fg, fb, fa); + break; + case extracolormap_fade_green: + exc->fadergba = R_PutRgbaRGBA(fr, val, fb, fa); + break; + case extracolormap_fade_blue: + exc->fadergba = R_PutRgbaRGBA(fr, fg, val, fa); + break; + case extracolormap_fade_alpha: + exc->fadergba = R_PutRgbaRGBA(fr, fg, fb, val); + break; + case extracolormap_fade_color: + rgba[0] = fr; + rgba[1] = fg; + rgba[2] = fb; + rgba[3] = fa; + GetExtraColormapRGBA(L, rgba, 3); + exc->fadergba = R_PutRgbaRGBA(rgba[0], rgba[1], rgba[2], rgba[3]); + break; + case extracolormap_fade_start: + if (val > 31) + return luaL_error(L, "fade start %d out of range (0 - 31)", val); + exc->fadestart = val; + break; + case extracolormap_fade_end: + if (val > 31) + return luaL_error(L, "fade end %d out of range (0 - 31)", val); + exc->fadeend = val; + break; + case extracolormap_colormap: + return luaL_error(L, LUA_QL("extracolormap_t") " field " LUA_QS " should not be set directly.", extracolormap_opt[field]); + } + +#undef val + + if (exc->rgba != old_rgba + || exc->fadergba != old_fade_rgba + || exc->fadestart != old_fade_start + || exc->fadeend != old_fade_end) + R_GenerateLightTable(exc, true); + + return 0; +} + +static int lighttable_get(lua_State *L) +{ + void **userdata; + + lighttable_t *table = *((lighttable_t **)luaL_checkudata(L, 1, META_LIGHTTABLE)); + UINT32 row = luaL_checkinteger(L, 2); + if (row < 1 || row > 34) + return luaL_error(L, "lighttable row %d out of range (1 - %d)", row, 34); + + userdata = lua_newuserdata(L, sizeof(void *)); + *userdata = &table[256 * (row - 1)]; + luaL_getmetatable(L, META_COLORMAP); + lua_setmetatable(L, -2); + + return 1; +} + +static int lighttable_len(lua_State *L) +{ + lua_pushinteger(L, NUM_PALETTE_ENTRIES); + return 1; +} + +int LUA_ColorLib(lua_State *L) +{ + luaL_newmetatable(L, META_EXTRACOLORMAP); + lua_pushcfunction(L, extracolormap_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, extracolormap_set); + lua_setfield(L, -2, "__newindex"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_LIGHTTABLE); + lua_pushcfunction(L, lighttable_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lighttable_len); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + return 0; +} diff --git a/src/lua_libs.h b/src/lua_libs.h index aaa9725fe..90fe68bca 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -96,6 +96,8 @@ extern lua_State *gL; #define META_HUDINFO "HUDINFO_T*" #define META_PATCH "PATCH_T*" #define META_COLORMAP "COLORMAP" +#define META_EXTRACOLORMAP "EXTRACOLORMAP_T*" +#define META_LIGHTTABLE "LIGHTTABLE_T*" #define META_CAMERA "CAMERA_T*" #define META_ACTION "actionf_p1*" @@ -152,6 +154,7 @@ int LUA_TagLib(lua_State *L); int LUA_PolyObjLib(lua_State *L); int LUA_BlockmapLib(lua_State *L); int LUA_HudLib(lua_State *L); +int LUA_ColorLib(lua_State *L); int LUA_FollowerLib(lua_State *L); int LUA_BotVarsLib(lua_State *L); int LUA_TerrainLib(lua_State *L); diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 29a317876..532284e93 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -49,6 +49,7 @@ enum sector_e { sector_ffloors, sector_fslope, sector_cslope, + sector_colormap, sector_flags, sector_specialflags, sector_damagetype, @@ -85,6 +86,7 @@ static const char *const sector_opt[] = { "ffloors", "f_slope", "c_slope", + "colormap", "flags", "specialflags", "damagetype", @@ -750,6 +752,9 @@ static int sector_get(lua_State *L) case sector_cslope: // c_slope LUA_PushUserdata(L, sector->c_slope, META_SLOPE); return 1; + case sector_colormap: // extra_colormap + LUA_PushUserdata(L, sector->extra_colormap, META_EXTRACOLORMAP); + return 1; case sector_flags: // flags lua_pushinteger(L, sector->flags); return 1; diff --git a/src/lua_script.c b/src/lua_script.c index 0144e09d8..a23487eda 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -61,6 +61,7 @@ static lua_CFunction liblist[] = { LUA_PolyObjLib, // polyobj_t LUA_BlockmapLib, // blockmap stuff LUA_HudLib, // HUD stuff + LUA_ColorLib, // general color functions LUA_FollowerLib, // follower_t, followers[] LUA_BotVarsLib, // botvars_t LUA_TerrainLib, // t_splash_t, t_footstep_t, t_overlay_t, terrain_t diff --git a/src/m_misc.cpp b/src/m_misc.cpp index cb1789e19..50ce1ffa4 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -2556,3 +2556,37 @@ UINT32 FNV1a_QuickCaseHash(const char *message, size_t size) return hash; } + +// Returns true if the string is empty. +boolean M_IsStringEmpty(const char *s) +{ + const char *ch = s; + + if (s == NULL || s[0] == '\0') + return true; + + for (;;ch++) + { + if (!(*ch)) + break; + if (!isspace((*ch))) + return false; + } + + return true; +} + +// Rounds off floating numbers and checks for 0 - 255 bounds +int M_RoundUp(double number) +{ + if (number > 255.0l) + return 255; + if (number < 0.0l) + return 0; + + if ((int)number <= (int)(number - 0.5f)) + return (int)number + 1; + + return (int)number; +} + diff --git a/src/m_misc.h b/src/m_misc.h index 10c1eeed3..9e5dfea63 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -126,6 +126,10 @@ FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size); // Hashes some message using FNV-1a UINT32 FNV1a_QuickCaseHash(const char *message, size_t size); +boolean M_IsStringEmpty(const char *s); + +int M_RoundUp(double number); + #include "w_wad.h" extern char configfile[MAX_WADPATH]; diff --git a/src/r_data.c b/src/r_data.c index b4ae9eeae..d17ba2901 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -387,7 +387,7 @@ extracolormap_t *R_CreateDefaultColormap(boolean lighttable) exc->fadeend = 31; exc->flags = 0; exc->rgba = 0; - exc->fadergba = 0x19000000; + exc->fadergba = 0xFF000000; exc->colormap = lighttable ? R_CreateLightTable(exc) : NULL; #ifdef EXTRACOLORMAPLUMPS exc->lump = LUMPERROR; @@ -502,7 +502,7 @@ boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, && !flags) ) && (!checkrgba ? true : rgba == 0) - && (!checkfadergba ? true : fadergba == 0x19000000) + && (!checkfadergba ? true : (unsigned)fadergba == 0xFF000000) #ifdef EXTRACOLORMAPLUMPS && lump == LUMPERROR && extra_colormap->lumpname[0] == 0 @@ -603,7 +603,7 @@ extracolormap_t *R_ColormapForName(char *name) if (lump == LUMPERROR) I_Error("R_ColormapForName: Cannot find colormap lump %.8s\n", name); - exc = R_GetColormapFromListByValues(0, 0x19000000, 0, 31, 0, lump); + exc = R_GetColormapFromListByValues(0, 0xFF000000, 0, 31, 0, lump); if (exc) return exc; @@ -623,7 +623,7 @@ extracolormap_t *R_ColormapForName(char *name) exc->fadeend = 31; exc->flags = 0; exc->rgba = 0; - exc->fadergba = 0x19000000; + exc->fadergba = 0xFF000000; R_AddColormapToList(exc); @@ -642,27 +642,42 @@ extracolormap_t *R_ColormapForName(char *name) static double brightChange[256], map[256][3]; static double deltas[256][3]; // for old fade colormaps -static int RoundUp(double number); +static colorlookup_t lighttable_lut; + +static UINT8 LightTableNearest(UINT8 r, UINT8 g, UINT8 b) +{ + return NearestColor(r, g, b); +} + +static UINT8 LightTableNearest_LUT(UINT8 r, UINT8 g, UINT8 b) +{ + return GetColorLUT(&lighttable_lut, r, g, b); +} lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) { - double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb, cdestbright; + extra_colormap->colormap = Z_MallocAlign((256 * 34) + 10, PU_LEVEL, NULL, 8); + R_GenerateLightTable(extra_colormap, false); + return extra_colormap->colormap; +} + +void R_GenerateLightTable(extracolormap_t *extra_colormap, boolean uselookup) +{ + double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; double maskamt = 0, othermask = 0; - double fmaskamt = 0, fothermask = 0; UINT8 cr = R_GetRgbaR(extra_colormap->rgba), - cg = R_GetRgbaG(extra_colormap->rgba), - cb = R_GetRgbaB(extra_colormap->rgba), - ca = R_GetRgbaA(extra_colormap->rgba), - cfr = R_GetRgbaR(extra_colormap->fadergba), - cfg = R_GetRgbaG(extra_colormap->fadergba), - cfb = R_GetRgbaB(extra_colormap->fadergba), - cfa = R_GetRgbaA(extra_colormap->fadergba); + cg = R_GetRgbaG(extra_colormap->rgba), + cb = R_GetRgbaB(extra_colormap->rgba), + ca = R_GetRgbaA(extra_colormap->rgba), + cfr = R_GetRgbaR(extra_colormap->fadergba), + cfg = R_GetRgbaG(extra_colormap->fadergba), + cfb = R_GetRgbaB(extra_colormap->fadergba); + // cfa = R_GetRgbaA(extra_colormap->fadergba); // unused in software UINT8 fadestart = extra_colormap->fadestart, - fadedist = extra_colormap->fadeend - extra_colormap->fadestart; + fadedist = extra_colormap->fadeend - extra_colormap->fadestart; - lighttable_t *lighttable = NULL; size_t i; ///////////////////// @@ -672,7 +687,7 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) cmaskg = cg; cmaskb = cb; - maskamt = (double)(ca/24.0l); + maskamt = (double)(ca/255.0l); othermask = 1 - maskamt; maskamt /= 0xff; @@ -686,27 +701,39 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) cdestr = cfr; cdestg = cfg; cdestb = cfb; - cdestbright = sqrt((cfr*cfr) + (cfg*cfg) + (cfb*cfb)); - fmaskamt = (double)(cfa/24.0l); - fothermask = 1 - fmaskamt; - //fmaskamt /= 0xff; + // fade alpha unused in software + // maskamt = (double)(cfa/255.0l); + // othermask = 1 - maskamt; + // maskamt /= 0xff; - (void)fothermask; // unused, but don't feel like commenting it out + // cdestr *= maskamt; + // cdestg *= maskamt; + // cdestb *= maskamt; ///////////////////// // This code creates the colormap array used by software renderer ///////////////////// { - double r, g, b, cbrightness, cbest, cdist; + double r, g, b, cbrightness; int p; - lighttable_t *colormap_p; + char *colormap_p; + + UINT8 (*NearestColorFunc)(UINT8, UINT8, UINT8); + + if (uselookup) + { + InitColorLUT(&lighttable_lut, pMasterPalette, false); + NearestColorFunc = LightTableNearest_LUT; + } + else + NearestColorFunc = LightTableNearest; // Initialise the map and delta arrays // map[i] stores an RGB color (as double) for index i, // which is then converted to SRB2's palette later - // brightChange[i] is the value added/subtracted every step for the fade; - // map[i]'s values are in/decremented by it after each use + // deltas[i] stores a corresponding fade delta between the RGB color and the final fade color; + // map[i]'s values are decremented by after each use for (i = 0; i < 256; i++) { r = pMasterPalette[i].s.red; @@ -717,122 +744,55 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) map[i][0] = (cbrightness * cmaskr) + (r * othermask); if (map[i][0] > 255.0l) map[i][0] = 255.0l; + deltas[i][0] = (map[i][0] - cdestr) / (double)fadedist; map[i][1] = (cbrightness * cmaskg) + (g * othermask); if (map[i][1] > 255.0l) map[i][1] = 255.0l; + deltas[i][1] = (map[i][1] - cdestg) / (double)fadedist; map[i][2] = (cbrightness * cmaskb) + (b * othermask); if (map[i][2] > 255.0l) map[i][2] = 255.0l; - - if (extra_colormap->flags & CMF_NEWFADE) - { - // Get the "best" color. - // Our brightest color's value, if we're fading to a darker color, - // or our (inverted) darkest color's value, if we're fading to a brighter color. - if (cbrightness < cdestbright) - { - cbest = 255.0l - min(r, min(g, b)); - cdist = 255.0l - max(cdestr, max(cdestg, cdestb)); - } - else - { - cbest = max(r, max(g, b)); - cdist = min(cdestr, min(cdestg, cdestb)); - } - - // Add/subtract this value during fading. - brightChange[i] = (fabs(cbest - cdist) / (double)fadedist) * fmaskamt; - } - else - { - deltas[i][0] = (map[i][0] - cdestr) / (double)fadedist; - deltas[i][1] = (map[i][1] - cdestg) / (double)fadedist; - deltas[i][2] = (map[i][2] - cdestb) / (double)fadedist; - } + deltas[i][2] = (map[i][2] - cdestb) / (double)fadedist; } // Now allocate memory for the actual colormap array itself! // aligned on 8 bit for asm code - colormap_p = Z_MallocAlign((COLORMAP_SIZE * (encoremap ? 2 : 1)) + 10, PU_LEVEL, NULL, 8); - lighttable = (UINT8 *)colormap_p; + colormap_p = (char *)extra_colormap->colormap; // Calculate the palette index for each palette index, for each light level // (as well as the two unused colormap lines we inherited from Doom) - for (p = 0; p < LIGHTLEVELS; p++) + for (p = 0; p < 34; p++) { for (i = 0; i < 256; i++) { - *colormap_p = NearestColor((UINT8)RoundUp(map[i][0]), - (UINT8)RoundUp(map[i][1]), - (UINT8)RoundUp(map[i][2])); + *colormap_p = NearestColorFunc((UINT8)M_RoundUp(map[i][0]), + (UINT8)M_RoundUp(map[i][1]), + (UINT8)M_RoundUp(map[i][2])); colormap_p++; if ((UINT32)p < fadestart) continue; - - if (extra_colormap->flags & CMF_NEWFADE) - { - // Add/subtract towards the destination color. - if (fabs(map[i][0] - cdestr) <= brightChange[i]) - map[i][0] = cdestr; - else if (map[i][0] > cdestr) - map[i][0] -= brightChange[i]; - else - map[i][0] += brightChange[i]; - - if (fabs(map[i][1] - cdestg) <= brightChange[i]) - map[i][1] = cdestg; - else if (map[i][1] > cdestg) - map[i][1] -= brightChange[i]; - else - map[i][1] += brightChange[i]; - - if (fabs(map[i][2] - cdestb) <= brightChange[i]) - map[i][2] = cdestb; - else if (map[i][2] > cdestb) - map[i][2] -= brightChange[i]; - else - map[i][2] += brightChange[i]; - } + #define ABS2(x) ((x) < 0 ? -(x) : (x)) + if (ABS2(map[i][0] - cdestr) > ABS2(deltas[i][0])) + map[i][0] -= deltas[i][0]; else - { - if (fabs(map[i][0] - cdestr) > fabs(deltas[i][0])) - map[i][0] -= deltas[i][0]; - else - map[i][0] = cdestr; + map[i][0] = cdestr; - if (fabs(map[i][1] - cdestg) > fabs(deltas[i][1])) - map[i][1] -= deltas[i][1]; - else - map[i][1] = cdestg; + if (ABS2(map[i][1] - cdestg) > ABS2(deltas[i][1])) + map[i][1] -= deltas[i][1]; + else + map[i][1] = cdestg; - if (fabs(map[i][2] - cdestb) > fabs(deltas[i][1])) // typo alert! - map[i][2] -= deltas[i][2]; - else - map[i][2] = cdestb; - } - } - } - - if (encoremap) - { - lighttable_t *colormap_p2 = lighttable; - - for (p = 0; p < LIGHTLEVELS; p++) - { - for (i = 0; i < 256; i++) - { - *colormap_p = colormap_p2[encoremap[i]]; - colormap_p++; - } - colormap_p2 += 256; + if (ABS2(map[i][2] - cdestb) > ABS2(deltas[i][1])) + map[i][2] -= deltas[i][2]; + else + map[i][2] = cdestb; + #undef ABS2 } } } - - return lighttable; } extracolormap_t *R_CreateColormapFromLinedef(char *p1, char *p2, char *p3) @@ -841,7 +801,7 @@ extracolormap_t *R_CreateColormapFromLinedef(char *p1, char *p2, char *p3) UINT8 cr = 0, cg = 0, cb = 0, ca = 0, cfr = 0, cfg = 0, cfb = 0, cfa = 25; UINT32 fadestart = 0, fadeend = 31; UINT8 flags = 0; - INT32 rgba = 0, fadergba = 0x19000000; + INT32 rgba = 0, fadergba = 0xFF000000; #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) #define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0) @@ -849,13 +809,13 @@ extracolormap_t *R_CreateColormapFromLinedef(char *p1, char *p2, char *p3) // Get base colormap value // First alpha-only, then full value if (p1[0] >= 'a' && p1[0] <= 'z' && !p1[1]) - ca = (p1[0] - 'a'); + ca = ((p1[0] - 'a') * 102) / 10; else if (p1[0] == '#' && p1[1] >= 'a' && p1[1] <= 'z' && !p1[2]) - ca = (p1[1] - 'a'); + ca = ((p1[1] - 'a') * 102) / 10; else if (p1[0] >= 'A' && p1[0] <= 'Z' && !p1[1]) - ca = (p1[0] - 'A'); + ca = ((p1[0] - 'A') * 102) / 10; else if (p1[0] == '#' && p1[1] >= 'A' && p1[1] <= 'Z' && !p1[2]) - ca = (p1[1] - 'A'); + ca = ((p1[1] - 'A') * 102) / 10; else if (p1[0] == '#') { // For each subsequent value, the value before it must exist @@ -871,20 +831,20 @@ extracolormap_t *R_CreateColormapFromLinedef(char *p1, char *p2, char *p3) cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6])); if (p1[7] >= 'a' && p1[7] <= 'z') - ca = (p1[7] - 'a'); + ca = ((p1[7] - 'a') * 102) / 10; else if (p1[7] >= 'A' && p1[7] <= 'Z') - ca = (p1[7] - 'A'); + ca = ((p1[7] - 'A') * 102) / 10; else - ca = 25; + ca = 255; } else - ca = 25; + ca = 255; } else - ca = 25; + ca = 255; } else - ca = 25; + ca = 255; } #define NUMFROMCHAR(c) (c >= '0' && c <= '9' ? c - '0' : 0) @@ -914,13 +874,13 @@ extracolormap_t *R_CreateColormapFromLinedef(char *p1, char *p2, char *p3) // Get fade (dark) colormap value // First alpha-only, then full value if (p3[0] >= 'a' && p3[0] <= 'z' && !p3[1]) - cfa = (p3[0] - 'a'); + cfa = ((p3[0] - 'a') * 102) / 10; else if (p3[0] == '#' && p3[1] >= 'a' && p3[1] <= 'z' && !p3[2]) - cfa = (p3[1] - 'a'); + cfa = ((p3[1] - 'a') * 102) / 10; else if (p3[0] >= 'A' && p3[0] <= 'Z' && !p3[1]) - cfa = (p3[0] - 'A'); + cfa = ((p3[0] - 'A') * 102) / 10; else if (p3[0] == '#' && p3[1] >= 'A' && p3[1] <= 'Z' && !p3[2]) - cfa = (p3[1] - 'A'); + cfa = ((p3[1] - 'A') * 102) / 10; else if (p3[0] == '#') { // For each subsequent value, the value before it must exist @@ -936,20 +896,20 @@ extracolormap_t *R_CreateColormapFromLinedef(char *p1, char *p2, char *p3) cfb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); if (p3[7] >= 'a' && p3[7] <= 'z') - cfa = (p3[7] - 'a'); + cfa = ((p3[7] - 'a') * 102) / 10; else if (p3[7] >= 'A' && p3[7] <= 'Z') - cfa = (p3[7] - 'A'); + cfa = ((p3[7] - 'A') * 102) / 10; else - cfa = 25; + cfa = 255; } else - cfa = 25; + cfa = 255; } else - cfa = 25; + cfa = 255; } else - cfa = 25; + cfa = 255; } #undef ALPHA2INT #undef HEX2INT @@ -1166,20 +1126,6 @@ UINT8 NearestPaletteColor(UINT8 r, UINT8 g, UINT8 b, RGBA_t *palette) return (UINT8)bestcolor; } -// Rounds off floating numbers and checks for 0 - 255 bounds -static int RoundUp(double number) -{ - if (number > 255.0l) - return 255; - if (number < 0.0l) - return 0; - - if ((int)number <= (int)(number - 0.5f)) - return (int)number + 1; - - return (int)number; -} - #ifdef EXTRACOLORMAPLUMPS const char *R_NameForColormap(extracolormap_t *extra_colormap) { diff --git a/src/r_data.h b/src/r_data.h index 0751ca1ee..03c1dc9a6 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -93,6 +93,7 @@ typedef enum TMCF_OVERRIDE = 1<<13, } textmapcolormapflags_t; +void R_GenerateLightTable(extracolormap_t *extra_colormap, boolean uselookup); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); extracolormap_t * R_CreateColormapFromLinedef(char *p1, char *p2, char *p3); extracolormap_t* R_CreateColormap(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags);