- hooked up the colorization feature.

It can now be used from UDMF and ZScript.
To avoid clutter it doesn't allow setting the values individually but requires definition of a data record in TEXTURES.

colorization
{
    DesaturationFactor <float>
    Invert
    AddColor <color>
    ModulateColor <color>
    BlendColor <color>, <mode> [, <alpha>]
}

Mode for BlendColor can be Alpha (normal translucent blending), as well as 3 special values taken from Build engine games: Screen, Overlay and HardLight.
This commit is contained in:
Christoph Oelckers 2019-12-22 16:08:34 +01:00
parent f9d2dc51d0
commit 9b9fd35107
10 changed files with 265 additions and 79 deletions

View File

@ -210,6 +210,9 @@ Note: All <bool> fields default to false unless mentioned otherwise.
coloradd_top = <int>; // Additive material color to apply to top section of sidedef. Default is black (0x000000)
coloradd_mid = <int>; // Additive material color to apply to middle section of sidedef. Default is black (0x000000)
coloradd_bottom = <int>; // Additive material color to apply to bottom section of sidedef. Default is black (0x000000)
colorization_top = <int>; // Sets a colorization record for the upper texture. Colorization records must be defined in TEXTURES.
colorization_mid = <int>; // Sets a colorization record for the middle texture. Colorization records must be defined in TEXTURES.
colorization_bottom = <int>; // Sets a colorization record for the lower texture. Colorization records must be defined in TEXTURES.
}
sector
@ -288,6 +291,9 @@ Note: All <bool> fields default to false unless mentioned otherwise.
coloradd_sprites = <int>; // Additive material color applied to sprites within the sector. Default is black (0x000000)
coloradd_walls = <int>; // Additive material color applied to walls within the sector. Default is black (0x000000)
colorization_floor = <int>; // Sets a colorization record for the floor texture. Colorization records must be defined in TEXTURES.
colorization_ceiling = <int>; // Sets a colorization record for the ceiling texture. Colorization records must be defined in TEXTURES.
portal_ceil_blocksound = <bool>; // ceiling portal blocks sound.
portal_ceil_disabled = <bool>; // ceiling portal disabled.
portal_ceil_nopass = <bool>; // ceiling portal blocks movement if true.
@ -495,6 +501,9 @@ arg0str in dynamic lights.
Added automapstyle and revealed linedef properties.
Replaced tabs with spaces.
1.31 22.12.2019
Coloriation options added
===============================================================================
EOF
===============================================================================

View File

@ -34,6 +34,7 @@
#include "templates.h"
#include "m_bbox.h"
#include "dobjgc.h"
#include "r_data/r_translate.h"
// Some more or less basic data types
// we depend on.
@ -601,76 +602,6 @@ FSerializer &Serialize(FSerializer &arc, const char *key, secspecial_t &spec, se
enum class EMoveResult { ok, crushed, pastdest };
struct TextureManipulation
{
enum
{
BlendNone = 0,
BlendAlpha = 1,
BlendScreen = 2,
BlendOverlay = 3,
BlendHardLight = 4,
BlendMask = 7,
InvertBit = 8,
ActiveBit = 16, // Must be set for the shader to do something
};
PalEntry AddColor; // Alpha contains the blend flags
PalEntry ModulateColor; // Alpha may contain a multiplier to get higher values than 1.0 without promoting this to 4 full floats.
PalEntry BlendColor;
float DesaturationFactor;
bool CheckIfEnabled() // check if this manipulation is doing something. NoOps do not need to be preserved, unless they override older setttings.
{
if (AddColor != 0 || // this includes a check for the blend mode without which BlendColor is not active
ModulateColor != 0x01ffffff || // 1 in alpha must be the default for a no-op.
DesaturationFactor != 0)
{
AddColor.a |= ActiveBit; // mark as active for the shader's benefit.
return true;
}
return false;
}
void SetTextureModulateColor(int slot, PalEntry rgb)
{
rgb.a = ModulateColor.a;
ModulateColor = rgb;
}
void SetTextureModulateScaleFactor(int slot, int fac)
{
ModulateColor.a = (uint8_t)fac;
}
void SetTextureAdditiveColor(int slot, PalEntry rgb)
{
rgb.a = AddColor.a;
AddColor = rgb;
}
void SetTextureBlendColor(int slot, PalEntry rgb)
{
BlendColor = rgb;
}
void SetTextureDesaturationFactor(int slot, double fac)
{
DesaturationFactor = (float)fac;
}
void SetTextureBlendMode(int slot, int mode)
{
AddColor.a = (AddColor.a & ~TextureManipulation::BlendMask) | (mode & TextureManipulation::BlendMask);
}
void SetTextureInvert(bool on)
{
AddColor.a |= TextureManipulation::InvertBit;
AddColor.a &= ~TextureManipulation::InvertBit;
}
};
struct sector_t
{
@ -1129,9 +1060,10 @@ public:
// TextureFX parameters
void SetTextureFx(int slot, const TextureManipulation &tm)
void SetTextureFx(int slot, const TextureManipulation *tm)
{
planes[slot].TextureFx = tm; // this is for getting the data from a texture.
if (tm) planes[slot].TextureFx = *tm; // this is for getting the data from a texture.
else planes[slot].TextureFx = {};
}
@ -1429,10 +1361,17 @@ struct side_t
textures[which].AdditiveColor = rgb;
}
void SetTextureFx(int slot, const TextureManipulation& tm)
void SetTextureFx(int slot, const TextureManipulation* tm)
{
textures[slot].TextureFx = tm; // this is for getting the data from a texture.
if (tm.AddColor.a) Flags |= WALLF_EXTCOLOR;
if (tm)
{
textures[slot].TextureFx = *tm; // this is for getting the data from a texture.
if (tm->AddColor.a) Flags |= WALLF_EXTCOLOR;
}
else
{
textures[slot].TextureFx = {};
}
}
PalEntry GetAdditiveColor(int which, sector_t *frontsector) const

View File

@ -141,6 +141,7 @@ void FTextureManager::DeleteAll()
}
mAnimatedDoors.Clear();
BuildTileData.Clear();
tmanips.Clear();
}
//==========================================================================
@ -688,6 +689,69 @@ void FTextureManager::AddHiresTextures (int wadnum)
//
//==========================================================================
void FTextureManager::ParseColorization(FScanner& sc)
{
TextureManipulation tm = {};
sc.MustGetString();
FName cname = sc.String;
sc.MustGetToken('{');
while (!sc.CheckToken('}'))
{
if (sc.Compare("desaturation"))
{
sc.MustGetFloat();
tm.DesaturationFactor = sc.Float;
}
else if (sc.Compare("AddColor"))
{
sc.MustGetString();
tm.AddColor = (tm.AddColor & 0xff000000) | (V_GetColor(NULL, sc) & 0xffffff);
}
else if (sc.Compare("ModulateColor"))
{
sc.MustGetString();
tm.ModulateColor = V_GetColor(NULL, sc) & 0xffffff;
if (sc.CheckToken(','))
{
sc.MustGetNumber();
tm.ModulateColor.a = sc.Number;
}
}
else if (sc.Compare("BlendColor"))
{
sc.MustGetString();
tm.BlendColor = V_GetColor(NULL, sc) & 0xffffff;
sc.MustGetToken(',');
sc.MustGetString();
static const char* opts[] = {"none", "alpha", "screen", "overlay", "hardlight", nullptr};
tm.AddColor.a = (tm.AddColor.a & ~TextureManipulation::BlendMask) | sc.MustMatchString(opts);
if (sc.CheckToken(','))
{
sc.MustGetFloat();
tm.BlendColor.a = clamp(sc.Float, 0., 1.) * 255;
}
}
else if (sc.Compare("invert"))
{
tm.AddColor.a |= TextureManipulation::InvertBit;
}
}
if (tm.CheckIfEnabled())
{
tmanips.Insert(cname, tm);
}
else
{
tmanips.Remove(cname);
}
}
//==========================================================================
//
// Loads the HIRESTEX lumps
//
//==========================================================================
void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname, FMultipatchTextureBuilder &build)
{
int remapLump, lastLump;
@ -824,19 +888,23 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build
}
else if (sc.Compare("sprite"))
{
build.ParseTexture(sc, ETextureType::Sprite);
build.ParseTexture(sc, ETextureType::Sprite);
}
else if (sc.Compare("walltexture"))
{
build.ParseTexture(sc, ETextureType::Wall);
build.ParseTexture(sc, ETextureType::Wall);
}
else if (sc.Compare("flat"))
{
build.ParseTexture(sc, ETextureType::Flat);
build.ParseTexture(sc, ETextureType::Flat);
}
else if (sc.Compare("graphic"))
{
build.ParseTexture(sc, ETextureType::MiscPatch);
build.ParseTexture(sc, ETextureType::MiscPatch);
}
else if (sc.Compare("colorization"))
{
ParseColorization(sc);
}
else if (sc.Compare("#include"))
{

View File

@ -601,6 +601,7 @@ public:
void AddPatches (int lumpnum);
void AddHiresTextures (int wadnum);
void LoadTextureDefs(int wadnum, const char *lumpname, FMultipatchTextureBuilder &build);
void ParseColorization(FScanner& sc);
void ParseTextureDef(int remapLump, FMultipatchTextureBuilder &build);
void SortTexturesByType(int start, int end);
bool AreTexturesCompatible (FTextureID picnum1, FTextureID picnum2);
@ -626,6 +627,12 @@ public:
FSwitchDef *FindSwitch (FTextureID texture);
FDoorAnimation *FindAnimatedDoor (FTextureID picnum);
TextureManipulation* GetTextureManipulation(FName name)
{
return tmanips.CheckKey(name);
}
private:
// texture counting
@ -683,6 +690,7 @@ private:
TArray<FSwitchDef *> mSwitchDefs;
TArray<FDoorAnimation> mAnimatedDoors;
TMap<FName, TextureManipulation> tmanips;
public:
TArray<FAnimDef *> mAnimations;

View File

@ -1295,6 +1295,18 @@ public:
Flag(sd->Flags, WALLF_NOAUTODECALS, key);
continue;
case NAME_colorization_top:
sd->SetTextureFx(side_t::top, TexMan.GetTextureManipulation(CheckString(key)));
break;
case NAME_colorization_mid:
sd->SetTextureFx(side_t::mid, TexMan.GetTextureManipulation(CheckString(key)));
break;
case NAME_colorization_bottom:
sd->SetTextureFx(side_t::bottom, TexMan.GetTextureManipulation(CheckString(key)));
break;
case NAME_nogradient_top:
Flag(sd->textures[side_t::top].flags, side_t::part::NoGradient, key);
break;
@ -1650,6 +1662,14 @@ public:
sec->AdditiveColors[sector_t::sprites] = CheckInt(key) | 0xff000000;
break;
case NAME_colorization_floor:
sec->SetTextureFx(sector_t::floor, TexMan.GetTextureManipulation(CheckString(key)));
break;
case NAME_colorization_ceiling:
sec->SetTextureFx(sector_t::ceiling, TexMan.GetTextureManipulation(CheckString(key)));
break;
case NAME_Desaturation:
desaturation = int(255*CheckFloat(key) + FLT_EPSILON); // FLT_EPSILON to avoid rounding errors with numbers slightly below a full integer.
continue;

View File

@ -89,6 +89,31 @@ FSerializer &Serialize(FSerializer &arc, const char *key, line_t &line, line_t *
}
//==========================================================================
//
//
//
//==========================================================================
FSerializer& Serialize(FSerializer& arc, const char* key, TextureManipulation& part, TextureManipulation *def)
{
if (arc.canSkip() && def != nullptr && !memcmp(&part, def, sizeof(part)))
{
return arc;
}
if (arc.BeginObject(key))
{
arc("addcolor", part.AddColor, def->AddColor)
("yoffset", part.ModulateColor, def->ModulateColor)
("xscale", part.BlendColor, def->BlendColor)
("yscale", part.DesaturationFactor, def->DesaturationFactor)
.EndObject();
}
return arc;
}
//==========================================================================
//
//
@ -114,6 +139,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, side_t::part &part, si
("color1", part.SpecialColors[0], def->SpecialColors[0])
("color2", part.SpecialColors[1], def->SpecialColors[1])
("addcolor", part.AdditiveColor, def->AdditiveColor)
("texturefx", part.TextureFx, def->TextureFx)
.EndObject();
}
return arc;
@ -212,6 +238,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, sector_t::splane &p, s
("alpha", p.alpha, def->alpha)
("glowcolor", p.GlowColor, def->GlowColor)
("glowheight", p.GlowHeight, def->GlowHeight)
("texturefx", p.TextureFx, def->TextureFx)
.EndObject();
}
return arc;

View File

@ -147,6 +147,77 @@ int CreateBloodTranslation(PalEntry color);
int R_FindCustomTranslation(FName name);
void R_ParseTrnslate();
struct TextureManipulation
{
enum
{
BlendNone = 0,
BlendAlpha = 1,
BlendScreen = 2,
BlendOverlay = 3,
BlendHardLight = 4,
BlendMask = 7,
InvertBit = 8,
ActiveBit = 16, // Must be set for the shader to do something
};
PalEntry AddColor; // Alpha contains the blend flags
PalEntry ModulateColor; // Alpha may contain a multiplier to get higher values than 1.0 without promoting this to 4 full floats.
PalEntry BlendColor;
float DesaturationFactor;
bool CheckIfEnabled() // check if this manipulation is doing something. NoOps do not need to be preserved, unless they override older setttings.
{
if (AddColor != 0 || // this includes a check for the blend mode without which BlendColor is not active
ModulateColor != 0x01ffffff || // 1 in alpha must be the default for a no-op.
DesaturationFactor != 0)
{
AddColor.a |= ActiveBit; // mark as active for the shader's benefit.
return true;
}
return false;
}
void SetTextureModulateColor(int slot, PalEntry rgb)
{
rgb.a = ModulateColor.a;
ModulateColor = rgb;
}
void SetTextureModulateScaleFactor(int slot, int fac)
{
ModulateColor.a = (uint8_t)fac;
}
void SetTextureAdditiveColor(int slot, PalEntry rgb)
{
rgb.a = AddColor.a;
AddColor = rgb;
}
void SetTextureBlendColor(int slot, PalEntry rgb)
{
BlendColor = rgb;
}
void SetTextureDesaturationFactor(int slot, double fac)
{
DesaturationFactor = (float)fac;
}
void SetTextureBlendMode(int slot, int mode)
{
AddColor.a = (AddColor.a & ~TextureManipulation::BlendMask) | (mode & TextureManipulation::BlendMask);
}
void SetTextureInvert(bool on)
{
AddColor.a |= TextureManipulation::InvertBit;
AddColor.a &= ~TextureManipulation::InvertBit;
}
};
#endif // __R_TRANSLATE_H

View File

@ -652,6 +652,24 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetAdditiveColor, SetAdditiveColor)
return 0;
}
static void SetColorization(sector_t* self, int pos, int cname)
{
if (pos >= 0 && pos < 2)
{
self->SetTextureFx(pos, TexMan.GetTextureManipulation(ENamedName(cname)));
}
}
DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetColorization, SetColorization)
{
PARAM_SELF_STRUCT_PROLOGUE(sector_t);
PARAM_INT(pos);
PARAM_INT(color);
SetColorization(self, pos, color);
return 0;
}
static void SetFogDensity(sector_t *self, int dens)
{
self->Colormap.FogDensity = dens;
@ -1749,6 +1767,25 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset)
return 0;
}
static void SetWallColorization(side_t* self, int pos, int cname)
{
if (pos >= 0 && pos < 2)
{
self->SetTextureFx(pos, TexMan.GetTextureManipulation(ENamedName(cname)));
}
}
DEFINE_ACTION_FUNCTION_NATIVE(_Side, SetColorization, SetWallColorization)
{
PARAM_SELF_STRUCT_PROLOGUE(side_t);
PARAM_INT(pos);
PARAM_INT(color);
SetWallColorization(self, pos, color);
return 0;
}
static int SideIndex(side_t *self)
{
return self->Index();

View File

@ -671,6 +671,11 @@ xx(useowncoloradd_mid)
xx(coloradd_mid)
xx(useowncoloradd_bottom)
xx(coloradd_bottom)
xx(colorization_top)
xx(colorization_mid)
xx(colorization_bottom)
xx(colorization_floor)
xx(colorization_ceiling)
xx(Renderstyle)

View File

@ -87,6 +87,7 @@ struct Side native play
native Color GetAdditiveColor(int tier);
native void SetAdditiveColor(int tier, Color color);
native void EnableAdditiveColor(int tier, bool enable);
native void SetColorization(int tier, Name cname);
//native DInterpolation *SetInterpolation(int position);
//native void StopInterpolation(int position);
@ -469,6 +470,7 @@ struct Sector native play
native void SetGlowColor(int pos, color color);
native void SetSpecialColor(int pos, color color);
native void SetAdditiveColor(int pos, Color color);
native void SetColorization(int tier, Name cname);
native TextureID GetTexture(int pos);
native void SetTexture(int pos, TextureID tex, bool floorclip = true);