- more options for Doom 64 style gradients on walls:

* Colors can npw be defined per sidedef, not only per sector.
* Gradients can be selectively disabled or vertically flipped per wall tier.
* Gradients can be clamped to their respective tier, i.e top and bottom of the tier, not the front sector defines where it starts.

The per-wall colors are implemented for hardware and softpoly renderer only, but not for the classic software renderer, because its code is far too scattered to do this efficiently.

# Conflicts:
#	src/hwrenderer/scene/hw_renderstate.h
#	src/hwrenderer/scene/hw_walls.cpp

# Conflicts:
#	src/gl/scene/gl_walls_draw.cpp
This commit is contained in:
Christoph Oelckers 2018-11-11 16:04:05 +01:00 committed by drfrag666
parent e00db66432
commit 8368331481
15 changed files with 390 additions and 135 deletions

View file

@ -179,6 +179,27 @@ Note: All <bool> fields default to false unless mentioned otherwise.
clipmidtex = <bool>; // Side's mid textures are clipped to floor and ceiling. clipmidtex = <bool>; // Side's mid textures are clipped to floor and ceiling.
wrapmidtex = <bool>; // Side's mid textures are wrapped. wrapmidtex = <bool>; // Side's mid textures are wrapped.
nodecals = <bool>; // Disables decals on the sidedef. nodecals = <bool>; // Disables decals on the sidedef.
nogradient_top = <bool>; // disables color gradient on upper tier. (Hardware rendering only.)
flipgradient_top = <bool>; // flips gradient colors on upper tier. (Hardware rendering only.)
clampgradient_top = <bool>; // clamps gradient on upper tier to actual bounds (default is the entire front sector height, hardware rendering only.)
useowncolors_top = <bool>; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector.
uppercolor_top = <int>; // Material color of the top of the upper tier.
lowercolor_top = <int>; // Material color of the bottom of the upper tier. (Hardware rendering only.)
nogradient_mid = <bool>; // disables color gradient on middle tier. (Hardware rendering only.)
flipgradient_mid = <bool>; // flips gradient colors on middle tier. (Hardware rendering only.)
clampgradient_mid = <bool>; // clamps gradient on middle tier to actual bounds (default is the entire front sector height, hardware rendering only.)
useowncolors_mid = <bool>; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector.
uppercolor_mid = <int>; // Material color of the top of the middle tier.
lowercolor_mid = <int>; // Material color of the bottom of the middle tier. (Hardware rendering only.)
nogradient_bottom = <bool>; // disables color gradient on lower tier. (Hardware rendering only.)
flipgradient_bottom = <bool>; // flips gradient colors on lower tier. (Hardware rendering only.)
clampgradient_bottom = <bool>;// clamps gradient on lower tier to actual bounds (default is the entire front sector height, hardware rendering only.)
useowncolors_bottom = <bool>; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector.
uppercolor_bottom = <int>; // Material color of the top of the lower tier.
lowercolor_bottom = <int>; // Material color of the bottom of the lower tier. (Hardware rendering only.)
} }
sector sector

View file

@ -68,7 +68,7 @@ static void matrixToGL(const VSMatrix &mat, int loc)
void FRenderState::Reset() void FRenderState::Reset()
{ {
mTextureEnabled = true; mTextureEnabled = true;
mClipLineEnabled = mSplitEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false; mClipLineEnabled = mSplitEnabled = mGradientEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
mColorMask[0] = mColorMask[1] = mColorMask[2] = mColorMask[3] = true; mColorMask[0] = mColorMask[1] = mColorMask[2] = mColorMask[3] = true;
currentColorMask[0] = currentColorMask[1] = currentColorMask[2] = currentColorMask[3] = true; currentColorMask[0] = currentColorMask[1] = currentColorMask[2] = currentColorMask[3] = true;
mFogColor.d = -1; mFogColor.d = -1;
@ -109,6 +109,8 @@ void FRenderState::Reset()
mGlowBottom.Set(0.0f, 0.0f, 0.0f, 0.0f); mGlowBottom.Set(0.0f, 0.0f, 0.0f, 0.0f);
mGlowTopPlane.Set(0.0f, 0.0f, 0.0f, 0.0f); mGlowTopPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
mGlowBottomPlane.Set(0.0f, 0.0f, 0.0f, 0.0f); mGlowBottomPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
mGradientTopPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
mGradientBottomPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
mSplitTopPlane.Set(0.0f, 0.0f, 0.0f, 0.0f); mSplitTopPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
mSplitBottomPlane.Set(0.0f, 0.0f, 0.0f, 0.0f); mSplitBottomPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
mClipLine.Set(0.0f, 0.0f, 0.0f, 0.0f); mClipLine.Set(0.0f, 0.0f, 0.0f, 0.0f);

View file

@ -75,6 +75,7 @@ class FRenderState
bool mTextureEnabled; bool mTextureEnabled;
bool mFogEnabled; bool mFogEnabled;
bool mGlowEnabled; bool mGlowEnabled;
bool mGradientEnabled;
bool mSplitEnabled; bool mSplitEnabled;
bool mClipLineEnabled; bool mClipLineEnabled;
bool mBrightmapEnabled; bool mBrightmapEnabled;
@ -103,6 +104,7 @@ class FRenderState
FStateVec4 mCameraPos; FStateVec4 mCameraPos;
FStateVec4 mGlowTop, mGlowBottom; FStateVec4 mGlowTop, mGlowBottom;
FStateVec4 mGlowTopPlane, mGlowBottomPlane; FStateVec4 mGlowTopPlane, mGlowBottomPlane;
FStateVec4 mGradientTopPlane, mGradientBottomPlane;
FStateVec4 mSplitTopPlane, mSplitBottomPlane; FStateVec4 mSplitTopPlane, mSplitBottomPlane;
FStateVec4 mClipLine; FStateVec4 mClipLine;
PalEntry mFogColor; PalEntry mFogColor;
@ -285,6 +287,11 @@ public:
mGlowEnabled = on; mGlowEnabled = on;
} }
void EnableGradient(bool on)
{
mGradientEnabled = on;
}
void EnableSplit(bool on) void EnableSplit(bool on)
{ {
if (!(gl.flags & RFL_NO_CLIP_PLANES)) if (!(gl.flags & RFL_NO_CLIP_PLANES))
@ -369,6 +376,14 @@ public:
mGlowBottomPlane.Set(bn.X, bn.Y, 1. / bn.Z, bottom.fD()); mGlowBottomPlane.Set(bn.X, bn.Y, 1. / bn.Z, bottom.fD());
} }
void SetGradientPlanes(const secplane_t &top, const secplane_t &bottom)
{
DVector3 tn = top.Normal();
DVector3 bn = bottom.Normal();
mGradientTopPlane.Set(tn.X, tn.Y, 1. / tn.Z, top.fD());
mGradientBottomPlane.Set(bn.X, bn.Y, 1. / bn.Z, bottom.fD());
}
void SetSplitPlanes(const secplane_t &top, const secplane_t &bottom) void SetSplitPlanes(const secplane_t &top, const secplane_t &bottom)
{ {
DVector3 tn = top.Normal(); DVector3 tn = top.Normal();

View file

@ -324,6 +324,20 @@ void GLWall::RenderMirrorSurface()
// //
//========================================================================== //==========================================================================
static const uint8_t renderwalltotier[] =
{
side_t::none,
side_t::top,
side_t::mid,
side_t::mid,
side_t::bottom,
side_t::none,
side_t::none,
side_t::mid,
side_t::none,
side_t::mid,
};
void GLWall::RenderTextured(int rflags) void GLWall::RenderTextured(int rflags)
{ {
int tmode = gl_RenderState.GetTextureMode(); int tmode = gl_RenderState.GetTextureMode();
@ -333,8 +347,8 @@ void GLWall::RenderTextured(int rflags)
{ {
gl_RenderState.EnableGlow(true); gl_RenderState.EnableGlow(true);
gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor); gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor);
}
gl_RenderState.SetGlowPlanes(frontsector->ceilingplane, frontsector->floorplane); gl_RenderState.SetGlowPlanes(frontsector->ceilingplane, frontsector->floorplane);
}
gl_RenderState.SetMaterial(gltexture, flags & 3, 0, -1, false); gl_RenderState.SetMaterial(gltexture, flags & 3, 0, -1, false);
if (type == RENDERWALL_M2SNF) if (type == RENDERWALL_M2SNF)
@ -345,11 +359,44 @@ void GLWall::RenderTextured(int rflags)
} }
mDrawer->SetFog(255, 0, NULL, false); mDrawer->SetFog(255, 0, NULL, false);
} }
gl_RenderState.SetObjectColor(seg->frontsector->SpecialColors[sector_t::walltop] | 0xff000000); if (type != RENDERWALL_COLOR)
gl_RenderState.SetObjectColor2(seg->frontsector->SpecialColors[sector_t::wallbottom] | 0xff000000); {
auto side = seg->sidedef;
auto tierndx = renderwalltotier[type];
auto &tier = side->textures[tierndx];
PalEntry color1 = side->GetSpecialColor(tierndx, side_t::walltop, frontsector);
PalEntry color2 = side->GetSpecialColor(tierndx, side_t::wallbottom, frontsector);
gl_RenderState.SetObjectColor(color1);
gl_RenderState.SetObjectColor2(color2);
if (color1 != color2)
{
// Do gradient setup only if there actually is a gradient.
gl_RenderState.EnableGradient(true);
if ((tier.flags & side_t::part::ClampGradient) && backsector)
{
if (tierndx == side_t::top)
{
gl_RenderState.SetGradientPlanes(frontsector->ceilingplane, backsector->ceilingplane);
}
else if (tierndx == side_t::mid)
{
gl_RenderState.SetGradientPlanes(backsector->ceilingplane, backsector->floorplane);
}
else // side_t::bottom:
{
gl_RenderState.SetGradientPlanes(backsector->floorplane, frontsector->floorplane);
}
}
else
{
gl_RenderState.SetGradientPlanes(frontsector->ceilingplane, frontsector->floorplane);
}
}
}
float absalpha = fabsf(alpha); float absalpha = fabsf(alpha);
if (lightlist == NULL) if (lightlist == nullptr)
{ {
if (type != RENDERWALL_M2SNF) mDrawer->SetFog(lightlevel, rel, &Colormap, RenderStyle == STYLE_Add); if (type != RENDERWALL_M2SNF) mDrawer->SetFog(lightlevel, rel, &Colormap, RenderStyle == STYLE_Add);
mDrawer->SetColor(lightlevel, rel, Colormap, absalpha); mDrawer->SetColor(lightlevel, rel, Colormap, absalpha);
@ -368,7 +415,7 @@ void GLWall::RenderTextured(int rflags)
if (low1 < ztop[0] || low2 < ztop[1]) if (low1 < ztop[0] || low2 < ztop[1])
{ {
int thisll = (*lightlist)[i].caster != NULL ? gl_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel; int thisll = (*lightlist)[i].caster != nullptr ? gl_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel;
FColormap thiscm; FColormap thiscm;
thiscm.FadeColor = Colormap.FadeColor; thiscm.FadeColor = Colormap.FadeColor;
thiscm.FogDensity = Colormap.FogDensity; thiscm.FogDensity = Colormap.FogDensity;
@ -387,6 +434,7 @@ void GLWall::RenderTextured(int rflags)
gl_RenderState.SetObjectColor2(0); gl_RenderState.SetObjectColor2(0);
gl_RenderState.SetTextureMode(tmode); gl_RenderState.SetTextureMode(tmode);
gl_RenderState.EnableGlow(false); gl_RenderState.EnableGlow(false);
gl_RenderState.EnableGradient(false);
} }
//========================================================================== //==========================================================================

View file

@ -173,6 +173,9 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
i_data += "uniform vec4 uGlowBottomPlane;\n"; i_data += "uniform vec4 uGlowBottomPlane;\n";
i_data += "uniform vec4 uGlowBottomColor;\n"; i_data += "uniform vec4 uGlowBottomColor;\n";
i_data += "uniform vec4 uGradientTopPlane;\n";
i_data += "uniform vec4 uGradientBottomPlane;\n";
i_data += "uniform vec4 uSplitTopPlane;\n"; i_data += "uniform vec4 uSplitTopPlane;\n";
i_data += "uniform vec4 uSplitBottomPlane;\n"; i_data += "uniform vec4 uSplitBottomPlane;\n";
@ -461,6 +464,8 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
muGlowTopColor.Init(hShader, "uGlowTopColor"); muGlowTopColor.Init(hShader, "uGlowTopColor");
muGlowBottomPlane.Init(hShader, "uGlowBottomPlane"); muGlowBottomPlane.Init(hShader, "uGlowBottomPlane");
muGlowTopPlane.Init(hShader, "uGlowTopPlane"); muGlowTopPlane.Init(hShader, "uGlowTopPlane");
muGradientBottomPlane.Init(hShader, "uGradientBottomPlane");
muGradientTopPlane.Init(hShader, "uGradientTopPlane");
muSplitBottomPlane.Init(hShader, "uSplitBottomPlane"); muSplitBottomPlane.Init(hShader, "uSplitBottomPlane");
muSplitTopPlane.Init(hShader, "uSplitTopPlane"); muSplitTopPlane.Init(hShader, "uSplitTopPlane");
muClipLine.Init(hShader, "uClipLine"); muClipLine.Init(hShader, "uClipLine");

View file

@ -277,6 +277,8 @@ class FShader
FUniform4f muGlowTopColor; FUniform4f muGlowTopColor;
FUniform4f muGlowBottomPlane; FUniform4f muGlowBottomPlane;
FUniform4f muGlowTopPlane; FUniform4f muGlowTopPlane;
FUniform4f muGradientBottomPlane;
FUniform4f muGradientTopPlane;
FUniform4f muSplitBottomPlane; FUniform4f muSplitBottomPlane;
FUniform4f muSplitTopPlane; FUniform4f muSplitTopPlane;
FUniform4f muClipLine; FUniform4f muClipLine;
@ -303,6 +305,7 @@ public:
int fakevb_index; int fakevb_index;
private: private:
int currentglowstate = 0; int currentglowstate = 0;
int currentgradientstate = 0;
int currentsplitstate = 0; int currentsplitstate = 0;
int currentcliplinestate = 0; int currentcliplinestate = 0;
int currentfixedcolormap = 0; int currentfixedcolormap = 0;

View file

@ -630,6 +630,26 @@ xx(hidden)
xx(blocksight) xx(blocksight)
xx(blockhitscan) xx(blockhitscan)
xx(nogradient_top)
xx(flipgradient_top)
xx(clampgradient_top)
xx(useowncolors_top)
xx(uppercolor_top)
xx(lowercolor_top)
xx(nogradient_mid)
xx(flipgradient_mid)
xx(clampgradient_mid)
xx(useowncolors_mid)
xx(uppercolor_mid)
xx(lowercolor_mid)
xx(nogradient_bottom)
xx(flipgradient_bottom)
xx(clampgradient_bottom)
xx(useowncolors_bottom)
xx(uppercolor_bottom)
xx(lowercolor_bottom)
xx(Renderstyle) xx(Renderstyle)
xx(ceilingplane_a) xx(ceilingplane_a)

View file

@ -113,6 +113,9 @@ FSerializer &Serialize(FSerializer &arc, const char *key, side_t::part &part, si
("yscale", part.yScale, def->yScale) ("yscale", part.yScale, def->yScale)
("texture", part.texture, def->texture) ("texture", part.texture, def->texture)
("interpolation", part.interpolation) ("interpolation", part.interpolation)
("flags", part.flags, def->flags)
("color1", part.SpecialColors[0], def->SpecialColors[0])
("color2", part.SpecialColors[1], def->SpecialColors[1])
.EndObject(); .EndObject();
} }
return arc; return arc;

View file

@ -879,17 +879,6 @@ DEFINE_ACTION_FUNCTION(_Sector, SetFade)
// //
//===================================================================================== //=====================================================================================
void sector_t::SetSpecialColor(int slot, int r, int g, int b)
{
SpecialColors[slot] = PalEntry(255, r, g, b);
}
void sector_t::SetSpecialColor(int slot, PalEntry rgb)
{
rgb.a = 255;
SpecialColors[slot] = rgb;
}
DEFINE_ACTION_FUNCTION(_Sector, SetSpecialColor) DEFINE_ACTION_FUNCTION(_Sector, SetSpecialColor)
{ {
PARAM_SELF_STRUCT_PROLOGUE(sector_t); PARAM_SELF_STRUCT_PROLOGUE(sector_t);

View file

@ -4249,9 +4249,21 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
memcpy(&level.loadlines[0], &level.lines[0], level.lines.Size() * sizeof(level.lines[0])); memcpy(&level.loadlines[0], &level.lines[0], level.lines.Size() * sizeof(level.lines[0]));
level.loadsides.Resize(level.sides.Size()); level.loadsides.Resize(level.sides.Size());
memcpy(&level.loadsides[0], &level.sides[0], level.sides.Size() * sizeof(level.sides[0])); memcpy(&level.loadsides[0], &level.sides[0], level.sides.Size() * sizeof(level.sides[0]));
for (auto i : { 29, 30 })
{
level.lines[i].sidedef[0]->SetSpecialColor(side_t::top, side_t::walltop, PalEntry(255, 255, 0));
level.lines[i].sidedef[0]->SetSpecialColor(side_t::top, side_t::wallbottom, PalEntry(0, 255, 255));
level.lines[i].sidedef[0]->SetSpecialColor(side_t::bottom, side_t::walltop, PalEntry(255, 0, 0));
level.lines[i].sidedef[0]->SetSpecialColor(side_t::bottom, side_t::wallbottom, PalEntry(0, 0, 255));
} }
level.lines[29].sidedef[0]->textures[side_t::top].flags = side_t::part::UseOwnColors;
level.lines[30].sidedef[0]->textures[side_t::top].flags = side_t::part::UseOwnColors | side_t::part::ClampGradient;
level.lines[29].sidedef[0]->textures[side_t::bottom].flags = side_t::part::UseOwnColors;
level.lines[30].sidedef[0]->textures[side_t::bottom].flags = side_t::part::UseOwnColors | side_t::part::ClampGradient;
}
// //
// P_Init // P_Init

View file

@ -1226,6 +1226,7 @@ public:
{ {
FName key = ParseKey(); FName key = ParseKey();
switch(key) switch(key)
{ {
case NAME_Offsetx: case NAME_Offsetx:
texOfs[0] = CheckInt(key); texOfs[0] = CheckInt(key);
@ -1337,6 +1338,79 @@ public:
Flag(sd->Flags, WALLF_NOAUTODECALS, key); Flag(sd->Flags, WALLF_NOAUTODECALS, key);
continue; continue;
case NAME_nogradient_top:
Flag(sd->textures[side_t::top].flags, side_t::part::NoGradient, key);
break;
case NAME_flipgradient_top:
Flag(sd->textures[side_t::top].flags, side_t::part::FlipGradient, key);
break;
case NAME_clampgradient_top:
Flag(sd->textures[side_t::top].flags, side_t::part::ClampGradient, key);
break;
case NAME_useowncolors_top:
Flag(sd->textures[side_t::top].flags, side_t::part::UseOwnColors, key);
break;
case NAME_uppercolor_top:
sd->SetSpecialColor(side_t::top, 0, CheckInt(key));
break;
case NAME_lowercolor_top:
sd->SetSpecialColor(side_t::top, 1, CheckInt(key));
break;
case NAME_nogradient_mid:
Flag(sd->textures[side_t::mid].flags, side_t::part::NoGradient, key);
break;
case NAME_flipgradient_mid:
Flag(sd->textures[side_t::mid].flags, side_t::part::FlipGradient, key);
break;
case NAME_clampgradient_mid:
Flag(sd->textures[side_t::mid].flags, side_t::part::ClampGradient, key);
break;
case NAME_useowncolors_mid:
Flag(sd->textures[side_t::mid].flags, side_t::part::UseOwnColors, key);
break;
case NAME_uppercolor_mid:
sd->SetSpecialColor(side_t::mid, 0, CheckInt(key));
break;
case NAME_lowercolor_mid:
sd->SetSpecialColor(side_t::mid, 1, CheckInt(key));
break;
case NAME_nogradient_bottom:
Flag(sd->textures[side_t::bottom].flags, side_t::part::NoGradient, key);
break;
case NAME_flipgradient_bottom:
Flag(sd->textures[side_t::bottom].flags, side_t::part::FlipGradient, key);
break;
case NAME_clampgradient_bottom:
Flag(sd->textures[side_t::bottom].flags, side_t::part::ClampGradient, key);
break;
case NAME_useowncolors_bottom:
Flag(sd->textures[side_t::bottom].flags, side_t::part::UseOwnColors, key);
break;
case NAME_uppercolor_bottom:
sd->SetSpecialColor(side_t::bottom, 0, CheckInt(key));
break;
case NAME_lowercolor_bottom:
sd->SetSpecialColor(side_t::bottom, 1, CheckInt(key));
break;
default: default:
break; break;

View file

@ -88,7 +88,6 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
wall.Line = line->linedef; wall.Line = line->linedef;
wall.Side = line->sidedef; wall.Side = line->sidedef;
wall.LineSegLine = line->linedef; wall.LineSegLine = line->linedef;
wall.Colormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
wall.Masked = false; wall.Masked = false;
wall.SubsectorDepth = subsectorDepth; wall.SubsectorDepth = subsectorDepth;
wall.StencilValue = stencilValue; wall.StencilValue = stencilValue;
@ -102,6 +101,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
wall.TopTexZ = topTexZ; wall.TopTexZ = topTexZ;
wall.BottomTexZ = bottomTexZ; wall.BottomTexZ = bottomTexZ;
wall.Wallpart = side_t::mid; wall.Wallpart = side_t::mid;
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid); wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid);
wall.Polyportal = polyportal; wall.Polyportal = polyportal;
wall.Render(thread); wall.Render(thread);
@ -140,6 +140,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
wall.TopTexZ = topTexZ; wall.TopTexZ = topTexZ;
wall.BottomTexZ = MIN(MIN(backceilz1, frontceilz1), MIN(backceilz2, frontceilz2)); wall.BottomTexZ = MIN(MIN(backceilz1, frontceilz1), MIN(backceilz2, frontceilz2));
wall.Wallpart = side_t::top; wall.Wallpart = side_t::top;
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::top); wall.Texture = GetTexture(wall.Line, wall.Side, side_t::top);
wall.Render(thread); wall.Render(thread);
} }
@ -152,6 +153,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
wall.UnpeggedCeil1 = topceilz1; wall.UnpeggedCeil1 = topceilz1;
wall.UnpeggedCeil2 = topceilz2; wall.UnpeggedCeil2 = topceilz2;
wall.Wallpart = side_t::bottom; wall.Wallpart = side_t::bottom;
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::bottom); wall.Texture = GetTexture(wall.Line, wall.Side, side_t::bottom);
wall.Render(thread); wall.Render(thread);
} }
@ -162,6 +164,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
wall.TopTexZ = MAX(middleceilz1, middleceilz2); wall.TopTexZ = MAX(middleceilz1, middleceilz2);
wall.BottomTexZ = MIN(middlefloorz1, middlefloorz2); wall.BottomTexZ = MIN(middlefloorz1, middlefloorz2);
wall.Wallpart = side_t::mid; wall.Wallpart = side_t::mid;
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid); wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid);
wall.Masked = true; wall.Masked = true;
wall.Additive = !!(wall.Line->flags & ML_ADDTRANS); wall.Additive = !!(wall.Line->flags & ML_ADDTRANS);
@ -212,7 +215,6 @@ void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, seg_t *line, se
wall.LineSegLine = line->linedef; wall.LineSegLine = line->linedef;
wall.Line = fakeFloor->master; wall.Line = fakeFloor->master;
wall.Side = fakeFloor->master->sidedef[0]; wall.Side = fakeFloor->master->sidedef[0];
wall.Colormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
wall.SectorLightLevel = frontsector->lightlevel; wall.SectorLightLevel = frontsector->lightlevel;
wall.Additive = !!(fakeFloor->flags & FF_ADDITIVETRANS); wall.Additive = !!(fakeFloor->flags & FF_ADDITIVETRANS);
if (!wall.Additive && fakeFloor->alpha == 255) if (!wall.Additive && fakeFloor->alpha == 255)
@ -231,6 +233,7 @@ void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, seg_t *line, se
wall.TopTexZ = topTexZ; wall.TopTexZ = topTexZ;
wall.BottomTexZ = bottomTexZ; wall.BottomTexZ = bottomTexZ;
wall.Wallpart = side_t::mid; wall.Wallpart = side_t::mid;
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
if (fakeFloor->flags & FF_UPPERTEXTURE) if (fakeFloor->flags & FF_UPPERTEXTURE)
wall.Texture = GetTexture(line->linedef, line->sidedef, side_t::top); wall.Texture = GetTexture(line->linedef, line->sidedef, side_t::top);
else if (fakeFloor->flags & FF_LOWERTEXTURE) else if (fakeFloor->flags & FF_LOWERTEXTURE)

View file

@ -325,7 +325,7 @@ public:
return !normal.XY().isZero(); return !normal.XY().isZero();
} }
DVector3 Normal() const const DVector3 &Normal() const
{ {
return normal; return normal;
} }
@ -645,8 +645,6 @@ public:
void SetColor(int r, int g, int b, int desat); void SetColor(int r, int g, int b, int desat);
void SetFade(int r, int g, int b); void SetFade(int r, int g, int b);
void SetFogDensity(int dens); void SetFogDensity(int dens);
void SetSpecialColor(int num, int r, int g, int b);
void SetSpecialColor(int num, PalEntry rgb);
void ClosestPoint(const DVector2 &pos, DVector2 &out) const; void ClosestPoint(const DVector2 &pos, DVector2 &out) const;
int GetFloorLight () const; int GetFloorLight () const;
int GetCeilingLight () const; int GetCeilingLight () const;
@ -914,6 +912,17 @@ public:
Flags &= ~SECF_SPECIALFLAGS; Flags &= ~SECF_SPECIALFLAGS;
} }
void SetSpecialColor(int slot, int r, int g, int b)
{
SpecialColors[slot] = PalEntry(255, r, g, b);
}
void SetSpecialColor(int slot, PalEntry rgb)
{
rgb.a = 255;
SpecialColors[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);
@ -1149,16 +1158,31 @@ struct side_t
{ {
top=0, top=0,
mid=1, mid=1,
bottom=2 bottom=2,
none = 1, // this is just for clarification in a mapping table
};
enum EColorSlot
{
walltop = 0,
wallbottom = 1,
}; };
struct part struct part
{ {
enum EPartFlags
{
NoGradient = 1,
FlipGradient = 2,
ClampGradient = 4,
UseOwnColors = 8,
};
double xOffset; double xOffset;
double yOffset; double yOffset;
double xScale; double xScale;
double yScale; double yScale;
TObjPtr<DInterpolation*> interpolation; TObjPtr<DInterpolation*> interpolation;
FTextureID texture; FTextureID texture;
int flags;
PalEntry SpecialColors[2];
void InitFrom(const part &other) void InitFrom(const part &other)
{ {
@ -1281,6 +1305,28 @@ struct side_t
textures[which].yScale *= delta; textures[which].yScale *= delta;
} }
void SetSpecialColor(int which, int slot, int r, int g, int b)
{
textures[which].SpecialColors[slot] = PalEntry(255, r, g, b);
}
void SetSpecialColor(int which, int slot, PalEntry rgb)
{
rgb.a = 255;
textures[which].SpecialColors[slot] = rgb;
}
// Note that the sector being passed in here may not be the actual sector this sidedef belongs to
// (either for polyobjects or FakeFlat'ed temporaries.)
PalEntry GetSpecialColor(int which, int slot, sector_t *frontsector) const
{
auto &part = textures[which];
if (part.flags & part::NoGradient) slot = 0;
if (part.flags & part::FlipGradient) slot ^= 1;
return (part.flags & part::UseOwnColors) ? part.SpecialColors[slot] : frontsector->SpecialColors[sector_t::walltop + slot];
}
DInterpolation *SetInterpolation(int position); DInterpolation *SetInterpolation(int position);
void StopInterpolation(int position); void StopInterpolation(int position);

View file

@ -1,5 +1,6 @@
in vec4 pixelpos; in vec4 pixelpos;
in vec3 glowdist; in vec3 glowdist;
in vec3 gradientdist;
in vec4 vWorldNormal; in vec4 vWorldNormal;
in vec4 vEyeNormal; in vec4 vEyeNormal;
@ -90,7 +91,7 @@ vec4 getTexel(vec2 st)
break; break;
} }
if (uObjectColor2.a == 0.0) texel *= uObjectColor; if (uObjectColor2.a == 0.0) texel *= uObjectColor;
else texel *= mix(uObjectColor, uObjectColor2, glowdist.z); else texel *= mix(uObjectColor, uObjectColor2, gradientdist.z);
return desaturate(texel); return desaturate(texel);
} }

View file

@ -7,6 +7,7 @@ in vec4 aVertex2;
in vec4 aNormal; in vec4 aNormal;
out vec4 pixelpos; out vec4 pixelpos;
out vec3 glowdist; out vec3 glowdist;
out vec3 gradientdist;
out vec4 vWorldNormal; out vec4 vWorldNormal;
out vec4 vEyeNormal; out vec4 vEyeNormal;
@ -50,16 +51,28 @@ void main()
pixelpos.xyz = worldcoord.xyz; pixelpos.xyz = worldcoord.xyz;
pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w; pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w;
float topatpoint = -((uGlowTopPlane.w + uGlowTopPlane.x * worldcoord.x + uGlowTopPlane.y * worldcoord.z) * uGlowTopPlane.z); if (uGlowTopColor.a > 0 || uGlowBottomColor.a > 0)
float bottomatpoint = -((uGlowBottomPlane.w + uGlowBottomPlane.x * worldcoord.x + uGlowBottomPlane.y * worldcoord.z) * uGlowBottomPlane.z); {
float topatpoint = (uGlowTopPlane.w + uGlowTopPlane.x * worldcoord.x + uGlowTopPlane.y * worldcoord.z) * uGlowTopPlane.z;
float bottomatpoint = (uGlowBottomPlane.w + uGlowBottomPlane.x * worldcoord.x + uGlowBottomPlane.y * worldcoord.z) * uGlowBottomPlane.z;
glowdist.x = topatpoint - worldcoord.y; glowdist.x = topatpoint - worldcoord.y;
glowdist.y = worldcoord.y - bottomatpoint; glowdist.y = worldcoord.y - bottomatpoint;
glowdist.z = clamp(glowdist.x / (topatpoint - bottomatpoint), 0.0, 1.0); glowdist.z = clamp(glowdist.x / (topatpoint - bottomatpoint), 0.0, 1.0);
}
if (uObjectColor2.a != 0)
{
float topatpoint = (uGradientTopPlane.w + uGradientTopPlane.x * worldcoord.x + uGradientTopPlane.y * worldcoord.z) * uGradientTopPlane.z;
float bottomatpoint = (uGradientBottomPlane.w + uGradientBottomPlane.x * worldcoord.x + uGradientBottomPlane.y * worldcoord.z) * uGradientBottomPlane.z;
gradientdist.x = topatpoint - worldcoord.y;
gradientdist.y = worldcoord.y - bottomatpoint;
gradientdist.z = clamp(gradientdist.x / (topatpoint - bottomatpoint), 0.0, 1.0);
}
if (uSplitBottomPlane.z != 0.0) if (uSplitBottomPlane.z != 0.0)
{ {
gl_ClipDistance[3] = -((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y; gl_ClipDistance[3] = ((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y;
gl_ClipDistance[4] = worldcoord.y + ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z); gl_ClipDistance[4] = worldcoord.y - ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z);
} }
vWorldNormal = NormalModelMatrix * vec4(normalize(aNormal.xyz), 1.0); vWorldNormal = NormalModelMatrix * vec4(normalize(aNormal.xyz), 1.0);