Rework implementation as per the new specification

The new specification is more flexible, and allows assigning additive 
colors to individual parts of a sector (walls, sprites, flats) and even 
individual parts of a side (top, middle, bottom)

Add AdditiveColors arrays to sector_t and side_t::part
Initialize AdditiveColors arrays to 0
Export AdditiveColors to ZScript
Save AdditiveColors in saved game files
Use colors from AdditiveColors arrays when setting the additive color 
for the render state
Add code to parse the new UDMF additive color properties
Remove additive color slot from sector color/part enum
Add SetAdditiveColor to sector_t and side_t
Add GetAdditiveColor to side_t
Export new methods and additive color arrays to ZScript
This commit is contained in:
Kevin Caccamo 2018-12-20 19:03:52 -05:00 committed by Christoph Oelckers
parent 60696c91a2
commit 0773e6a98e
10 changed files with 123 additions and 16 deletions

View file

@ -509,7 +509,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which)
lightlevel = hw_ClampLight(frontsector->GetFloorLight()); lightlevel = hw_ClampLight(frontsector->GetFloorLight());
Colormap = frontsector->Colormap; Colormap = frontsector->Colormap;
FlatColor = frontsector->SpecialColors[sector_t::floor]; FlatColor = frontsector->SpecialColors[sector_t::floor];
AddColor = frontsector->SpecialColors[sector_t::add]; AddColor = frontsector->AdditiveColors[sector_t::floor];
port = frontsector->ValidatePortal(sector_t::floor); port = frontsector->ValidatePortal(sector_t::floor);
if ((stack = (port != NULL))) if ((stack = (port != NULL)))
{ {
@ -565,7 +565,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which)
lightlevel = hw_ClampLight(frontsector->GetCeilingLight()); lightlevel = hw_ClampLight(frontsector->GetCeilingLight());
Colormap = frontsector->Colormap; Colormap = frontsector->Colormap;
FlatColor = frontsector->SpecialColors[sector_t::ceiling]; FlatColor = frontsector->SpecialColors[sector_t::ceiling];
AddColor = frontsector->SpecialColors[sector_t::add]; AddColor = frontsector->AdditiveColors[sector_t::ceiling];
port = frontsector->ValidatePortal(sector_t::ceiling); port = frontsector->ValidatePortal(sector_t::ceiling);
if ((stack = (port != NULL))) if ((stack = (port != NULL)))
{ {

View file

@ -159,7 +159,7 @@ void GLSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent)
: ThingColor.Modulate(cursec->SpecialColors[sector_t::sprites]); : ThingColor.Modulate(cursec->SpecialColors[sector_t::sprites]);
state.SetObjectColor(finalcol); state.SetObjectColor(finalcol);
state.SetAddColor(cursec->SpecialColors[sector_t::add] | 0xff000000); state.SetAddColor(cursec->AdditiveColors[sector_t::sprites] | 0xff000000);
} }
state.SetColor(lightlevel, rel, di->isFullbrightScene(), Colormap, trans); state.SetColor(lightlevel, rel, di->isFullbrightScene(), Colormap, trans);
} }

View file

@ -174,7 +174,7 @@ void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
PalEntry color2 = side->GetSpecialColor(tierndx, side_t::wallbottom, frontsector); PalEntry color2 = side->GetSpecialColor(tierndx, side_t::wallbottom, frontsector);
state.SetObjectColor(color1); state.SetObjectColor(color1);
state.SetObjectColor2(color2); state.SetObjectColor2(color2);
state.SetAddColor(seg->frontsector->SpecialColors[sector_t::add] | 0xff000000); state.SetAddColor(side->GetAdditiveColor(tierndx, frontsector));
if (color1 != color2) if (color1 != color2)
{ {
// Do gradient setup only if there actually is a gradient. // Do gradient setup only if there actually is a gradient.

View file

@ -72,9 +72,12 @@ void HWDrawInfo::DrawPSprite(HUDSprite *huds, FRenderState &state)
state.SetRenderStyle(huds->RenderStyle); state.SetRenderStyle(huds->RenderStyle);
state.SetTextureMode(huds->RenderStyle); state.SetTextureMode(huds->RenderStyle);
state.SetObjectColor(huds->ObjectColor); state.SetObjectColor(huds->ObjectColor);
if (huds->owner->Sector) { if (huds->owner->Sector)
state.SetAddColor(huds->owner->Sector->SpecialColors[sector_t::add] | 0xff000000); {
} else { state.SetAddColor(huds->owner->Sector->AdditiveColors[sector_t::sprites] | 0xff000000);
}
else
{
state.SetAddColor(0); state.SetAddColor(0);
} }
state.SetDynLight(huds->dynrgb[0], huds->dynrgb[1], huds->dynrgb[2]); state.SetDynLight(huds->dynrgb[0], huds->dynrgb[1], huds->dynrgb[2]);

View file

@ -108,6 +108,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, side_t::part &part, si
("flags", part.flags, def->flags) ("flags", part.flags, def->flags)
("color1", part.SpecialColors[0], def->SpecialColors[0]) ("color1", part.SpecialColors[0], def->SpecialColors[0])
("color2", part.SpecialColors[1], def->SpecialColors[1]) ("color2", part.SpecialColors[1], def->SpecialColors[1])
("addcolor", part.AdditiveColor, def->AdditiveColor)
.EndObject(); .EndObject();
} }
return arc; return arc;
@ -293,7 +294,8 @@ FSerializer &Serialize(FSerializer &arc, const char *key, sector_t &p, sector_t
("linked_floor", p.e->Linked.Floor.Sectors) ("linked_floor", p.e->Linked.Floor.Sectors)
("linked_ceiling", p.e->Linked.Ceiling.Sectors) ("linked_ceiling", p.e->Linked.Ceiling.Sectors)
("colormap", p.Colormap, def->Colormap) ("colormap", p.Colormap, def->Colormap)
.Array("specialcolors", p.SpecialColors, def->SpecialColors, 6, true) .Array("specialcolors", p.SpecialColors, def->SpecialColors, 5, true)
.Array("additivecolors", p.AdditiveColors, def->AdditiveColors, 5, true)
("gravity", p.gravity, def->gravity) ("gravity", p.gravity, def->gravity)
.Terrain("floorterrain", p.terrainnum[0], &def->terrainnum[0]) .Terrain("floorterrain", p.terrainnum[0], &def->terrainnum[0])
.Terrain("ceilingterrain", p.terrainnum[1], &def->terrainnum[1]) .Terrain("ceilingterrain", p.terrainnum[1], &def->terrainnum[1])

View file

@ -1096,7 +1096,7 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex)
ss->nextsec = -1; //jff 2/26/98 add fields to support locking out ss->nextsec = -1; //jff 2/26/98 add fields to support locking out
ss->prevsec = -1; // stair retriggering until build completes ss->prevsec = -1; // stair retriggering until build completes
memset(ss->SpecialColors, -1, sizeof(ss->SpecialColors)); memset(ss->SpecialColors, -1, sizeof(ss->SpecialColors));
ss->SpecialColors[sector_t::add] = 0; memset(ss->AdditiveColors, 0, sizeof(ss->AdditiveColors));
ss->SetAlpha(sector_t::floor, 1.); ss->SetAlpha(sector_t::floor, 1.);
ss->SetAlpha(sector_t::ceiling, 1.); ss->SetAlpha(sector_t::ceiling, 1.);

View file

@ -1388,6 +1388,18 @@ public:
sd->SetSpecialColor(side_t::bottom, 1, CheckInt(key)); sd->SetSpecialColor(side_t::bottom, 1, CheckInt(key));
break; break;
case NAME_coloradd_top:
sd->SetAdditiveColor(side_t::top, CheckInt(key));
break;
case NAME_coloradd_mid:
sd->SetAdditiveColor(side_t::mid, CheckInt(key));
break;
case NAME_coloradd_bottom:
sd->SetAdditiveColor(side_t::bottom, CheckInt(key));
break;
default: default:
break; break;
@ -1453,7 +1465,7 @@ public:
sec->terrainnum[sector_t::ceiling] = sec->terrainnum[sector_t::floor] = -1; sec->terrainnum[sector_t::ceiling] = sec->terrainnum[sector_t::floor] = -1;
sec->ibocount = -1; sec->ibocount = -1;
memset(sec->SpecialColors, -1, sizeof(sec->SpecialColors)); memset(sec->SpecialColors, -1, sizeof(sec->SpecialColors));
sec->SpecialColors[sector_t::add] = 0; memset(sec->AdditiveColors, 0, sizeof(sec->AdditiveColors));
if (floordrop) sec->Flags = SECF_FLOORDROP; if (floordrop) sec->Flags = SECF_FLOORDROP;
// killough 3/7/98: end changes // killough 3/7/98: end changes
@ -1626,8 +1638,20 @@ public:
sec->SpecialColors[sector_t::sprites] = CheckInt(key) | 0xff000000; sec->SpecialColors[sector_t::sprites] = CheckInt(key) | 0xff000000;
break; break;
case NAME_Color_Add: case NAME_ColorAdd_Floor:
sec->SpecialColors[sector_t::add] = CheckInt(key) | 0xff000000; sec->AdditiveColors[sector_t::floor] = CheckInt(key) | 0xff000000; // Alpha is used to decide whether or not to use the color
break;
case NAME_ColorAdd_Ceiling:
sec->AdditiveColors[sector_t::ceiling] = CheckInt(key) | 0xff000000;
break;
case NAME_ColorAdd_Walls:
sec->AdditiveColors[sector_t::walltop] = CheckInt(key) | 0xff000000;
break;
case NAME_ColorAdd_Sprites:
sec->AdditiveColors[sector_t::sprites] = CheckInt(key) | 0xff000000;
break; break;
case NAME_Desaturation: case NAME_Desaturation:

View file

@ -660,8 +660,8 @@ public:
// only used for specialcolors array // only used for specialcolors array
walltop, walltop,
wallbottom, wallbottom,
sprites, sprites
add
}; };
struct splane struct splane
@ -914,6 +914,12 @@ public:
SpecialColors[slot] = rgb; SpecialColors[slot] = rgb;
} }
void SetAdditiveColor(int slot, PalEntry rgb)
{
rgb.a = 255;
AdditiveColors[slot] = rgb;
}
inline bool PortalBlocksView(int plane); inline bool PortalBlocksView(int plane);
inline bool PortalBlocksSight(int plane); inline bool PortalBlocksSight(int plane);
inline bool PortalBlocksMovement(int plane); inline bool PortalBlocksMovement(int plane);
@ -974,7 +980,8 @@ public:
secplane_t floorplane, ceilingplane; secplane_t floorplane, ceilingplane;
// [RH] give floor and ceiling even more properties // [RH] give floor and ceiling even more properties
PalEntry SpecialColors[6]; PalEntry SpecialColors[5];
PalEntry AdditiveColors[5];
FColormap Colormap; FColormap Colormap;
TObjPtr<AActor*> SoundTarget; TObjPtr<AActor*> SoundTarget;
@ -1153,6 +1160,7 @@ struct side_t
FTextureID texture; FTextureID texture;
int flags; int flags;
PalEntry SpecialColors[2]; PalEntry SpecialColors[2];
PalEntry AdditiveColor;
void InitFrom(const part &other) void InitFrom(const part &other)
{ {
@ -1296,6 +1304,20 @@ struct side_t
return (part.flags & part::UseOwnColors) ? part.SpecialColors[slot] : frontsector->SpecialColors[sector_t::walltop + slot]; return (part.flags & part::UseOwnColors) ? part.SpecialColors[slot] : frontsector->SpecialColors[sector_t::walltop + slot];
} }
void SetAdditiveColor(int which, PalEntry rgb)
{
rgb.a = 255;
textures[which].AdditiveColor = rgb;
}
PalEntry GetAdditiveColor(int which, sector_t *frontsector) const
{
auto &color = textures[which].AdditiveColor;
if (color.a == 0) {
return frontsector->AdditiveColors[sector_t::walltop]; // Used as additive color for all walls
}
return color;
}
DInterpolation *SetInterpolation(int position); DInterpolation *SetInterpolation(int position);
void StopInterpolation(int position); void StopInterpolation(int position);

View file

@ -542,6 +542,23 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetSpecialColor, SetSpecialColor)
return 0; return 0;
} }
static void SetAdditiveColor(sector_t *self, int pos, int color)
{
if (pos >= 0 && pos < 5)
{
self->SetAdditiveColor(pos, color);
}
}
DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetAdditiveColor, SetAdditiveColor)
{
PARAM_SELF_STRUCT_PROLOGUE(sector_t);
PARAM_INT(pos);
PARAM_COLOR(color);
SetSpecialColor(self, pos, color);
return 0;
}
static void SetFogDensity(sector_t *self, int dens) static void SetFogDensity(sector_t *self, int dens)
{ {
self->Colormap.FogDensity = dens; self->Colormap.FogDensity = dens;
@ -1524,6 +1541,40 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, RemoveForceField, RemoveForceField)
return 0; return 0;
} }
static int GetSideAdditiveColor(side_t *self, int tier)
{
if (tier >= 0 && tier < 3)
{
return self->GetAdditiveColor(tier, self->sector);
}
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(_Side, GetAdditiveColor, GetSideAdditiveColor)
{
PARAM_SELF_STRUCT_PROLOGUE(side_t);
PARAM_INT(tier);
ACTION_RETURN_INT(GetSideAdditiveColor(self, tier));
return 0;
}
static void SetSideAdditiveColor(side_t *self, int tier, int color)
{
if (tier >= 0 && tier < 3)
{
self->SetAdditiveColor(tier, color);
}
}
DEFINE_ACTION_FUNCTION_NATIVE(_Side, SetAdditiveColor, SetSideAdditiveColor)
{
PARAM_SELF_STRUCT_PROLOGUE(side_t);
PARAM_INT(tier);
PARAM_COLOR(color);
SetSideAdditiveColor(self, tier, color);
return 0;
}
static int SideIndex(side_t *self) static int SideIndex(side_t *self)
{ {
unsigned ndx = self->Index(); unsigned ndx = self->Index();
@ -2701,6 +2752,7 @@ DEFINE_FIELD_X(Sector, sector_t, floorplane)
DEFINE_FIELD_X(Sector, sector_t, ceilingplane) DEFINE_FIELD_X(Sector, sector_t, ceilingplane)
DEFINE_FIELD_X(Sector, sector_t, Colormap) DEFINE_FIELD_X(Sector, sector_t, Colormap)
DEFINE_FIELD_X(Sector, sector_t, SpecialColors) DEFINE_FIELD_X(Sector, sector_t, SpecialColors)
DEFINE_FIELD_X(Sector, sector_t, AdditiveColors)
DEFINE_FIELD_X(Sector, sector_t, SoundTarget) DEFINE_FIELD_X(Sector, sector_t, SoundTarget)
DEFINE_FIELD_X(Sector, sector_t, special) DEFINE_FIELD_X(Sector, sector_t, special)
DEFINE_FIELD_X(Sector, sector_t, lightlevel) DEFINE_FIELD_X(Sector, sector_t, lightlevel)

View file

@ -86,6 +86,8 @@ struct Side native play
native double GetTextureYScale(int which); native double GetTextureYScale(int which);
native void MultiplyTextureYScale(int which, double delta); native void MultiplyTextureYScale(int which, double delta);
native void SetSpecialColor(int tier, int position, Color scolor); native void SetSpecialColor(int tier, int position, Color scolor);
native Color GetAdditiveColor(int tier);
native void SetAdditiveColor(int tier, Color color);
//native DInterpolation *SetInterpolation(int position); //native DInterpolation *SetInterpolation(int position);
//native void StopInterpolation(int position); //native void StopInterpolation(int position);
@ -235,7 +237,8 @@ struct Sector native play
{ {
native readonly FColormap ColorMap; native readonly FColormap ColorMap;
native readonly Color SpecialColors[6]; native readonly Color SpecialColors[5];
native readonly Color AdditiveColors[5];
native Actor SoundTarget; native Actor SoundTarget;
@ -409,6 +412,7 @@ struct Sector native play
native void SetGlowHeight(int pos, double height); native void SetGlowHeight(int pos, double height);
native void SetGlowColor(int pos, color color); native void SetGlowColor(int pos, color color);
native void SetSpecialColor(int pos, color color); native void SetSpecialColor(int pos, color color);
native void SetAdditiveColor(int pos, Color color);
native TextureID GetTexture(int pos); native TextureID GetTexture(int pos);
native void SetTexture(int pos, TextureID tex, bool floorclip = true); native void SetTexture(int pos, TextureID tex, bool floorclip = true);