mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 06:42:08 +00:00
- 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.
This commit is contained in:
parent
d37192c1e8
commit
f2dcff4386
15 changed files with 410 additions and 146 deletions
|
@ -154,31 +154,52 @@ Note: All <bool> fields default to false unless mentioned otherwise.
|
|||
|
||||
sidedef
|
||||
{
|
||||
scalex_top = <float>; // X scale for upper texture, Default = 1.0.
|
||||
scaley_top = <float>; // y scale for upper texture, Default = 1.0.
|
||||
scalex_mid = <float>; // X scale for mid texture, Default = 1.0.
|
||||
scaley_mid = <float>; // y scale for mid texture, Default = 1.0.
|
||||
scalex_bottom = <float>; // X scale for lower texture, Default = 1.0.
|
||||
scaley_bottom = <float>; // y scale for lower texture, Default = 1.0.
|
||||
offsetx_top = <float>; // X offset for upper texture, Default = 0.0.
|
||||
offsety_top = <float>; // y offset for upper texture, Default = 0.0.
|
||||
offsetx_mid = <float>; // X offset for mid texture, Default = 0.0.
|
||||
offsety_mid = <float>; // y offset for mid texture, Default = 0.0.
|
||||
offsetx_bottom = <float>; // X offset for lower texture, Default = 0.0.
|
||||
offsety_bottom = <float>; // y offset for lower texture, Default = 0.0.
|
||||
// When global texture offsets are used they will
|
||||
// be added on top of these values.
|
||||
light = <integer>; // This side's light level. Default is 0.
|
||||
lightabsolute = <bool>; // true = 'light' is an absolute value. Default is
|
||||
// relative to the owning sector's light level.
|
||||
lightfog = <bool>; // true = This side's relative lighting is used even in
|
||||
// foggy sectors. Default is to disable relative
|
||||
// lighting in foggy sectors.
|
||||
nofakecontrast = <bool>; // Disables use of fake contrast on this sidedef.
|
||||
smoothlighting = <bool>; // Use smooth fake contrast.
|
||||
clipmidtex = <bool>; // Side's mid textures are clipped to floor and ceiling.
|
||||
wrapmidtex = <bool>; // Side's mid textures are wrapped.
|
||||
nodecals = <bool>; // Disables decals on the sidedef.
|
||||
scalex_top = <float>; // X scale for upper texture, Default = 1.0.
|
||||
scaley_top = <float>; // y scale for upper texture, Default = 1.0.
|
||||
scalex_mid = <float>; // X scale for mid texture, Default = 1.0.
|
||||
scaley_mid = <float>; // y scale for mid texture, Default = 1.0.
|
||||
scalex_bottom = <float>; // X scale for lower texture, Default = 1.0.
|
||||
scaley_bottom = <float>; // y scale for lower texture, Default = 1.0.
|
||||
offsetx_top = <float>; // X offset for upper texture, Default = 0.0.
|
||||
offsety_top = <float>; // y offset for upper texture, Default = 0.0.
|
||||
offsetx_mid = <float>; // X offset for mid texture, Default = 0.0.
|
||||
offsety_mid = <float>; // y offset for mid texture, Default = 0.0.
|
||||
offsetx_bottom = <float>; // X offset for lower texture, Default = 0.0.
|
||||
offsety_bottom = <float>; // y offset for lower texture, Default = 0.0.
|
||||
// When global texture offsets are used they will
|
||||
// be added on top of these values.
|
||||
light = <integer>; // This side's light level. Default is 0.
|
||||
lightabsolute = <bool>; // true = 'light' is an absolute value. Default is
|
||||
// relative to the owning sector's light level.
|
||||
lightfog = <bool>; // true = This side's relative lighting is used even in
|
||||
// foggy sectors. Default is to disable relative
|
||||
// lighting in foggy sectors.
|
||||
nofakecontrast = <bool>; // Disables use of fake contrast on this sidedef.
|
||||
smoothlighting = <bool>; // Use smooth fake contrast.
|
||||
clipmidtex = <bool>; // Side's mid textures are clipped to floor and ceiling.
|
||||
wrapmidtex = <bool>; // Side's mid textures are wrapped.
|
||||
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
|
||||
|
|
|
@ -138,7 +138,6 @@ bool FGLRenderState::ApplyShader()
|
|||
activeShader->muLightParms.Set(mLightParms);
|
||||
activeShader->muFogColor.Set(mFogColor);
|
||||
activeShader->muObjectColor.Set(mObjectColor);
|
||||
activeShader->muObjectColor2.Set(mObjectColor2);
|
||||
activeShader->muDynLightColor.Set(mDynColor.vec);
|
||||
activeShader->muInterpolationFactor.Set(mInterpolationFactor);
|
||||
activeShader->muTimer.Set((double)(screen->FrameTime - firstFrame) * (double)mShaderTimer / 1000.);
|
||||
|
@ -151,6 +150,8 @@ bool FGLRenderState::ApplyShader()
|
|||
{
|
||||
activeShader->muGlowTopColor.Set(mGlowTop.vec);
|
||||
activeShader->muGlowBottomColor.Set(mGlowBottom.vec);
|
||||
activeShader->muGlowTopPlane.Set(mGlowTopPlane.vec);
|
||||
activeShader->muGlowBottomPlane.Set(mGlowBottomPlane.vec);
|
||||
activeShader->currentglowstate = 1;
|
||||
}
|
||||
else if (activeShader->currentglowstate)
|
||||
|
@ -160,10 +161,18 @@ bool FGLRenderState::ApplyShader()
|
|||
activeShader->muGlowBottomColor.Set(nulvec);
|
||||
activeShader->currentglowstate = 0;
|
||||
}
|
||||
if (mGlowEnabled || mObjectColor2.a != 0)
|
||||
|
||||
if (mGradientEnabled)
|
||||
{
|
||||
activeShader->muGlowTopPlane.Set(mGlowTopPlane.vec);
|
||||
activeShader->muGlowBottomPlane.Set(mGlowBottomPlane.vec);
|
||||
activeShader->muObjectColor2.Set(mObjectColor2);
|
||||
activeShader->muGradientTopPlane.Set(mGradientTopPlane.vec);
|
||||
activeShader->muGradientBottomPlane.Set(mGradientBottomPlane.vec);
|
||||
activeShader->currentgradientstate = 1;
|
||||
}
|
||||
else if (activeShader->currentgradientstate)
|
||||
{
|
||||
activeShader->muObjectColor2.Set(0);
|
||||
activeShader->currentgradientstate = 0;
|
||||
}
|
||||
|
||||
if (mSplitEnabled)
|
||||
|
|
|
@ -93,6 +93,9 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
|||
i_data += "uniform vec4 uGlowBottomPlane;\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 uSplitBottomPlane;\n";
|
||||
|
||||
|
@ -335,6 +338,8 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
|||
muGlowTopColor.Init(hShader, "uGlowTopColor");
|
||||
muGlowBottomPlane.Init(hShader, "uGlowBottomPlane");
|
||||
muGlowTopPlane.Init(hShader, "uGlowTopPlane");
|
||||
muGradientBottomPlane.Init(hShader, "uGradientBottomPlane");
|
||||
muGradientTopPlane.Init(hShader, "uGradientTopPlane");
|
||||
muSplitBottomPlane.Init(hShader, "uSplitBottomPlane");
|
||||
muSplitTopPlane.Init(hShader, "uSplitTopPlane");
|
||||
muInterpolationFactor.Init(hShader, "uInterpolationFactor");
|
||||
|
|
|
@ -249,6 +249,8 @@ class FShader
|
|||
FUniform4f muGlowTopColor;
|
||||
FUniform4f muGlowBottomPlane;
|
||||
FUniform4f muGlowTopPlane;
|
||||
FUniform4f muGradientBottomPlane;
|
||||
FUniform4f muGradientTopPlane;
|
||||
FUniform4f muSplitBottomPlane;
|
||||
FUniform4f muSplitTopPlane;
|
||||
FBufferedUniform1f muInterpolationFactor;
|
||||
|
@ -266,6 +268,7 @@ public:
|
|||
int fakevb_index;
|
||||
private:
|
||||
int currentglowstate = 0;
|
||||
int currentgradientstate = 0;
|
||||
int currentsplitstate = 0;
|
||||
int currentcliplinestate = 0;
|
||||
int currentfixedcolormap = 0;
|
||||
|
|
|
@ -127,6 +127,7 @@ protected:
|
|||
uint8_t mFogEnabled;
|
||||
uint8_t mTextureEnabled:1;
|
||||
uint8_t mGlowEnabled : 1;
|
||||
uint8_t mGradientEnabled : 1;
|
||||
uint8_t mBrightmapEnabled : 1;
|
||||
uint8_t mModelMatrixEnabled : 1;
|
||||
uint8_t mTextureMatrixEnabled : 1;
|
||||
|
@ -147,6 +148,7 @@ protected:
|
|||
FStateVec4 mColor;
|
||||
FStateVec4 mGlowTop, mGlowBottom;
|
||||
FStateVec4 mGlowTopPlane, mGlowBottomPlane;
|
||||
FStateVec4 mGradientTopPlane, mGradientBottomPlane;
|
||||
FStateVec4 mSplitTopPlane, mSplitBottomPlane;
|
||||
PalEntry mFogColor;
|
||||
PalEntry mObjectColor;
|
||||
|
@ -172,7 +174,7 @@ public:
|
|||
void Reset()
|
||||
{
|
||||
mTextureEnabled = true;
|
||||
mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
|
||||
mGradientEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
|
||||
mFogColor.d = -1;
|
||||
mTextureMode = -1;
|
||||
mDesaturation = 0;
|
||||
|
@ -201,6 +203,8 @@ public:
|
|||
mGlowBottom.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);
|
||||
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);
|
||||
mSplitBottomPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mDynColor.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
@ -290,6 +294,11 @@ public:
|
|||
mGlowEnabled = on;
|
||||
}
|
||||
|
||||
void EnableGradient(bool on)
|
||||
{
|
||||
mGradientEnabled = on;
|
||||
}
|
||||
|
||||
void EnableBrightmap(bool on)
|
||||
{
|
||||
mBrightmapEnabled = on;
|
||||
|
@ -324,18 +333,26 @@ public:
|
|||
|
||||
void SetGlowPlanes(const secplane_t &top, const secplane_t &bottom)
|
||||
{
|
||||
DVector3 tn = top.Normal();
|
||||
DVector3 bn = bottom.Normal();
|
||||
mGlowTopPlane.Set((float)tn.X, (float)tn.Y, (float)(1. / tn.Z), (float)top.fD());
|
||||
mGlowBottomPlane.Set((float)bn.X, (float)bn.Y, (float)(1. / bn.Z), (float)bottom.fD());
|
||||
auto &tn = top.Normal();
|
||||
auto &bn = bottom.Normal();
|
||||
mGlowTopPlane.Set((float)tn.X, (float)tn.Y, (float)top.negiC, (float)top.fD());
|
||||
mGlowBottomPlane.Set((float)bn.X, (float)bn.Y, (float)bottom.negiC, (float)bottom.fD());
|
||||
}
|
||||
|
||||
void SetGradientPlanes(const secplane_t &top, const secplane_t &bottom)
|
||||
{
|
||||
auto &tn = top.Normal();
|
||||
auto &bn = bottom.Normal();
|
||||
mGradientTopPlane.Set((float)tn.X, (float)tn.Y, (float)top.negiC, (float)top.fD());
|
||||
mGradientBottomPlane.Set((float)bn.X, (float)bn.Y, (float)bottom.negiC, (float)bottom.fD());
|
||||
}
|
||||
|
||||
void SetSplitPlanes(const secplane_t &top, const secplane_t &bottom)
|
||||
{
|
||||
DVector3 tn = top.Normal();
|
||||
DVector3 bn = bottom.Normal();
|
||||
mSplitTopPlane.Set((float)tn.X, (float)tn.Y, (float)(1. / tn.Z), (float)top.fD());
|
||||
mSplitBottomPlane.Set((float)bn.X, (float)bn.Y, (float)(1. / bn.Z), (float)bottom.fD());
|
||||
auto &tn = top.Normal();
|
||||
auto &bn = bottom.Normal();
|
||||
mSplitTopPlane.Set((float)tn.X, (float)tn.Y, (float)top.negiC, (float)top.fD());
|
||||
mSplitBottomPlane.Set((float)bn.X, (float)bn.Y, (float)bottom.negiC, (float)bottom.fD());
|
||||
}
|
||||
|
||||
void SetDynLight(float r, float g, float b)
|
||||
|
|
|
@ -130,6 +130,20 @@ void GLWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
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::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
|
||||
{
|
||||
int tmode = state.GetTextureMode();
|
||||
|
@ -139,8 +153,8 @@ void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
|
|||
{
|
||||
state.EnableGlow(true);
|
||||
state.SetGlowParams(topglowcolor, bottomglowcolor);
|
||||
state.SetGlowPlanes(frontsector->ceilingplane, frontsector->floorplane);
|
||||
}
|
||||
state.SetGlowPlanes(frontsector->ceilingplane, frontsector->floorplane);
|
||||
state.SetMaterial(gltexture, flags & 3, 0, -1);
|
||||
|
||||
if (type == RENDERWALL_M2SNF)
|
||||
|
@ -151,8 +165,41 @@ void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
|
|||
}
|
||||
state.SetFog(255, 0, di->isFullbrightScene(), nullptr, false);
|
||||
}
|
||||
state.SetObjectColor(seg->frontsector->SpecialColors[sector_t::walltop] | 0xff000000);
|
||||
state.SetObjectColor2(seg->frontsector->SpecialColors[sector_t::wallbottom] | 0xff000000);
|
||||
if (type != RENDERWALL_COLOR)
|
||||
{
|
||||
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);
|
||||
state.SetObjectColor(color1);
|
||||
state.SetObjectColor2(color2);
|
||||
if (color1 != color2)
|
||||
{
|
||||
// Do gradient setup only if there actually is a gradient.
|
||||
|
||||
state.EnableGradient(true);
|
||||
if ((tier.flags & side_t::part::ClampGradient) && backsector)
|
||||
{
|
||||
if (tierndx == side_t::top)
|
||||
{
|
||||
state.SetGradientPlanes(frontsector->ceilingplane, backsector->ceilingplane);
|
||||
}
|
||||
else if (tierndx == side_t::mid)
|
||||
{
|
||||
state.SetGradientPlanes(backsector->ceilingplane, backsector->floorplane);
|
||||
}
|
||||
else // side_t::bottom:
|
||||
{
|
||||
state.SetGradientPlanes(backsector->floorplane, frontsector->floorplane);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state.SetGradientPlanes(frontsector->ceilingplane, frontsector->floorplane);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float absalpha = fabsf(alpha);
|
||||
if (lightlist == nullptr)
|
||||
|
@ -174,7 +221,7 @@ void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
|
|||
|
||||
if (low1 < ztop[0] || low2 < ztop[1])
|
||||
{
|
||||
int thisll = (*lightlist)[i].caster != NULL ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel;
|
||||
int thisll = (*lightlist)[i].caster != nullptr ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel;
|
||||
FColormap thiscm;
|
||||
thiscm.FadeColor = Colormap.FadeColor;
|
||||
thiscm.FogDensity = Colormap.FogDensity;
|
||||
|
@ -193,6 +240,7 @@ void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
|
|||
state.SetObjectColor2(0);
|
||||
state.SetTextureMode(tmode);
|
||||
state.EnableGlow(false);
|
||||
state.EnableGradient(false);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -630,6 +630,26 @@ xx(hidden)
|
|||
xx(blocksight)
|
||||
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(ceilingplane_a)
|
||||
|
|
|
@ -105,6 +105,9 @@ FSerializer &Serialize(FSerializer &arc, const char *key, side_t::part &part, si
|
|||
("yscale", part.yScale, def->yScale)
|
||||
("texture", part.texture, def->texture)
|
||||
("interpolation", part.interpolation)
|
||||
("flags", part.flags, def->flags)
|
||||
("color1", part.SpecialColors[0], def->SpecialColors[0])
|
||||
("color2", part.SpecialColors[1], def->SpecialColors[1])
|
||||
.EndObject();
|
||||
}
|
||||
return arc;
|
||||
|
|
|
@ -878,17 +878,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)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(sector_t);
|
||||
|
|
160
src/p_setup.cpp
160
src/p_setup.cpp
|
@ -3632,7 +3632,7 @@ void P_FreeExtraLevelData()
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
||||
void P_SetupLevel(const char *lumpname, int position, bool newGame)
|
||||
{
|
||||
cycle_t times[20];
|
||||
#if 0
|
||||
|
@ -3686,13 +3686,13 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
players[consoleplayer].viewz = NO_VALUE;
|
||||
|
||||
// Make sure all sounds are stopped before Z_FreeTags.
|
||||
S_Start ();
|
||||
S_Start();
|
||||
|
||||
// [RH] clear out the mid-screen message
|
||||
C_MidPrint (NULL, NULL);
|
||||
C_MidPrint(NULL, NULL);
|
||||
|
||||
// Free all level data from the previous map
|
||||
P_FreeLevelData ();
|
||||
P_FreeLevelData();
|
||||
|
||||
MapData *map = P_OpenMapData(lumpname, true);
|
||||
if (map == NULL)
|
||||
|
@ -3724,7 +3724,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
uint8_t *mapdata = new uint8_t[map->Size(0)];
|
||||
map->Read(0, mapdata);
|
||||
times[0].Clock();
|
||||
buildmap = P_LoadBuildMap (mapdata, map->Size(0), &buildthings, &numbuildthings);
|
||||
buildmap = P_LoadBuildMap(mapdata, map->Size(0), &buildthings, &numbuildthings);
|
||||
times[0].Unclock();
|
||||
delete[] mapdata;
|
||||
}
|
||||
|
@ -3736,10 +3736,10 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
ForceNodeBuild = gennodes;
|
||||
|
||||
// [RH] Load in the BEHAVIOR lump
|
||||
FBehavior::StaticUnloadModules ();
|
||||
FBehavior::StaticUnloadModules();
|
||||
if (map->HasBehavior)
|
||||
{
|
||||
P_LoadBehavior (map);
|
||||
P_LoadBehavior(map);
|
||||
level.maptype = MAPTYPE_HEXEN;
|
||||
}
|
||||
else
|
||||
|
@ -3796,25 +3796,25 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
level.flags2 |= LEVEL2_DUMMYSWITCHES;
|
||||
}
|
||||
|
||||
FBehavior::StaticLoadDefaultModules ();
|
||||
FBehavior::StaticLoadDefaultModules();
|
||||
#ifndef NO_EDATA
|
||||
LoadMapinfoACSLump();
|
||||
#endif
|
||||
|
||||
|
||||
P_LoadStrifeConversations (map, lumpname);
|
||||
P_LoadStrifeConversations(map, lumpname);
|
||||
|
||||
FMissingTextureTracker missingtex;
|
||||
|
||||
if (!map->isText)
|
||||
{
|
||||
times[0].Clock();
|
||||
P_LoadVertexes (map);
|
||||
P_LoadVertexes(map);
|
||||
times[0].Unclock();
|
||||
|
||||
// Check for maps without any BSP data at all (e.g. SLIGE)
|
||||
times[1].Clock();
|
||||
P_LoadSectors (map, missingtex);
|
||||
P_LoadSectors(map, missingtex);
|
||||
times[1].Unclock();
|
||||
|
||||
times[2].Clock();
|
||||
|
@ -3822,23 +3822,23 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
|
||||
times[3].Clock();
|
||||
if (!map->HasBehavior)
|
||||
P_LoadLineDefs (map);
|
||||
P_LoadLineDefs(map);
|
||||
else
|
||||
P_LoadLineDefs2 (map); // [RH] Load Hexen-style linedefs
|
||||
P_LoadLineDefs2(map); // [RH] Load Hexen-style linedefs
|
||||
times[3].Unclock();
|
||||
|
||||
times[4].Clock();
|
||||
P_LoadSideDefs2 (map, missingtex);
|
||||
P_LoadSideDefs2(map, missingtex);
|
||||
times[4].Unclock();
|
||||
|
||||
times[5].Clock();
|
||||
P_FinishLoadingLineDefs ();
|
||||
P_FinishLoadingLineDefs();
|
||||
times[5].Unclock();
|
||||
|
||||
if (!map->HasBehavior)
|
||||
P_LoadThings (map);
|
||||
P_LoadThings(map);
|
||||
else
|
||||
P_LoadThings2 (map); // [RH] Load Hexen-style things
|
||||
P_LoadThings2(map); // [RH] Load Hexen-style things
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3850,7 +3850,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
SetCompatibilityParams(checksum);
|
||||
|
||||
times[6].Clock();
|
||||
P_LoopSidedefs (true);
|
||||
P_LoopSidedefs(true);
|
||||
times[6].Unclock();
|
||||
|
||||
linemap.Clear();
|
||||
|
@ -3869,36 +3869,36 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
{
|
||||
// Check for compressed nodes first, then uncompressed nodes
|
||||
FileReader *fr = nullptr;
|
||||
uint32_t id = MAKE_ID('X','x','X','x'), idcheck = 0, idcheck2 = 0, idcheck3 = 0, idcheck4 = 0, idcheck5 = 0, idcheck6 = 0;
|
||||
uint32_t id = MAKE_ID('X', 'x', 'X', 'x'), idcheck = 0, idcheck2 = 0, idcheck3 = 0, idcheck4 = 0, idcheck5 = 0, idcheck6 = 0;
|
||||
|
||||
if (map->Size(ML_ZNODES) != 0)
|
||||
{
|
||||
// Test normal nodes first
|
||||
fr = &map->Reader(ML_ZNODES);
|
||||
idcheck = MAKE_ID('Z','N','O','D');
|
||||
idcheck2 = MAKE_ID('X','N','O','D');
|
||||
idcheck = MAKE_ID('Z', 'N', 'O', 'D');
|
||||
idcheck2 = MAKE_ID('X', 'N', 'O', 'D');
|
||||
}
|
||||
else if (map->Size(ML_GLZNODES) != 0)
|
||||
{
|
||||
fr = &map->Reader(ML_GLZNODES);
|
||||
idcheck = MAKE_ID('Z','G','L','N');
|
||||
idcheck2 = MAKE_ID('Z','G','L','2');
|
||||
idcheck3 = MAKE_ID('Z','G','L','3');
|
||||
idcheck4 = MAKE_ID('X','G','L','N');
|
||||
idcheck5 = MAKE_ID('X','G','L','2');
|
||||
idcheck6 = MAKE_ID('X','G','L','3');
|
||||
idcheck = MAKE_ID('Z', 'G', 'L', 'N');
|
||||
idcheck2 = MAKE_ID('Z', 'G', 'L', '2');
|
||||
idcheck3 = MAKE_ID('Z', 'G', 'L', '3');
|
||||
idcheck4 = MAKE_ID('X', 'G', 'L', 'N');
|
||||
idcheck5 = MAKE_ID('X', 'G', 'L', '2');
|
||||
idcheck6 = MAKE_ID('X', 'G', 'L', '3');
|
||||
}
|
||||
|
||||
if (fr != nullptr && fr->isOpen()) fr->Read (&id, 4);
|
||||
if (fr != nullptr && fr->isOpen()) fr->Read(&id, 4);
|
||||
if (id != 0 && (id == idcheck || id == idcheck2 || id == idcheck3 || id == idcheck4 || id == idcheck5 || id == idcheck6))
|
||||
{
|
||||
try
|
||||
{
|
||||
P_LoadZNodes (*fr, id);
|
||||
P_LoadZNodes(*fr, id);
|
||||
}
|
||||
catch (CRecoverableError &error)
|
||||
{
|
||||
Printf ("Error loading nodes: %s\n", error.GetMessage());
|
||||
Printf("Error loading nodes: %s\n", error.GetMessage());
|
||||
|
||||
ForceNodeBuild = true;
|
||||
level.subsectors.Clear();
|
||||
|
@ -3915,29 +3915,29 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
if (!P_CheckV4Nodes(map))
|
||||
{
|
||||
times[7].Clock();
|
||||
P_LoadSubsectors<mapsubsector_t, mapseg_t> (map);
|
||||
P_LoadSubsectors<mapsubsector_t, mapseg_t>(map);
|
||||
times[7].Unclock();
|
||||
|
||||
times[8].Clock();
|
||||
if (!ForceNodeBuild) P_LoadNodes<mapnode_t, mapsubsector_t> (map);
|
||||
if (!ForceNodeBuild) P_LoadNodes<mapnode_t, mapsubsector_t>(map);
|
||||
times[8].Unclock();
|
||||
|
||||
times[9].Clock();
|
||||
if (!ForceNodeBuild) P_LoadSegs<mapseg_t> (map);
|
||||
if (!ForceNodeBuild) P_LoadSegs<mapseg_t>(map);
|
||||
times[9].Unclock();
|
||||
}
|
||||
else
|
||||
{
|
||||
times[7].Clock();
|
||||
P_LoadSubsectors<mapsubsector4_t, mapseg4_t> (map);
|
||||
P_LoadSubsectors<mapsubsector4_t, mapseg4_t>(map);
|
||||
times[7].Unclock();
|
||||
|
||||
times[8].Clock();
|
||||
if (!ForceNodeBuild) P_LoadNodes<mapnode4_t, mapsubsector4_t> (map);
|
||||
if (!ForceNodeBuild) P_LoadNodes<mapnode4_t, mapsubsector4_t>(map);
|
||||
times[8].Unclock();
|
||||
|
||||
times[9].Clock();
|
||||
if (!ForceNodeBuild) P_LoadSegs<mapseg4_t> (map);
|
||||
if (!ForceNodeBuild) P_LoadSegs<mapseg4_t>(map);
|
||||
times[9].Unclock();
|
||||
}
|
||||
}
|
||||
|
@ -3957,16 +3957,16 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
}
|
||||
else reloop = true;
|
||||
|
||||
uint64_t startTime=0, endTime=0;
|
||||
uint64_t startTime = 0, endTime = 0;
|
||||
|
||||
bool BuildGLNodes;
|
||||
if (ForceNodeBuild)
|
||||
{
|
||||
BuildGLNodes = RequireGLNodes || multiplayer || demoplayback || demorecording || genglnodes;
|
||||
|
||||
startTime = I_msTime ();
|
||||
startTime = I_msTime();
|
||||
TArray<FNodeBuilder::FPolyStart> polyspots, anchors;
|
||||
P_GetPolySpots (map, polyspots, anchors);
|
||||
P_GetPolySpots(map, polyspots, anchors);
|
||||
FNodeBuilder::FLevel leveldata =
|
||||
{
|
||||
&level.vertexes[0], (int)level.vertexes.Size(),
|
||||
|
@ -3974,14 +3974,14 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
&level.lines[0], (int)level.lines.Size(),
|
||||
0, 0, 0, 0
|
||||
};
|
||||
leveldata.FindMapBounds ();
|
||||
leveldata.FindMapBounds();
|
||||
// We need GL nodes if am_textured is on.
|
||||
// In case a sync critical game mode is started, also build GL nodes to avoid problems
|
||||
// if the different machines' am_textured setting differs.
|
||||
FNodeBuilder builder (leveldata, polyspots, anchors, BuildGLNodes);
|
||||
builder.Extract (level);
|
||||
endTime = I_msTime ();
|
||||
DPrintf (DMSG_NOTIFY, "BSP generation took %.3f sec (%d segs)\n", (endTime - startTime) * 0.001, level.segs.Size());
|
||||
FNodeBuilder builder(leveldata, polyspots, anchors, BuildGLNodes);
|
||||
builder.Extract(level);
|
||||
endTime = I_msTime();
|
||||
DPrintf(DMSG_NOTIFY, "BSP generation took %.3f sec (%d segs)\n", (endTime - startTime) * 0.001, level.segs.Size());
|
||||
oldvertextable = builder.GetOldVertexTable();
|
||||
reloop = true;
|
||||
}
|
||||
|
@ -3989,14 +3989,14 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
{
|
||||
BuildGLNodes = false;
|
||||
// Older ZDBSPs had problems with compressed sidedefs and assigned wrong sides to the segs if both sides were the same sidedef.
|
||||
for(auto &seg : level.segs)
|
||||
for (auto &seg : level.segs)
|
||||
{
|
||||
if (seg.backsector == seg.frontsector && seg.linedef)
|
||||
{
|
||||
double d1 = (seg.v1->fPos() - seg.linedef->v1->fPos()).LengthSquared();
|
||||
double d2 = (seg.v2->fPos() - seg.linedef->v1->fPos()).LengthSquared();
|
||||
|
||||
if (d2<d1) // backside
|
||||
if (d2 < d1) // backside
|
||||
{
|
||||
seg.sidedef = seg.linedef->sidedef[1];
|
||||
}
|
||||
|
@ -4023,22 +4023,22 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
}
|
||||
|
||||
// set the head node for gameplay purposes. If the separate gamenodes array is not empty, use that, otherwise use the render nodes.
|
||||
level.headgamenode = level.gamenodes.Size() > 0 ? &level.gamenodes[level.gamenodes.Size() - 1] : level.nodes.Size()? &level.nodes[level.nodes.Size() - 1] : nullptr;
|
||||
level.headgamenode = level.gamenodes.Size() > 0 ? &level.gamenodes[level.gamenodes.Size() - 1] : level.nodes.Size() ? &level.nodes[level.nodes.Size() - 1] : nullptr;
|
||||
|
||||
times[10].Clock();
|
||||
P_LoadBlockMap (map);
|
||||
P_LoadBlockMap(map);
|
||||
times[10].Unclock();
|
||||
|
||||
times[11].Clock();
|
||||
P_LoadReject (map, buildmap);
|
||||
P_LoadReject(map, buildmap);
|
||||
times[11].Unclock();
|
||||
|
||||
times[12].Clock();
|
||||
P_GroupLines (buildmap);
|
||||
P_GroupLines(buildmap);
|
||||
times[12].Unclock();
|
||||
|
||||
times[13].Clock();
|
||||
P_FloodZones ();
|
||||
P_FloodZones();
|
||||
times[13].Unclock();
|
||||
|
||||
if (hasglnodes)
|
||||
|
@ -4049,8 +4049,8 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
}
|
||||
|
||||
bodyqueslot = 0;
|
||||
// phares 8/10/98: Clear body queue so the corpses from previous games are
|
||||
// not assumed to be from this one.
|
||||
// phares 8/10/98: Clear body queue so the corpses from previous games are
|
||||
// not assumed to be from this one.
|
||||
|
||||
for (i = 0; i < BODYQUESIZE; i++)
|
||||
bodyque[i] = NULL;
|
||||
|
@ -4060,7 +4060,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
if (!buildmap)
|
||||
{
|
||||
// [RH] Spawn slope creating things first.
|
||||
P_SpawnSlopeMakers (&MapThingsConverted[0], &MapThingsConverted[MapThingsConverted.Size()], oldvertextable);
|
||||
P_SpawnSlopeMakers(&MapThingsConverted[0], &MapThingsConverted[MapThingsConverted.Size()], oldvertextable);
|
||||
P_CopySlopes();
|
||||
|
||||
// Spawn 3d floors - must be done before spawning things so it can't be done in P_SpawnSpecials
|
||||
|
@ -4078,7 +4078,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
|
||||
times[15].Clock();
|
||||
if (!map->HasBehavior && !map->isText)
|
||||
P_TranslateTeleportThings (); // [RH] Assign teleport destination TIDs
|
||||
P_TranslateTeleportThings(); // [RH] Assign teleport destination TIDs
|
||||
times[15].Unclock();
|
||||
}
|
||||
#if 0 // There is no such thing as a build map.
|
||||
|
@ -4086,7 +4086,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
{
|
||||
for (i = 0; i < numbuildthings; ++i)
|
||||
{
|
||||
SpawnMapThing (i, &buildthings[i], 0);
|
||||
SpawnMapThing(i, &buildthings[i], 0);
|
||||
}
|
||||
delete[] buildthings;
|
||||
}
|
||||
|
@ -4098,7 +4098,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
}
|
||||
|
||||
// set up world state
|
||||
P_SpawnSpecials ();
|
||||
P_SpawnSpecials();
|
||||
|
||||
// disable reflective planes on sloped sectors.
|
||||
for (auto &sec : level.sectors)
|
||||
|
@ -4121,8 +4121,8 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
P_InitHealthGroups();
|
||||
|
||||
times[16].Clock();
|
||||
if (reloop) P_LoopSidedefs (false);
|
||||
PO_Init (); // Initialize the polyobjs
|
||||
if (reloop) P_LoopSidedefs(false);
|
||||
PO_Init(); // Initialize the polyobjs
|
||||
if (!level.IsReentering())
|
||||
P_FinalizePortals(); // finalize line portals after polyobjects have been initialized. This info is needed for properly flagging them.
|
||||
times[16].Unclock();
|
||||
|
@ -4134,12 +4134,12 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
// if deathmatch, randomly spawn the active players
|
||||
if (deathmatch)
|
||||
{
|
||||
for (i=0 ; i<MAXPLAYERS ; i++)
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
players[i].mo = NULL;
|
||||
G_DeathMatchSpawnPlayer (i);
|
||||
G_DeathMatchSpawnPlayer(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4159,7 +4159,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
|
||||
// [SP] move unfriendly players around
|
||||
// horribly hacky - yes, this needs rewritten.
|
||||
if (level.deathmatchstarts.Size () > 0)
|
||||
if (level.deathmatchstarts.Size() > 0)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
|
@ -4168,7 +4168,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
if (!(players[i].mo->flags & MF_FRIENDLY))
|
||||
{
|
||||
AActor * oldSpawn = players[i].mo;
|
||||
G_DeathMatchSpawnPlayer (i);
|
||||
G_DeathMatchSpawnPlayer(i);
|
||||
oldSpawn->Destroy();
|
||||
}
|
||||
}
|
||||
|
@ -4182,11 +4182,11 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
TThinkerIterator<AActor> it;
|
||||
AActor * mo;
|
||||
|
||||
while ((mo=it.Next()))
|
||||
while ((mo = it.Next()))
|
||||
{
|
||||
if (mo->flags & MF_COUNTKILL)
|
||||
{
|
||||
if (mo->Sector->damageamount > 0 && (mo->Sector->Flags & (SECF_ENDGODMODE|SECF_ENDLEVEL)) == (SECF_ENDGODMODE|SECF_ENDLEVEL))
|
||||
if (mo->Sector->damageamount > 0 && (mo->Sector->Flags & (SECF_ENDGODMODE | SECF_ENDLEVEL)) == (SECF_ENDGODMODE | SECF_ENDLEVEL))
|
||||
{
|
||||
mo->ClearCounters();
|
||||
}
|
||||
|
@ -4202,20 +4202,20 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
R_OldBlend = 0xffffffff;
|
||||
|
||||
// [RH] Remove all particles
|
||||
P_ClearParticles ();
|
||||
P_ClearParticles();
|
||||
|
||||
times[17].Clock();
|
||||
// preload graphics and sounds
|
||||
if (precache)
|
||||
{
|
||||
P_PrecacheLevel ();
|
||||
S_PrecacheLevel ();
|
||||
P_PrecacheLevel();
|
||||
S_PrecacheLevel();
|
||||
}
|
||||
times[17].Unclock();
|
||||
|
||||
if (deathmatch)
|
||||
{
|
||||
AnnounceGameStart ();
|
||||
AnnounceGameStart();
|
||||
}
|
||||
|
||||
// This check was previously done at run time each time the heightsec was checked.
|
||||
|
@ -4235,12 +4235,12 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
}
|
||||
}
|
||||
|
||||
P_ResetSightCounters (true);
|
||||
P_ResetSightCounters(true);
|
||||
//Printf ("free memory: 0x%x\n", Z_FreeMemory());
|
||||
|
||||
if (showloadtimes)
|
||||
{
|
||||
Printf ("---Total load times---\n");
|
||||
Printf("---Total load times---\n");
|
||||
for (i = 0; i < 18; ++i)
|
||||
{
|
||||
static const char *timenames[] =
|
||||
|
@ -4264,7 +4264,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
"init polys",
|
||||
"precache"
|
||||
};
|
||||
Printf ("Time%3d:%9.4f ms (%s)\n", i, times[i].TimeMS(), timenames[i]);
|
||||
Printf("Time%3d:%9.4f ms (%s)\n", i, times[i].TimeMS(), timenames[i]);
|
||||
}
|
||||
}
|
||||
MapThingsConverted.Clear();
|
||||
|
@ -4280,10 +4280,22 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
memcpy(&level.loadlines[0], &level.lines[0], level.lines.Size() * sizeof(level.lines[0]));
|
||||
level.loadsides.Resize(level.sides.Size());
|
||||
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
|
||||
//
|
||||
|
|
|
@ -1223,6 +1223,7 @@ public:
|
|||
{
|
||||
FName key = ParseKey();
|
||||
switch(key)
|
||||
|
||||
{
|
||||
case NAME_Offsetx:
|
||||
texOfs[0] = CheckInt(key);
|
||||
|
@ -1334,6 +1335,79 @@ public:
|
|||
Flag(sd->Flags, WALLF_NOAUTODECALS, key);
|
||||
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:
|
||||
break;
|
||||
|
||||
|
|
|
@ -88,7 +88,6 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
|
|||
wall.Line = line->linedef;
|
||||
wall.Side = line->sidedef;
|
||||
wall.LineSegLine = line->linedef;
|
||||
wall.Colormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
|
||||
wall.Masked = false;
|
||||
wall.SubsectorDepth = subsectorDepth;
|
||||
wall.StencilValue = stencilValue;
|
||||
|
@ -102,6 +101,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
|
|||
wall.TopTexZ = topTexZ;
|
||||
wall.BottomTexZ = bottomTexZ;
|
||||
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.Polyportal = polyportal;
|
||||
wall.Render(thread);
|
||||
|
@ -140,6 +140,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
|
|||
wall.TopTexZ = topTexZ;
|
||||
wall.BottomTexZ = MIN(MIN(backceilz1, frontceilz1), MIN(backceilz2, frontceilz2));
|
||||
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.Render(thread);
|
||||
}
|
||||
|
@ -152,6 +153,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
|
|||
wall.UnpeggedCeil1 = topceilz1;
|
||||
wall.UnpeggedCeil2 = topceilz2;
|
||||
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.Render(thread);
|
||||
}
|
||||
|
@ -162,6 +164,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
|
|||
wall.TopTexZ = MAX(middleceilz1, middleceilz2);
|
||||
wall.BottomTexZ = MIN(middlefloorz1, middlefloorz2);
|
||||
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.Masked = true;
|
||||
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.Line = fakeFloor->master;
|
||||
wall.Side = fakeFloor->master->sidedef[0];
|
||||
wall.Colormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
|
||||
wall.SectorLightLevel = frontsector->lightlevel;
|
||||
wall.Additive = !!(fakeFloor->flags & FF_ADDITIVETRANS);
|
||||
if (!wall.Additive && fakeFloor->alpha == 255)
|
||||
|
@ -231,6 +233,7 @@ void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, seg_t *line, se
|
|||
wall.TopTexZ = topTexZ;
|
||||
wall.BottomTexZ = bottomTexZ;
|
||||
wall.Wallpart = side_t::mid;
|
||||
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
|
||||
if (fakeFloor->flags & FF_UPPERTEXTURE)
|
||||
wall.Texture = GetTexture(line->linedef, line->sidedef, side_t::top);
|
||||
else if (fakeFloor->flags & FF_LOWERTEXTURE)
|
||||
|
|
54
src/r_defs.h
54
src/r_defs.h
|
@ -325,7 +325,7 @@ public:
|
|||
return !normal.XY().isZero();
|
||||
}
|
||||
|
||||
DVector3 Normal() const
|
||||
const DVector3 &Normal() const
|
||||
{
|
||||
return normal;
|
||||
}
|
||||
|
@ -645,8 +645,6 @@ public:
|
|||
void SetColor(int r, int g, int b, int desat);
|
||||
void SetFade(int r, int g, int b);
|
||||
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;
|
||||
int GetFloorLight () const;
|
||||
int GetCeilingLight () const;
|
||||
|
@ -917,6 +915,17 @@ public:
|
|||
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 PortalBlocksSight(int plane);
|
||||
inline bool PortalBlocksMovement(int plane);
|
||||
|
@ -1138,16 +1147,31 @@ struct side_t
|
|||
{
|
||||
top=0,
|
||||
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
|
||||
{
|
||||
enum EPartFlags
|
||||
{
|
||||
NoGradient = 1,
|
||||
FlipGradient = 2,
|
||||
ClampGradient = 4,
|
||||
UseOwnColors = 8,
|
||||
};
|
||||
double xOffset;
|
||||
double yOffset;
|
||||
double xScale;
|
||||
double yScale;
|
||||
TObjPtr<DInterpolation*> interpolation;
|
||||
FTextureID texture;
|
||||
int flags;
|
||||
PalEntry SpecialColors[2];
|
||||
|
||||
void InitFrom(const part &other)
|
||||
{
|
||||
|
@ -1270,6 +1294,28 @@ struct side_t
|
|||
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);
|
||||
void StopInterpolation(int position);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
in vec4 pixelpos;
|
||||
in vec3 glowdist;
|
||||
in vec3 gradientdist;
|
||||
|
||||
in vec4 vWorldNormal;
|
||||
in vec4 vEyeNormal;
|
||||
|
@ -111,7 +112,7 @@ vec4 getTexel(vec2 st)
|
|||
|
||||
}
|
||||
if (uObjectColor2.a == 0.0) texel *= uObjectColor;
|
||||
else texel *= mix(uObjectColor, uObjectColor2, glowdist.z);
|
||||
else texel *= mix(uObjectColor, uObjectColor2, gradientdist.z);
|
||||
|
||||
return desaturate(texel);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ layout(location = 3) in vec4 aVertex2;
|
|||
layout(location = 4) in vec4 aNormal;
|
||||
out vec4 pixelpos;
|
||||
out vec3 glowdist;
|
||||
out vec3 gradientdist;
|
||||
|
||||
out vec4 vWorldNormal;
|
||||
out vec4 vEyeNormal;
|
||||
|
@ -37,16 +38,28 @@ void main()
|
|||
pixelpos.xyz = worldcoord.xyz;
|
||||
pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w;
|
||||
|
||||
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.y = worldcoord.y - bottomatpoint;
|
||||
glowdist.z = clamp(glowdist.x / (topatpoint - bottomatpoint), 0.0, 1.0);
|
||||
if (uGlowTopColor.a > 0 || uGlowBottomColor.a > 0)
|
||||
{
|
||||
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.y = worldcoord.y - bottomatpoint;
|
||||
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)
|
||||
{
|
||||
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[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);
|
||||
}
|
||||
|
||||
vWorldNormal = NormalModelMatrix * vec4(normalize(aNormal.xyz), 1.0);
|
||||
|
|
Loading…
Reference in a new issue