Lua colorlib: extracolormap support

This commit is contained in:
Lactozilla 2026-03-08 13:15:13 -04:00 committed by NepDisk
parent 1ddd84cf13
commit baf749e5c3
13 changed files with 486 additions and 160 deletions

View file

@ -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

View file

@ -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
{

View file

@ -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())
{

View file

@ -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" \

View file

@ -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

334
src/lua_colorlib.c Normal file
View file

@ -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;
}

View file

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

View file

@ -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;

View file

@ -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

View file

@ -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;
}

View file

@ -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];

View file

@ -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)
{

View file

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