From 9b9fd35107493ea38fc77a6d1c2478e322a5681d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 22 Dec 2019 16:08:34 +0100 Subject: [PATCH] - 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 Invert AddColor ModulateColor BlendColor , [, ] } Mode for BlendColor can be Alpha (normal translucent blending), as well as 3 special values taken from Build engine games: Screen, Overlay and HardLight. --- specs/udmf_zdoom.txt | 9 +++ src/gamedata/r_defs.h | 89 ++++-------------------- src/gamedata/textures/texturemanager.cpp | 76 ++++++++++++++++++-- src/gamedata/textures/textures.h | 8 +++ src/maploader/udmf.cpp | 20 ++++++ src/p_saveg.cpp | 27 +++++++ src/r_data/r_translate.h | 71 +++++++++++++++++++ src/scripting/vmthunks.cpp | 37 ++++++++++ src/utility/namedef.h | 5 ++ wadsrc/static/zscript/mapdata.zs | 2 + 10 files changed, 265 insertions(+), 79 deletions(-) diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 2f30e4df9f..2559ebe786 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -210,6 +210,9 @@ Note: All fields default to false unless mentioned otherwise. coloradd_top = ; // Additive material color to apply to top section of sidedef. Default is black (0x000000) coloradd_mid = ; // Additive material color to apply to middle section of sidedef. Default is black (0x000000) coloradd_bottom = ; // Additive material color to apply to bottom section of sidedef. Default is black (0x000000) + colorization_top = ; // Sets a colorization record for the upper texture. Colorization records must be defined in TEXTURES. + colorization_mid = ; // Sets a colorization record for the middle texture. Colorization records must be defined in TEXTURES. + colorization_bottom = ; // Sets a colorization record for the lower texture. Colorization records must be defined in TEXTURES. } sector @@ -288,6 +291,9 @@ Note: All fields default to false unless mentioned otherwise. coloradd_sprites = ; // Additive material color applied to sprites within the sector. Default is black (0x000000) coloradd_walls = ; // Additive material color applied to walls within the sector. Default is black (0x000000) + colorization_floor = ; // Sets a colorization record for the floor texture. Colorization records must be defined in TEXTURES. + colorization_ceiling = ; // Sets a colorization record for the ceiling texture. Colorization records must be defined in TEXTURES. + portal_ceil_blocksound = ; // ceiling portal blocks sound. portal_ceil_disabled = ; // ceiling portal disabled. portal_ceil_nopass = ; // 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 =============================================================================== diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index d9f30dd8b2..8c551ba0c8 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -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 diff --git a/src/gamedata/textures/texturemanager.cpp b/src/gamedata/textures/texturemanager.cpp index 1bdbf96247..cc2dc548f4 100644 --- a/src/gamedata/textures/texturemanager.cpp +++ b/src/gamedata/textures/texturemanager.cpp @@ -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")) { diff --git a/src/gamedata/textures/textures.h b/src/gamedata/textures/textures.h index 2791199152..416d9e719d 100644 --- a/src/gamedata/textures/textures.h +++ b/src/gamedata/textures/textures.h @@ -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 mSwitchDefs; TArray mAnimatedDoors; + TMap tmanips; public: TArray mAnimations; diff --git a/src/maploader/udmf.cpp b/src/maploader/udmf.cpp index b1c0ba0541..c1aae17153 100644 --- a/src/maploader/udmf.cpp +++ b/src/maploader/udmf.cpp @@ -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; diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 025ca18a4b..add4ce024b 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -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; diff --git a/src/r_data/r_translate.h b/src/r_data/r_translate.h index 8e704a5d34..0c52f256d7 100644 --- a/src/r_data/r_translate.h +++ b/src/r_data/r_translate.h @@ -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 diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index 4f0d2fb328..ea4d9530b1 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -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(); diff --git a/src/utility/namedef.h b/src/utility/namedef.h index e2063f8a77..c0d5f82d3d 100644 --- a/src/utility/namedef.h +++ b/src/utility/namedef.h @@ -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) diff --git a/wadsrc/static/zscript/mapdata.zs b/wadsrc/static/zscript/mapdata.zs index 3fbb21df90..d3fd0d21b5 100644 --- a/wadsrc/static/zscript/mapdata.zs +++ b/wadsrc/static/zscript/mapdata.zs @@ -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);