From f2dcff43868b2cf34f7b69e677a32b76724b02b3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 11 Nov 2018 16:04:05 +0100 Subject: [PATCH] - 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. --- specs/udmf_zdoom.txt | 71 +++++++---- src/gl/renderer/gl_renderstate.cpp | 17 ++- src/gl/shaders/gl_shader.cpp | 5 + src/gl/shaders/gl_shader.h | 3 + src/hwrenderer/scene/hw_renderstate.h | 35 ++++-- src/hwrenderer/scene/hw_walls.cpp | 56 ++++++++- src/namedef.h | 20 +++ src/p_saveg.cpp | 3 + src/p_sectors.cpp | 11 -- src/p_setup.cpp | 170 ++++++++++++++------------ src/p_udmf.cpp | 74 +++++++++++ src/polyrenderer/scene/poly_wall.cpp | 7 +- src/r_defs.h | 54 +++++++- wadsrc/static/shaders/glsl/main.fp | 3 +- wadsrc/static/shaders/glsl/main.vp | 27 ++-- 15 files changed, 410 insertions(+), 146 deletions(-) diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index e26044dc6c..43722d0fe5 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -154,31 +154,52 @@ Note: All fields default to false unless mentioned otherwise. sidedef { - scalex_top = ; // X scale for upper texture, Default = 1.0. - scaley_top = ; // y scale for upper texture, Default = 1.0. - scalex_mid = ; // X scale for mid texture, Default = 1.0. - scaley_mid = ; // y scale for mid texture, Default = 1.0. - scalex_bottom = ; // X scale for lower texture, Default = 1.0. - scaley_bottom = ; // y scale for lower texture, Default = 1.0. - offsetx_top = ; // X offset for upper texture, Default = 0.0. - offsety_top = ; // y offset for upper texture, Default = 0.0. - offsetx_mid = ; // X offset for mid texture, Default = 0.0. - offsety_mid = ; // y offset for mid texture, Default = 0.0. - offsetx_bottom = ; // X offset for lower texture, Default = 0.0. - offsety_bottom = ; // y offset for lower texture, Default = 0.0. - // When global texture offsets are used they will - // be added on top of these values. - light = ; // This side's light level. Default is 0. - lightabsolute = ; // true = 'light' is an absolute value. Default is - // relative to the owning sector's light level. - lightfog = ; // true = This side's relative lighting is used even in - // foggy sectors. Default is to disable relative - // lighting in foggy sectors. - nofakecontrast = ; // Disables use of fake contrast on this sidedef. - smoothlighting = ; // Use smooth fake contrast. - clipmidtex = ; // Side's mid textures are clipped to floor and ceiling. - wrapmidtex = ; // Side's mid textures are wrapped. - nodecals = ; // Disables decals on the sidedef. + scalex_top = ; // X scale for upper texture, Default = 1.0. + scaley_top = ; // y scale for upper texture, Default = 1.0. + scalex_mid = ; // X scale for mid texture, Default = 1.0. + scaley_mid = ; // y scale for mid texture, Default = 1.0. + scalex_bottom = ; // X scale for lower texture, Default = 1.0. + scaley_bottom = ; // y scale for lower texture, Default = 1.0. + offsetx_top = ; // X offset for upper texture, Default = 0.0. + offsety_top = ; // y offset for upper texture, Default = 0.0. + offsetx_mid = ; // X offset for mid texture, Default = 0.0. + offsety_mid = ; // y offset for mid texture, Default = 0.0. + offsetx_bottom = ; // X offset for lower texture, Default = 0.0. + offsety_bottom = ; // y offset for lower texture, Default = 0.0. + // When global texture offsets are used they will + // be added on top of these values. + light = ; // This side's light level. Default is 0. + lightabsolute = ; // true = 'light' is an absolute value. Default is + // relative to the owning sector's light level. + lightfog = ; // true = This side's relative lighting is used even in + // foggy sectors. Default is to disable relative + // lighting in foggy sectors. + nofakecontrast = ; // Disables use of fake contrast on this sidedef. + smoothlighting = ; // Use smooth fake contrast. + clipmidtex = ; // Side's mid textures are clipped to floor and ceiling. + wrapmidtex = ; // Side's mid textures are wrapped. + nodecals = ; // Disables decals on the sidedef. + + nogradient_top = ; // disables color gradient on upper tier. (Hardware rendering only.) + flipgradient_top = ; // flips gradient colors on upper tier. (Hardware rendering only.) + clampgradient_top = ; // clamps gradient on upper tier to actual bounds (default is the entire front sector height, hardware rendering only.) + useowncolors_top = ; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector. + uppercolor_top = ; // Material color of the top of the upper tier. + lowercolor_top = ; // Material color of the bottom of the upper tier. (Hardware rendering only.) + + nogradient_mid = ; // disables color gradient on middle tier. (Hardware rendering only.) + flipgradient_mid = ; // flips gradient colors on middle tier. (Hardware rendering only.) + clampgradient_mid = ; // clamps gradient on middle tier to actual bounds (default is the entire front sector height, hardware rendering only.) + useowncolors_mid = ; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector. + uppercolor_mid = ; // Material color of the top of the middle tier. + lowercolor_mid = ; // Material color of the bottom of the middle tier. (Hardware rendering only.) + + nogradient_bottom = ; // disables color gradient on lower tier. (Hardware rendering only.) + flipgradient_bottom = ; // flips gradient colors on lower tier. (Hardware rendering only.) + clampgradient_bottom = ;// clamps gradient on lower tier to actual bounds (default is the entire front sector height, hardware rendering only.) + useowncolors_bottom = ; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector. + uppercolor_bottom = ; // Material color of the top of the lower tier. + lowercolor_bottom = ; // Material color of the bottom of the lower tier. (Hardware rendering only.) } sector diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 1bfed5fc64..76e8ba892e 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -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) diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index d4352dcb71..b31e9532fe 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -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"); diff --git a/src/gl/shaders/gl_shader.h b/src/gl/shaders/gl_shader.h index 732b5eaafa..cc1dece32a 100644 --- a/src/gl/shaders/gl_shader.h +++ b/src/gl/shaders/gl_shader.h @@ -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; diff --git a/src/hwrenderer/scene/hw_renderstate.h b/src/hwrenderer/scene/hw_renderstate.h index 22cabc4c61..66f7ccff3f 100644 --- a/src/hwrenderer/scene/hw_renderstate.h +++ b/src/hwrenderer/scene/hw_renderstate.h @@ -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) diff --git a/src/hwrenderer/scene/hw_walls.cpp b/src/hwrenderer/scene/hw_walls.cpp index f8455c2459..0622553f75 100644 --- a/src/hwrenderer/scene/hw_walls.cpp +++ b/src/hwrenderer/scene/hw_walls.cpp @@ -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); } //========================================================================== diff --git a/src/namedef.h b/src/namedef.h index ecac82b56a..5744ef4869 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -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) diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 53f4959a25..a8dff68680 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -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; diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index be86c87ef3..dd0eb882cc 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -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); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 8f456c024c..b0004b795f 100644 --- a/src/p_setup.cpp +++ b/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 @@ -3662,7 +3662,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame) level.SetMusicVolume(level.MusicVolume); for (i = 0; i < MAXPLAYERS; ++i) { - players[i].killcount = players[i].secretcount + players[i].killcount = players[i].secretcount = players[i].itemcount = 0; } } @@ -3683,16 +3683,16 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame) translationtables[TRANSLATION_LevelScripted].Clear(); // Initial height of PointOfView will be set by player think. - players[consoleplayer].viewz = NO_VALUE; + 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 @@ -3756,7 +3756,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame) { // Has the user overridden the game's default translator with a commandline parameter? translator = Args->CheckValue("-xlat"); - if (translator == NULL) + if (translator == NULL) { // Use the game's default. translator = gameinfo.translator.GetChars(); @@ -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 (map); + P_LoadSubsectors(map); times[7].Unclock(); times[8].Clock(); - if (!ForceNodeBuild) P_LoadNodes (map); + if (!ForceNodeBuild) P_LoadNodes(map); times[8].Unclock(); times[9].Clock(); - if (!ForceNodeBuild) P_LoadSegs (map); + if (!ForceNodeBuild) P_LoadSegs(map); times[9].Unclock(); } else { times[7].Clock(); - P_LoadSubsectors (map); + P_LoadSubsectors(map); times[7].Unclock(); times[8].Clock(); - if (!ForceNodeBuild) P_LoadNodes (map); + if (!ForceNodeBuild) P_LoadNodes(map); times[8].Unclock(); times[9].Clock(); - if (!ForceNodeBuild) P_LoadSegs (map); + if (!ForceNodeBuild) P_LoadSegs(map); times[9].Unclock(); } } @@ -3948,7 +3948,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame) // If loading the regular nodes failed try GL nodes before considering a rebuild if (ForceNodeBuild) { - if (P_LoadGLNodes(map)) + if (P_LoadGLNodes(map)) { ForceNodeBuild = false; reloop = true; @@ -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 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 (d2sidedef[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 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 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 // diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index e0bccff7d1..6bacd4229e 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -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; diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index b7872724bd..3ba2e9f56e 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -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) diff --git a/src/r_defs.h b/src/r_defs.h index cb394cd410..ad128c4dc8 100644 --- a/src/r_defs.h +++ b/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 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); diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index dd082e6146..77855a85a6 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -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); } diff --git a/wadsrc/static/shaders/glsl/main.vp b/wadsrc/static/shaders/glsl/main.vp index 0be91afb8a..dccbb77c00 100644 --- a/wadsrc/static/shaders/glsl/main.vp +++ b/wadsrc/static/shaders/glsl/main.vp @@ -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);