From 13c6d169058ca5812d175be908e9181b09894c26 Mon Sep 17 00:00:00 2001
From: ZZYZX <zzyzx@virtual>
Date: Sat, 28 Jan 2017 01:12:42 +0200
Subject: [PATCH 01/11] Fixed: compile-time error in vararg function call would
 result in a crash.

---
 src/scripting/codegeneration/codegen.cpp | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp
index d090fa6e4..8fd95c411 100644
--- a/src/scripting/codegeneration/codegen.cpp
+++ b/src/scripting/codegeneration/codegen.cpp
@@ -8202,14 +8202,16 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
 			{
 				// only cast implicit-string types for vararg, leave everything else as-is
 				// this was outright copypasted from FxFormat
-				ArgList[i] = ArgList[i]->Resolve(ctx);
-				if (ArgList[i]->ValueType == TypeName ||
-					ArgList[i]->ValueType == TypeSound)
+				x = ArgList[i]->Resolve(ctx);
+				if (x)
 				{
-					x = new FxStringCast(ArgList[i]);
-					x = x->Resolve(ctx);
+					if (x->ValueType == TypeName ||
+						x->ValueType == TypeSound)
+					{
+						x = new FxStringCast(ArgList[i]);
+						x = x->Resolve(ctx);
+					}
 				}
-				else x = ArgList[i];
 			}
 			else if (!(flag & (VARF_Ref|VARF_Out)))
 			{

From c923f8c5e108138f69470724dd21d8655c8871f2 Mon Sep 17 00:00:00 2001
From: Rachael Alexanderson <eruanna@drdteam.org>
Date: Sat, 28 Jan 2017 00:13:27 -0500
Subject: [PATCH 02/11] - fixed: If GLRenderer is uninitialized (i.e. using
 software renderer, or during startup), gl_paltonemap_* CVARs would crash the
 game.

---
 src/gl/renderer/gl_postprocess.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp
index c504088f4..72121d338 100644
--- a/src/gl/renderer/gl_postprocess.cpp
+++ b/src/gl/renderer/gl_postprocess.cpp
@@ -135,12 +135,14 @@ CUSTOM_CVAR(Float, gl_ssao_exponent, 1.8f, 0)
 
 CUSTOM_CVAR(Float, gl_paltonemap_powtable, 2.0f, CVAR_ARCHIVE | CVAR_NOINITCALL)
 {
-	GLRenderer->ClearTonemapPalette();
+	if (GLRenderer)
+		GLRenderer->ClearTonemapPalette();
 }
 
 CUSTOM_CVAR(Bool, gl_paltonemap_reverselookup, true, CVAR_ARCHIVE | CVAR_NOINITCALL)
 {
-	GLRenderer->ClearTonemapPalette();
+	if (GLRenderer)
+		GLRenderer->ClearTonemapPalette();
 }
 
 

From dd03bb1fcb72eb06012775fe66b7a553982fd80c Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Sat, 28 Jan 2017 12:20:18 +0100
Subject: [PATCH 03/11] - made r_fullbrightignoresectorcolor a MAPINFO option,
 so far only working on the software renderer. GL still needs a few changes to
 handle it correctly.

---
 src/g_level.cpp                    | 15 +++++++++++++++
 src/g_level.h                      |  1 +
 src/g_levellocals.h                |  1 +
 src/g_mapinfo.cpp                  |  2 ++
 src/gl/renderer/gl_renderstate.cpp |  4 ++--
 src/r_bsp.cpp                      |  5 ++---
 src/r_main.cpp                     |  5 ++---
 src/r_segs.cpp                     | 12 ++++++------
 src/r_things.cpp                   | 17 ++++++++---------
 src/r_utility.cpp                  |  5 +++++
 wadsrc/static/language.enu         |  2 +-
 wadsrc/static/menudef.txt          |  9 ++++++++-
 12 files changed, 53 insertions(+), 25 deletions(-)

diff --git a/src/g_level.cpp b/src/g_level.cpp
index a71b481c9..8b67c9107 100644
--- a/src/g_level.cpp
+++ b/src/g_level.cpp
@@ -101,6 +101,7 @@ EXTERN_CVAR (Float, sv_gravity)
 EXTERN_CVAR (Float, sv_aircontrol)
 EXTERN_CVAR (Int, disableautosave)
 EXTERN_CVAR (String, playerclass)
+EXTERN_CVAR(Int, r_preservesectorcolor)
 
 #define SNAP_ID			MAKE_ID('s','n','A','p')
 #define DSNP_ID			MAKE_ID('d','s','N','p')
@@ -1487,6 +1488,20 @@ bool FLevelLocals::IsFreelookAllowed() const
 //
 //==========================================================================
 
+bool FLevelLocals::PreserveSectorColor() const
+{
+	if (r_preservesectorcolor == 0)
+		return false;
+	if (r_preservesectorcolor == 1)
+		return true;
+	return !!(level.flags3 & LEVEL3_PRESERVESECTORCOLOR);
+}
+
+//==========================================================================
+//
+//
+//==========================================================================
+
 FString CalcMapName (int episode, int level)
 {
 	FString lumpname;
diff --git a/src/g_level.h b/src/g_level.h
index 1fadcee3a..270cf54f0 100644
--- a/src/g_level.h
+++ b/src/g_level.h
@@ -223,6 +223,7 @@ enum ELevelFlags : unsigned int
 	
 	// More flags!
 	LEVEL3_FORCEFAKECONTRAST	= 0x00000001,	// forces fake contrast even with fog enabled
+	LEVEL3_PRESERVESECTORCOLOR	= 0x00000002,
 };
 
 
diff --git a/src/g_levellocals.h b/src/g_levellocals.h
index 357e2e154..0afac37ad 100644
--- a/src/g_levellocals.h
+++ b/src/g_levellocals.h
@@ -79,6 +79,7 @@ struct FLevelLocals
 	bool		IsJumpingAllowed() const;
 	bool		IsCrouchingAllowed() const;
 	bool		IsFreelookAllowed() const;
+	bool		PreserveSectorColor() const;
 };
 
 extern FLevelLocals level;
diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp
index bb641b23b..3f8e50027 100644
--- a/src/g_mapinfo.cpp
+++ b/src/g_mapinfo.cpp
@@ -1282,6 +1282,8 @@ MapFlagHandlers[] =
 	{ "unfreezesingleplayerconversations",MITYPE_SETFLAG2,	LEVEL2_CONV_SINGLE_UNFREEZE, 0 },
 	{ "spawnwithweaponraised",			MITYPE_SETFLAG2,	LEVEL2_PRERAISEWEAPON, 0 },
 	{ "forcefakecontrast",				MITYPE_SETFLAG3,	LEVEL3_FORCEFAKECONTRAST, 0 },
+	{ "preservesectorcolor",			MITYPE_SETFLAG3,	LEVEL3_PRESERVESECTORCOLOR, 0 },
+	{ "nopreservesectorcolor",			MITYPE_CLRFLAG3,	LEVEL3_PRESERVESECTORCOLOR, 0 },
 	{ "nobotnodes",						MITYPE_IGNORE,	0, 0 },		// Skulltag option: nobotnodes
 	{ "compat_shorttex",				MITYPE_COMPATFLAG, COMPATF_SHORTTEX, 0 },
 	{ "compat_stairs",					MITYPE_COMPATFLAG, COMPATF_STAIRINDEX, 0 },
diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp
index 429f69c34..04a53d67d 100644
--- a/src/gl/renderer/gl_renderstate.cpp
+++ b/src/gl/renderer/gl_renderstate.cpp
@@ -141,9 +141,10 @@ bool FRenderState::ApplyShader()
 			fogset = -gl_fogmode;
 		}
 	}
+	glVertexAttrib4fv(VATTR_NORMAL, mNormal.vec);
 
 	glVertexAttrib4fv(VATTR_COLOR, mColor.vec);
-	glVertexAttrib4fv(VATTR_NORMAL, mNormal.vec);
+	activeShader->muObjectColor.Set(mObjectColor);
 
 	activeShader->muDesaturation.Set(mDesaturation / 255.f);
 	activeShader->muFogEnabled.Set(fogset);
@@ -152,7 +153,6 @@ bool FRenderState::ApplyShader()
 	activeShader->muCameraPos.Set(mCameraPos.vec);
 	activeShader->muLightParms.Set(mLightParms);
 	activeShader->muFogColor.Set(mFogColor);
-	activeShader->muObjectColor.Set(mObjectColor);
 	activeShader->muDynLightColor.Set(mDynColor.vec);
 	activeShader->muInterpolationFactor.Set(mInterpolationFactor);
 	activeShader->muClipHeight.Set(mClipHeight);
diff --git a/src/r_bsp.cpp b/src/r_bsp.cpp
index 14a2f153f..a28b63d4a 100644
--- a/src/r_bsp.cpp
+++ b/src/r_bsp.cpp
@@ -54,7 +54,6 @@
 #include "g_levellocals.h"
 
 CVAR (Bool, r_drawflat, false, 0)		// [RH] Don't texture segs?
-EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
 
 namespace swrenderer
 {
@@ -1109,7 +1108,7 @@ void R_Subsector (subsector_t *sub)
 	}
 	else
 	{
-		basecolormap = (r_fullbrightignoresectorcolor && fixedlightlev >= 0) ? &FullNormalLight : frontsector->ColorMap;
+		basecolormap = (!level.PreserveSectorColor() && fixedlightlev >= 0) ? &FullNormalLight : frontsector->ColorMap;
 	}
 
 	portal = frontsector->ValidatePortal(sector_t::ceiling);
@@ -1143,7 +1142,7 @@ void R_Subsector (subsector_t *sub)
 	}
 	else
 	{
-		basecolormap = (r_fullbrightignoresectorcolor && fixedlightlev >= 0) ? &FullNormalLight : frontsector->ColorMap;
+		basecolormap = (!level.PreserveSectorColor() && fixedlightlev >= 0) ? &FullNormalLight : frontsector->ColorMap;
 	}
 
 	// killough 3/7/98: Add (x,y) offsets to flats, add deep water check
diff --git a/src/r_main.cpp b/src/r_main.cpp
index 7030339c7..8907888f5 100644
--- a/src/r_main.cpp
+++ b/src/r_main.cpp
@@ -59,6 +59,7 @@
 #include "r_data/colormaps.h"
 #include "p_maputl.h"
 #include "r_thread.h"
+#include "g_levellocals.h"
 
 CVAR (String, r_viewsize, "", CVAR_NOSET)
 CVAR (Bool, r_shadercolormaps, true, CVAR_ARCHIVE)
@@ -78,8 +79,6 @@ CUSTOM_CVAR (Int, r_columnmethod, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
 CVAR(Int, r_portal_recursions, 4, CVAR_ARCHIVE)
 CVAR(Bool, r_highlight_portals, false, CVAR_ARCHIVE)
 
-EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor)
-
 extern cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles;
 extern cycle_t FrameCycles;
 
@@ -488,7 +487,7 @@ void R_SetupColormap(player_t *player)
 		{
 			fixedlightlev = player->fixedlightlevel * 256;
 			// [SP] Emulate GZDoom's light-amp goggles.
-			if (r_fullbrightignoresectorcolor && fixedlightlev >= 0)
+			if (!level.PreserveSectorColor() && fixedlightlev >= 0)
 			{
 				fixedcolormap = FullNormalLight.Maps;
 			}
diff --git a/src/r_segs.cpp b/src/r_segs.cpp
index ccf6ccf20..490de11d0 100644
--- a/src/r_segs.cpp
+++ b/src/r_segs.cpp
@@ -47,13 +47,13 @@
 #include "r_draw.h"
 #include "v_palette.h"
 #include "r_data/colormaps.h"
+#include "g_levellocals.h"
 
 #define WALLYREPEAT 8
 
 
 CVAR(Bool, r_fogboundary, true, 0)
 CVAR(Bool, r_drawmirrors, true, 0)
-EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
 
 namespace swrenderer
 {
@@ -291,7 +291,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
 	rw_scalestep = ds->iscalestep;
 
 	if (fixedlightlev >= 0)
-		R_SetColorMapLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
+		R_SetColorMapLight((!level.PreserveSectorColor()) ? &FullNormalLight : basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
 	else if (fixedcolormap != NULL)
 		R_SetColorMapLight(fixedcolormap, 0, 0);
 
@@ -608,7 +608,7 @@ void R_RenderFakeWall(drawseg_t *ds, int x1, int x2, F3DFloor *rover)
 	}
 
 	if (fixedlightlev >= 0)
-		R_SetColorMapLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
+		R_SetColorMapLight((!level.PreserveSectorColor()) ? &FullNormalLight : basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
 	else if (fixedcolormap != NULL)
 		R_SetColorMapLight(fixedcolormap, 0, 0);
 
@@ -1060,7 +1060,7 @@ void R_RenderSegLoop ()
 	fixed_t xoffset = rw_offset;
 
 	if (fixedlightlev >= 0)
-		R_SetColorMapLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
+		R_SetColorMapLight((!level.PreserveSectorColor()) ? &FullNormalLight : basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
 	else if (fixedcolormap != NULL)
 		R_SetColorMapLight(fixedcolormap, 0, 0);
 
@@ -2303,11 +2303,11 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
 
 	rw_light = rw_lightleft + (x1 - savecoord.sx1) * rw_lightstep;
 	if (fixedlightlev >= 0)
-		R_SetColorMapLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : usecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
+		R_SetColorMapLight((!level.PreserveSectorColor()) ? &FullNormalLight : usecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
 	else if (fixedcolormap != NULL)
 		R_SetColorMapLight(fixedcolormap, 0, 0);
 	else if (!foggy && (decal->RenderFlags & RF_FULLBRIGHT))
-		R_SetColorMapLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : usecolormap, 0, 0);
+		R_SetColorMapLight((!level.PreserveSectorColor()) ? &FullNormalLight : usecolormap, 0, 0);
 	else
 		calclighting = true;
 
diff --git a/src/r_things.cpp b/src/r_things.cpp
index 730448706..827a0dca2 100644
--- a/src/r_things.cpp
+++ b/src/r_things.cpp
@@ -74,7 +74,6 @@ EXTERN_CVAR(Bool, r_deathcamera);
 EXTERN_CVAR(Bool, r_drawplayersprites)
 EXTERN_CVAR(Bool, r_drawvoxels)
 
-CVAR(Bool, r_fullbrightignoresectorcolor, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
 //CVAR(Bool, r_splitsprites, true, CVAR_ARCHIVE)
 
 namespace swrenderer
@@ -537,7 +536,7 @@ void R_DrawWallSprite(vissprite_t *spr)
 	else if (fixedcolormap != NULL)
 		R_SetColorMapLight(fixedcolormap, 0, 0);
 	else if (!foggy && (spr->renderflags & RF_FULLBRIGHT))
-		R_SetColorMapLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : usecolormap, 0, 0);
+		R_SetColorMapLight((!level.PreserveSectorColor()) ? &FullNormalLight : usecolormap, 0, 0);
 	else
 		calclighting = true;
 
@@ -1128,7 +1127,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
 		}
 		else if (!foggy && ((renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)))
 		{ // full bright
-			vis->colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps;
+			vis->colormap = (!level.PreserveSectorColor()) ? FullNormalLight.Maps : mybasecolormap->Maps;
 		}
 		else
 		{ // diminished light
@@ -1455,11 +1454,11 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double
 			}
 			if (fixedlightlev >= 0)
 			{
-				vis->colormap = (r_fullbrightignoresectorcolor) ? (FullNormalLight.Maps + fixedlightlev) : (mybasecolormap->Maps + fixedlightlev);
+				vis->colormap = (!level.PreserveSectorColor()) ? (FullNormalLight.Maps + fixedlightlev) : (mybasecolormap->Maps + fixedlightlev);
 			}
 			else if (!foggy && pspr->GetState()->GetFullbright())
 			{ // full bright
-				vis->colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps;	// [RH] use basecolormap
+				vis->colormap = (!level.PreserveSectorColor()) ? FullNormalLight.Maps : mybasecolormap->Maps;	// [RH] use basecolormap
 			}
 			else
 			{ // local light
@@ -1506,9 +1505,9 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double
 			noaccel = true;
 		}
 		// [SP] If emulating GZDoom fullbright, disable acceleration
-		if (r_fullbrightignoresectorcolor && fixedlightlev >= 0)
+		if (!level.PreserveSectorColor() && fixedlightlev >= 0)
 			mybasecolormap = &FullNormalLight;
-		if (r_fullbrightignoresectorcolor && !foggy && pspr->GetState()->GetFullbright())
+		if (!level.PreserveSectorColor() && !foggy && pspr->GetState()->GetFullbright())
 			mybasecolormap = &FullNormalLight;
 		colormap_to_use = mybasecolormap;
 	}
@@ -2049,7 +2048,7 @@ void R_DrawSprite (vissprite_t *spr)
 			}
 			else if (!foggy && (spr->renderflags & RF_FULLBRIGHT))
 			{ // full bright
-				spr->colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps;
+				spr->colormap = (!level.PreserveSectorColor()) ? FullNormalLight.Maps : mybasecolormap->Maps;
 			}
 			else
 			{ // diminished light
@@ -2607,7 +2606,7 @@ void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade,
 	}
 	else if (particle->bright)
 	{
-		vis->colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : map;
+		vis->colormap = (!level.PreserveSectorColor()) ? FullNormalLight.Maps : map;
 	}
 	else
 	{
diff --git a/src/r_utility.cpp b/src/r_utility.cpp
index d2358d8b3..8b0a04a86 100644
--- a/src/r_utility.cpp
+++ b/src/r_utility.cpp
@@ -91,6 +91,11 @@ static TArray<DVector3a> InterpolationPath;
 
 // PUBLIC DATA DEFINITIONS -------------------------------------------------
 
+CUSTOM_CVAR(Int, r_preservesectorcolor, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
+{
+	if (self < -1 || self > 1) self = -1;
+}
+
 CVAR (Bool, r_deathcamera, false, CVAR_ARCHIVE)
 CVAR (Int, r_clearbuffer, 0, 0)
 CVAR (Bool, r_drawvoxels, true, 0)
diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu
index bdc1ce3ae..c2fb0a5a0 100644
--- a/wadsrc/static/language.enu
+++ b/wadsrc/static/language.enu
@@ -1787,7 +1787,7 @@ DSPLYMNU_WATERFADE				= "Underwater Blend Intensity";
 DSPLYMNU_PALLETEHACK			= "DirectDraw palette hack"; // Not used
 DSPLYMNU_ATTACHEDSURFACES		= "Use attached surfaces"; // Not used
 DSPLYMNU_SKYMODE				= "Sky render mode";
-DSPLYMNU_GZDFULLBRIGHT			= "Fullbright overrides sector color";
+DSPLYMNU_GZDFULLBRIGHT			= "Fullbright preserves sector color";
 DSPLYMNU_DRAWFUZZ				= "Use fuzz effect";
 DSPLYMNU_TRANSSOUL				= "Lost Soul translucency";
 DSPLYMNU_FAKECONTRAST			= "Use fake contrast";
diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt
index 47213a0f6..64e29dfe7 100644
--- a/wadsrc/static/menudef.txt
+++ b/wadsrc/static/menudef.txt
@@ -651,6 +651,13 @@ OptionValue Fuzziness
 	2.0, "$OPTVAL_SHADOW"
 }
 
+OptionValue SectorColor
+{
+	-1.0, "$OPTVAL_MAPSETTING"
+	 0.0, "$OPTVAL_OFF"
+	 1.0, "$OPTVAL_ON"
+}
+
 OptionMenu "OpenGLOptions"
 {
 	Title "$GLMNU_TITLE"
@@ -690,7 +697,7 @@ OptionMenu "VideoOptions"
 	}
 	
 	Option "$DSPLYMNU_SKYMODE",					"r_skymode", "SkyModes"
-	Option "$DSPLYMNU_GZDFULLBRIGHT",			"r_fullbrightignoresectorcolor", "OnOff"
+	Option "$DSPLYMNU_GZDFULLBRIGHT",			"r_preservesectorcolor", "SectorColor"
 	Option "$DSPLYMNU_DRAWFUZZ",				"r_drawfuzz", "Fuzziness"
 	Slider "$DSPLYMNU_TRANSSOUL",				"transsouls", 0.25, 1.0, 0.05, 2
 	Option "$DSPLYMNU_FAKECONTRAST",			"r_fakecontrast", "Contrast"

From 1d2ae53ecbd37e77237672c870221b51e286cfd5 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Sat, 28 Jan 2017 18:26:52 +0100
Subject: [PATCH 04/11] Revert "- made r_fullbrightignoresectorcolor a MAPINFO
 option, so far only working on the software renderer. GL still needs a few
 changes to handle it correctly."

This reverts commit dd03bb1fcb72eb06012775fe66b7a553982fd80c.

Turns out that making this work in GL will create a complete mess so better remove the option as it would only cause problems.
---
 src/g_level.cpp                    | 15 ---------------
 src/g_level.h                      |  1 -
 src/g_levellocals.h                |  1 -
 src/g_mapinfo.cpp                  |  2 --
 src/gl/renderer/gl_renderstate.cpp |  4 ++--
 src/r_bsp.cpp                      |  5 +++--
 src/r_main.cpp                     |  5 +++--
 src/r_segs.cpp                     | 12 ++++++------
 src/r_things.cpp                   | 17 +++++++++--------
 src/r_utility.cpp                  |  5 -----
 wadsrc/static/language.enu         |  2 +-
 wadsrc/static/menudef.txt          |  9 +--------
 12 files changed, 25 insertions(+), 53 deletions(-)

diff --git a/src/g_level.cpp b/src/g_level.cpp
index 8b67c9107..a71b481c9 100644
--- a/src/g_level.cpp
+++ b/src/g_level.cpp
@@ -101,7 +101,6 @@ EXTERN_CVAR (Float, sv_gravity)
 EXTERN_CVAR (Float, sv_aircontrol)
 EXTERN_CVAR (Int, disableautosave)
 EXTERN_CVAR (String, playerclass)
-EXTERN_CVAR(Int, r_preservesectorcolor)
 
 #define SNAP_ID			MAKE_ID('s','n','A','p')
 #define DSNP_ID			MAKE_ID('d','s','N','p')
@@ -1488,20 +1487,6 @@ bool FLevelLocals::IsFreelookAllowed() const
 //
 //==========================================================================
 
-bool FLevelLocals::PreserveSectorColor() const
-{
-	if (r_preservesectorcolor == 0)
-		return false;
-	if (r_preservesectorcolor == 1)
-		return true;
-	return !!(level.flags3 & LEVEL3_PRESERVESECTORCOLOR);
-}
-
-//==========================================================================
-//
-//
-//==========================================================================
-
 FString CalcMapName (int episode, int level)
 {
 	FString lumpname;
diff --git a/src/g_level.h b/src/g_level.h
index 270cf54f0..1fadcee3a 100644
--- a/src/g_level.h
+++ b/src/g_level.h
@@ -223,7 +223,6 @@ enum ELevelFlags : unsigned int
 	
 	// More flags!
 	LEVEL3_FORCEFAKECONTRAST	= 0x00000001,	// forces fake contrast even with fog enabled
-	LEVEL3_PRESERVESECTORCOLOR	= 0x00000002,
 };
 
 
diff --git a/src/g_levellocals.h b/src/g_levellocals.h
index 0afac37ad..357e2e154 100644
--- a/src/g_levellocals.h
+++ b/src/g_levellocals.h
@@ -79,7 +79,6 @@ struct FLevelLocals
 	bool		IsJumpingAllowed() const;
 	bool		IsCrouchingAllowed() const;
 	bool		IsFreelookAllowed() const;
-	bool		PreserveSectorColor() const;
 };
 
 extern FLevelLocals level;
diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp
index 3f8e50027..bb641b23b 100644
--- a/src/g_mapinfo.cpp
+++ b/src/g_mapinfo.cpp
@@ -1282,8 +1282,6 @@ MapFlagHandlers[] =
 	{ "unfreezesingleplayerconversations",MITYPE_SETFLAG2,	LEVEL2_CONV_SINGLE_UNFREEZE, 0 },
 	{ "spawnwithweaponraised",			MITYPE_SETFLAG2,	LEVEL2_PRERAISEWEAPON, 0 },
 	{ "forcefakecontrast",				MITYPE_SETFLAG3,	LEVEL3_FORCEFAKECONTRAST, 0 },
-	{ "preservesectorcolor",			MITYPE_SETFLAG3,	LEVEL3_PRESERVESECTORCOLOR, 0 },
-	{ "nopreservesectorcolor",			MITYPE_CLRFLAG3,	LEVEL3_PRESERVESECTORCOLOR, 0 },
 	{ "nobotnodes",						MITYPE_IGNORE,	0, 0 },		// Skulltag option: nobotnodes
 	{ "compat_shorttex",				MITYPE_COMPATFLAG, COMPATF_SHORTTEX, 0 },
 	{ "compat_stairs",					MITYPE_COMPATFLAG, COMPATF_STAIRINDEX, 0 },
diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp
index 04a53d67d..429f69c34 100644
--- a/src/gl/renderer/gl_renderstate.cpp
+++ b/src/gl/renderer/gl_renderstate.cpp
@@ -141,10 +141,9 @@ bool FRenderState::ApplyShader()
 			fogset = -gl_fogmode;
 		}
 	}
-	glVertexAttrib4fv(VATTR_NORMAL, mNormal.vec);
 
 	glVertexAttrib4fv(VATTR_COLOR, mColor.vec);
-	activeShader->muObjectColor.Set(mObjectColor);
+	glVertexAttrib4fv(VATTR_NORMAL, mNormal.vec);
 
 	activeShader->muDesaturation.Set(mDesaturation / 255.f);
 	activeShader->muFogEnabled.Set(fogset);
@@ -153,6 +152,7 @@ bool FRenderState::ApplyShader()
 	activeShader->muCameraPos.Set(mCameraPos.vec);
 	activeShader->muLightParms.Set(mLightParms);
 	activeShader->muFogColor.Set(mFogColor);
+	activeShader->muObjectColor.Set(mObjectColor);
 	activeShader->muDynLightColor.Set(mDynColor.vec);
 	activeShader->muInterpolationFactor.Set(mInterpolationFactor);
 	activeShader->muClipHeight.Set(mClipHeight);
diff --git a/src/r_bsp.cpp b/src/r_bsp.cpp
index a28b63d4a..14a2f153f 100644
--- a/src/r_bsp.cpp
+++ b/src/r_bsp.cpp
@@ -54,6 +54,7 @@
 #include "g_levellocals.h"
 
 CVAR (Bool, r_drawflat, false, 0)		// [RH] Don't texture segs?
+EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
 
 namespace swrenderer
 {
@@ -1108,7 +1109,7 @@ void R_Subsector (subsector_t *sub)
 	}
 	else
 	{
-		basecolormap = (!level.PreserveSectorColor() && fixedlightlev >= 0) ? &FullNormalLight : frontsector->ColorMap;
+		basecolormap = (r_fullbrightignoresectorcolor && fixedlightlev >= 0) ? &FullNormalLight : frontsector->ColorMap;
 	}
 
 	portal = frontsector->ValidatePortal(sector_t::ceiling);
@@ -1142,7 +1143,7 @@ void R_Subsector (subsector_t *sub)
 	}
 	else
 	{
-		basecolormap = (!level.PreserveSectorColor() && fixedlightlev >= 0) ? &FullNormalLight : frontsector->ColorMap;
+		basecolormap = (r_fullbrightignoresectorcolor && fixedlightlev >= 0) ? &FullNormalLight : frontsector->ColorMap;
 	}
 
 	// killough 3/7/98: Add (x,y) offsets to flats, add deep water check
diff --git a/src/r_main.cpp b/src/r_main.cpp
index 8907888f5..7030339c7 100644
--- a/src/r_main.cpp
+++ b/src/r_main.cpp
@@ -59,7 +59,6 @@
 #include "r_data/colormaps.h"
 #include "p_maputl.h"
 #include "r_thread.h"
-#include "g_levellocals.h"
 
 CVAR (String, r_viewsize, "", CVAR_NOSET)
 CVAR (Bool, r_shadercolormaps, true, CVAR_ARCHIVE)
@@ -79,6 +78,8 @@ CUSTOM_CVAR (Int, r_columnmethod, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
 CVAR(Int, r_portal_recursions, 4, CVAR_ARCHIVE)
 CVAR(Bool, r_highlight_portals, false, CVAR_ARCHIVE)
 
+EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor)
+
 extern cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles;
 extern cycle_t FrameCycles;
 
@@ -487,7 +488,7 @@ void R_SetupColormap(player_t *player)
 		{
 			fixedlightlev = player->fixedlightlevel * 256;
 			// [SP] Emulate GZDoom's light-amp goggles.
-			if (!level.PreserveSectorColor() && fixedlightlev >= 0)
+			if (r_fullbrightignoresectorcolor && fixedlightlev >= 0)
 			{
 				fixedcolormap = FullNormalLight.Maps;
 			}
diff --git a/src/r_segs.cpp b/src/r_segs.cpp
index 490de11d0..ccf6ccf20 100644
--- a/src/r_segs.cpp
+++ b/src/r_segs.cpp
@@ -47,13 +47,13 @@
 #include "r_draw.h"
 #include "v_palette.h"
 #include "r_data/colormaps.h"
-#include "g_levellocals.h"
 
 #define WALLYREPEAT 8
 
 
 CVAR(Bool, r_fogboundary, true, 0)
 CVAR(Bool, r_drawmirrors, true, 0)
+EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
 
 namespace swrenderer
 {
@@ -291,7 +291,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
 	rw_scalestep = ds->iscalestep;
 
 	if (fixedlightlev >= 0)
-		R_SetColorMapLight((!level.PreserveSectorColor()) ? &FullNormalLight : basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
+		R_SetColorMapLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
 	else if (fixedcolormap != NULL)
 		R_SetColorMapLight(fixedcolormap, 0, 0);
 
@@ -608,7 +608,7 @@ void R_RenderFakeWall(drawseg_t *ds, int x1, int x2, F3DFloor *rover)
 	}
 
 	if (fixedlightlev >= 0)
-		R_SetColorMapLight((!level.PreserveSectorColor()) ? &FullNormalLight : basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
+		R_SetColorMapLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
 	else if (fixedcolormap != NULL)
 		R_SetColorMapLight(fixedcolormap, 0, 0);
 
@@ -1060,7 +1060,7 @@ void R_RenderSegLoop ()
 	fixed_t xoffset = rw_offset;
 
 	if (fixedlightlev >= 0)
-		R_SetColorMapLight((!level.PreserveSectorColor()) ? &FullNormalLight : basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
+		R_SetColorMapLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
 	else if (fixedcolormap != NULL)
 		R_SetColorMapLight(fixedcolormap, 0, 0);
 
@@ -2303,11 +2303,11 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
 
 	rw_light = rw_lightleft + (x1 - savecoord.sx1) * rw_lightstep;
 	if (fixedlightlev >= 0)
-		R_SetColorMapLight((!level.PreserveSectorColor()) ? &FullNormalLight : usecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
+		R_SetColorMapLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : usecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
 	else if (fixedcolormap != NULL)
 		R_SetColorMapLight(fixedcolormap, 0, 0);
 	else if (!foggy && (decal->RenderFlags & RF_FULLBRIGHT))
-		R_SetColorMapLight((!level.PreserveSectorColor()) ? &FullNormalLight : usecolormap, 0, 0);
+		R_SetColorMapLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : usecolormap, 0, 0);
 	else
 		calclighting = true;
 
diff --git a/src/r_things.cpp b/src/r_things.cpp
index 827a0dca2..730448706 100644
--- a/src/r_things.cpp
+++ b/src/r_things.cpp
@@ -74,6 +74,7 @@ EXTERN_CVAR(Bool, r_deathcamera);
 EXTERN_CVAR(Bool, r_drawplayersprites)
 EXTERN_CVAR(Bool, r_drawvoxels)
 
+CVAR(Bool, r_fullbrightignoresectorcolor, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
 //CVAR(Bool, r_splitsprites, true, CVAR_ARCHIVE)
 
 namespace swrenderer
@@ -536,7 +537,7 @@ void R_DrawWallSprite(vissprite_t *spr)
 	else if (fixedcolormap != NULL)
 		R_SetColorMapLight(fixedcolormap, 0, 0);
 	else if (!foggy && (spr->renderflags & RF_FULLBRIGHT))
-		R_SetColorMapLight((!level.PreserveSectorColor()) ? &FullNormalLight : usecolormap, 0, 0);
+		R_SetColorMapLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : usecolormap, 0, 0);
 	else
 		calclighting = true;
 
@@ -1127,7 +1128,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
 		}
 		else if (!foggy && ((renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)))
 		{ // full bright
-			vis->colormap = (!level.PreserveSectorColor()) ? FullNormalLight.Maps : mybasecolormap->Maps;
+			vis->colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps;
 		}
 		else
 		{ // diminished light
@@ -1454,11 +1455,11 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double
 			}
 			if (fixedlightlev >= 0)
 			{
-				vis->colormap = (!level.PreserveSectorColor()) ? (FullNormalLight.Maps + fixedlightlev) : (mybasecolormap->Maps + fixedlightlev);
+				vis->colormap = (r_fullbrightignoresectorcolor) ? (FullNormalLight.Maps + fixedlightlev) : (mybasecolormap->Maps + fixedlightlev);
 			}
 			else if (!foggy && pspr->GetState()->GetFullbright())
 			{ // full bright
-				vis->colormap = (!level.PreserveSectorColor()) ? FullNormalLight.Maps : mybasecolormap->Maps;	// [RH] use basecolormap
+				vis->colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps;	// [RH] use basecolormap
 			}
 			else
 			{ // local light
@@ -1505,9 +1506,9 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double
 			noaccel = true;
 		}
 		// [SP] If emulating GZDoom fullbright, disable acceleration
-		if (!level.PreserveSectorColor() && fixedlightlev >= 0)
+		if (r_fullbrightignoresectorcolor && fixedlightlev >= 0)
 			mybasecolormap = &FullNormalLight;
-		if (!level.PreserveSectorColor() && !foggy && pspr->GetState()->GetFullbright())
+		if (r_fullbrightignoresectorcolor && !foggy && pspr->GetState()->GetFullbright())
 			mybasecolormap = &FullNormalLight;
 		colormap_to_use = mybasecolormap;
 	}
@@ -2048,7 +2049,7 @@ void R_DrawSprite (vissprite_t *spr)
 			}
 			else if (!foggy && (spr->renderflags & RF_FULLBRIGHT))
 			{ // full bright
-				spr->colormap = (!level.PreserveSectorColor()) ? FullNormalLight.Maps : mybasecolormap->Maps;
+				spr->colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps;
 			}
 			else
 			{ // diminished light
@@ -2606,7 +2607,7 @@ void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade,
 	}
 	else if (particle->bright)
 	{
-		vis->colormap = (!level.PreserveSectorColor()) ? FullNormalLight.Maps : map;
+		vis->colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : map;
 	}
 	else
 	{
diff --git a/src/r_utility.cpp b/src/r_utility.cpp
index 8b0a04a86..d2358d8b3 100644
--- a/src/r_utility.cpp
+++ b/src/r_utility.cpp
@@ -91,11 +91,6 @@ static TArray<DVector3a> InterpolationPath;
 
 // PUBLIC DATA DEFINITIONS -------------------------------------------------
 
-CUSTOM_CVAR(Int, r_preservesectorcolor, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
-{
-	if (self < -1 || self > 1) self = -1;
-}
-
 CVAR (Bool, r_deathcamera, false, CVAR_ARCHIVE)
 CVAR (Int, r_clearbuffer, 0, 0)
 CVAR (Bool, r_drawvoxels, true, 0)
diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu
index c2fb0a5a0..bdc1ce3ae 100644
--- a/wadsrc/static/language.enu
+++ b/wadsrc/static/language.enu
@@ -1787,7 +1787,7 @@ DSPLYMNU_WATERFADE				= "Underwater Blend Intensity";
 DSPLYMNU_PALLETEHACK			= "DirectDraw palette hack"; // Not used
 DSPLYMNU_ATTACHEDSURFACES		= "Use attached surfaces"; // Not used
 DSPLYMNU_SKYMODE				= "Sky render mode";
-DSPLYMNU_GZDFULLBRIGHT			= "Fullbright preserves sector color";
+DSPLYMNU_GZDFULLBRIGHT			= "Fullbright overrides sector color";
 DSPLYMNU_DRAWFUZZ				= "Use fuzz effect";
 DSPLYMNU_TRANSSOUL				= "Lost Soul translucency";
 DSPLYMNU_FAKECONTRAST			= "Use fake contrast";
diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt
index 64e29dfe7..47213a0f6 100644
--- a/wadsrc/static/menudef.txt
+++ b/wadsrc/static/menudef.txt
@@ -651,13 +651,6 @@ OptionValue Fuzziness
 	2.0, "$OPTVAL_SHADOW"
 }
 
-OptionValue SectorColor
-{
-	-1.0, "$OPTVAL_MAPSETTING"
-	 0.0, "$OPTVAL_OFF"
-	 1.0, "$OPTVAL_ON"
-}
-
 OptionMenu "OpenGLOptions"
 {
 	Title "$GLMNU_TITLE"
@@ -697,7 +690,7 @@ OptionMenu "VideoOptions"
 	}
 	
 	Option "$DSPLYMNU_SKYMODE",					"r_skymode", "SkyModes"
-	Option "$DSPLYMNU_GZDFULLBRIGHT",			"r_preservesectorcolor", "SectorColor"
+	Option "$DSPLYMNU_GZDFULLBRIGHT",			"r_fullbrightignoresectorcolor", "OnOff"
 	Option "$DSPLYMNU_DRAWFUZZ",				"r_drawfuzz", "Fuzziness"
 	Slider "$DSPLYMNU_TRANSSOUL",				"transsouls", 0.25, 1.0, 0.05, 2
 	Option "$DSPLYMNU_FAKECONTRAST",			"r_fakecontrast", "Contrast"

From dbbd797baadc8b997c1b6d5d24a71df734248cd1 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Sat, 28 Jan 2017 19:05:39 +0100
Subject: [PATCH 05/11] - added the needed properties for Doom64 colors and a
 little FraggleScript hack to test it with existing maps.

---
 src/fragglescript/t_func.cpp | 13 +++++++++++--
 src/fragglescript/t_load.cpp | 19 +++++++++++++++++++
 src/fragglescript/t_script.h |  1 +
 src/namedef.h                |  5 +++++
 src/p_saveg.cpp              |  1 +
 src/p_setup.cpp              |  1 +
 src/p_udmf.cpp               | 21 +++++++++++++++++++++
 src/r_defs.h                 |  9 ++++++++-
 8 files changed, 67 insertions(+), 3 deletions(-)

diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp
index 5aaa402e8..1ffd34fad 100644
--- a/src/fragglescript/t_func.cpp
+++ b/src/fragglescript/t_func.cpp
@@ -3875,7 +3875,7 @@ void FParser::SF_SetColor(void)
 			color.r=intvalue(t_argv[1]);
 			color.g=intvalue(t_argv[2]);
 			color.b=intvalue(t_argv[3]);
-			color.a=0;
+			color.a = (DFraggleThinker::ActiveThinker->setcolormaterial) ? 255 : 0;
 		}
 		else return;
 
@@ -3883,7 +3883,16 @@ void FParser::SF_SetColor(void)
 		FSSectorTagIterator itr(tagnum);
 		while ((i = itr.Next()) >= 0)
 		{
-			level.sectors[i].ColorMap = GetSpecialLights (color, level.sectors[i].ColorMap->Fade, 0);
+			if (!DFraggleThinker::ActiveThinker->setcolormaterial)
+				level.sectors[i].ColorMap = GetSpecialLights(color, level.sectors[i].ColorMap->Fade, 0);
+			else
+			{
+				// little hack for testing the D64 color stuff.
+				for (int j = 0; j < 4; j++) level.sectors[i].SpecialColors[j] = color;
+				// simulates 'nocoloredspritelighting' settings.
+				int v = (color.r + color.g + color.b) / 3;
+				level.sectors[i].SpecialColors[4] = (255 + v + v) / 3;
+			}
 		}
 	}
 }
diff --git a/src/fragglescript/t_load.cpp b/src/fragglescript/t_load.cpp
index b3b38543d..eb7b602bf 100644
--- a/src/fragglescript/t_load.cpp
+++ b/src/fragglescript/t_load.cpp
@@ -73,15 +73,18 @@ struct FFsOptions : public FOptionalMapinfoData
 	{
 		identifier = "fragglescript";
 		nocheckposition = false;
+		setcolormaterial = false;
 	}
 	virtual FOptionalMapinfoData *Clone() const
 	{
 		FFsOptions *newopt = new FFsOptions;
 		newopt->identifier = identifier;
 		newopt->nocheckposition = nocheckposition;
+		newopt->setcolormaterial = setcolormaterial;
 		return newopt;
 	}
 	bool nocheckposition;
+	bool setcolormaterial;
 };
 
 DEFINE_MAP_OPTION(fs_nocheckposition, false)
@@ -99,6 +102,21 @@ DEFINE_MAP_OPTION(fs_nocheckposition, false)
 	}
 }
 
+DEFINE_MAP_OPTION(fs_setcolormaterial, false)
+{
+	FFsOptions *opt = info->GetOptData<FFsOptions>("fragglescript");
+
+	if (parse.CheckAssign())
+	{
+		parse.sc.MustGetNumber();
+		opt->setcolormaterial = !!parse.sc.Number;
+	}
+	else
+	{
+		opt->setcolormaterial = true;
+	}
+}
+
 //-----------------------------------------------------------------------------
 //
 // Process the lump to strip all unneeded information from it
@@ -307,6 +325,7 @@ bool FScriptLoader::ParseInfo(MapData * map)
 		if (opt != NULL)
 		{
 			DFraggleThinker::ActiveThinker->nocheckposition = opt->nocheckposition;
+			DFraggleThinker::ActiveThinker->setcolormaterial = opt->setcolormaterial;
 		}
 	}
 
diff --git a/src/fragglescript/t_script.h b/src/fragglescript/t_script.h
index 7a5c21a10..6172c352a 100644
--- a/src/fragglescript/t_script.h
+++ b/src/fragglescript/t_script.h
@@ -695,6 +695,7 @@ public:
 	TObjPtr<DRunningScript> RunningScripts;
 	TArray<TObjPtr<AActor> > SpawnedThings;
 	bool nocheckposition;
+	bool setcolormaterial;
 
 	DFraggleThinker();
 	void OnDestroy() override;
diff --git a/src/namedef.h b/src/namedef.h
index 731947da7..ef7f1c58d 100644
--- a/src/namedef.h
+++ b/src/namedef.h
@@ -549,6 +549,11 @@ xx(Lightceilingabsolute)
 xx(Gravity)
 xx(Lightcolor)
 xx(Fadecolor)
+xx(Color_Floor)
+xx(Color_Ceiling)
+xx(Color_Walltop)
+xx(Color_Wallbottom)
+xx(Color_Sprites)
 xx(Desaturation)
 xx(SoundSequence)
 xx(Silent)
diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp
index 04c35d157..48908ea71 100644
--- a/src/p_saveg.cpp
+++ b/src/p_saveg.cpp
@@ -275,6 +275,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, sector_t &p, sector_t
 			("linked_floor", p.e->Linked.Floor.Sectors)
 			("linked_ceiling", p.e->Linked.Ceiling.Sectors)
 			("colormap", p.ColorMap, def->ColorMap)
+			.Array("specialcolors", p.SpecialColors, def->SpecialColors, 5, true)
 			("gravity", p.gravity, def->gravity)
 			.Terrain("floorterrain", p.terrainnum[0], &def->terrainnum[0])
 			.Terrain("ceilingterrain", p.terrainnum[1], &def->terrainnum[1])
diff --git a/src/p_setup.cpp b/src/p_setup.cpp
index b94e12b9b..e2dee7cf1 100644
--- a/src/p_setup.cpp
+++ b/src/p_setup.cpp
@@ -1504,6 +1504,7 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex)
 		ss->SeqName = NAME_None;
 		ss->nextsec = -1;	//jff 2/26/98 add fields to support locking out
 		ss->prevsec = -1;	// stair retriggering until build completes
+		memset(ss->SpecialColors, -1, sizeof(ss->SpecialColors));
 
 		ss->SetAlpha(sector_t::floor, 1.);
 		ss->SetAlpha(sector_t::ceiling, 1.);
diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp
index b0c9dbc15..6c732d67f 100644
--- a/src/p_udmf.cpp
+++ b/src/p_udmf.cpp
@@ -1307,6 +1307,7 @@ public:
 		sec->sectornum = index;
 		sec->damageinterval = 32;
 		sec->terrainnum[sector_t::ceiling] = sec->terrainnum[sector_t::floor] = -1;
+		memset(sec->SpecialColors, -1, sizeof(sec->SpecialColors));
 		if (floordrop) sec->Flags = SECF_FLOORDROP;
 		// killough 3/7/98: end changes
 
@@ -1459,6 +1460,26 @@ public:
 					fadecolor = CheckInt(key);
 					continue;
 
+				case NAME_Color_Floor:
+					sec->SpecialColors[sector_t::floor] = CheckInt(key) || 0xff000000;
+					break;
+
+				case NAME_Color_Ceiling:
+					sec->SpecialColors[sector_t::ceiling] = CheckInt(key) || 0xff000000;
+					break;
+
+				case NAME_Color_Walltop:
+					sec->SpecialColors[sector_t::walltop] = CheckInt(key) || 0xff000000;
+					break;
+
+				case NAME_Color_Wallbottom:
+					sec->SpecialColors[sector_t::wallbottom] = CheckInt(key) || 0xff000000;
+					break;
+
+				case NAME_Color_Sprites:
+					sec->SpecialColors[sector_t::sprites] = CheckInt(key) || 0xff000000;
+					break;
+
 				case NAME_Desaturation:
 					desaturation = int(255*CheckFloat(key));
 					continue;
diff --git a/src/r_defs.h b/src/r_defs.h
index 3c38f285d..ff5cdd690 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -479,6 +479,7 @@ enum
 	SECF_UNDERWATERMASK	= 32+64,
 	SECF_DRAWN			= 128,	// sector has been drawn at least once
 	SECF_HIDDEN			= 256,	// Do not draw on textured automap
+	SECF_SPECIALCOLORSABSOLUTE = 512,	// The special colors ignore the light level except for fog density.
 };
 
 enum
@@ -660,10 +661,15 @@ public:
 	FSectorPortal *ValidatePortal(int which);
 	void CheckPortalPlane(int plane);
 
+
 	enum
 	{
 		floor,
-		ceiling
+		ceiling,
+		// only used for specialcolors array
+		walltop,
+		wallbottom,
+		sprites
 	};
 
 	struct splane
@@ -961,6 +967,7 @@ public:
 
 	// [RH] give floor and ceiling even more properties
 	FDynamicColormap *ColorMap;	// [RH] Per-sector colormap
+	PalEntry	SpecialColors[5];
 
 
 	TObjPtr<AActor> SoundTarget;

From 12d073a27d13a0f42b8ddb114e386e949c22cb99 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Sat, 28 Jan 2017 18:19:58 +0100
Subject: [PATCH 06/11] - objectcolor stuff.

# Conflicts:
#	src/gl/renderer/gl_renderstate.cpp
---
 src/gl/renderer/gl_renderstate.cpp      |  3 +++
 src/gl/renderer/gl_renderstate.h        |  6 ++++++
 src/gl/shaders/gl_shader.cpp            |  1 +
 src/gl/shaders/gl_shader.h              |  1 +
 wadsrc/static/shaders/glsl/main.fp      |  5 +++--
 wadsrc/static/shaders/glsl/main.vp      | 12 +++++++++---
 wadsrc/static/shaders/glsl/shaderdefs.i |  1 +
 7 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp
index 429f69c34..d70eb5166 100644
--- a/src/gl/renderer/gl_renderstate.cpp
+++ b/src/gl/renderer/gl_renderstate.cpp
@@ -72,6 +72,7 @@ void FRenderState::Reset()
 	mModelMatrixEnabled = false;
 	mTextureMatrixEnabled = false;
 	mObjectColor = 0xffffffff;
+	mObjectColor2 = 0;
 	mVertexBuffer = mCurrentVertexBuffer = NULL;
 	mColormapState = CM_DEFAULT;
 	mSoftLight = 0;
@@ -144,6 +145,8 @@ bool FRenderState::ApplyShader()
 
 	glVertexAttrib4fv(VATTR_COLOR, mColor.vec);
 	glVertexAttrib4fv(VATTR_NORMAL, mNormal.vec);
+	//activeShader->muObjectColor2.Set(mObjectColor2);
+	activeShader->muObjectColor2.Set(mObjectColor2);
 
 	activeShader->muDesaturation.Set(mDesaturation / 255.f);
 	activeShader->muFogEnabled.Set(fogset);
diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h
index 76e2c791c..2bef2ff91 100644
--- a/src/gl/renderer/gl_renderstate.h
+++ b/src/gl/renderer/gl_renderstate.h
@@ -106,6 +106,7 @@ class FRenderState
 	FStateVec4 mClipLine;
 	PalEntry mFogColor;
 	PalEntry mObjectColor;
+	PalEntry mObjectColor2;
 	FStateVec4 mDynColor;
 	float mClipSplit[2];
 
@@ -381,6 +382,11 @@ public:
 		mObjectColor = pe;
 	}
 
+	void SetObjectColor2(PalEntry pe)
+	{
+		mObjectColor2 = pe;
+	}
+
 	void SetFog(PalEntry c, float d)
 	{
 		const float LOG2E = 1.442692f;	// = 1/log(2)
diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp
index ef512faea..421139050 100644
--- a/src/gl/shaders/gl_shader.cpp
+++ b/src/gl/shaders/gl_shader.cpp
@@ -225,6 +225,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
 	muFogColor.Init(hShader, "uFogColor");
 	muDynLightColor.Init(hShader, "uDynLightColor");
 	muObjectColor.Init(hShader, "uObjectColor");
+	muObjectColor2.Init(hShader, "uObjectColor2");
 	muGlowBottomColor.Init(hShader, "uGlowBottomColor");
 	muGlowTopColor.Init(hShader, "uGlowTopColor");
 	muGlowBottomPlane.Init(hShader, "uGlowBottomPlane");
diff --git a/src/gl/shaders/gl_shader.h b/src/gl/shaders/gl_shader.h
index f9eb5c292..e8012aa5d 100644
--- a/src/gl/shaders/gl_shader.h
+++ b/src/gl/shaders/gl_shader.h
@@ -271,6 +271,7 @@ class FShader
 	FBufferedUniformPE muFogColor;
 	FBufferedUniform4f muDynLightColor;
 	FBufferedUniformPE muObjectColor;
+	FBufferedUniformPE muObjectColor2;
 	FUniform4f muGlowBottomColor;
 	FUniform4f muGlowTopColor;
 	FUniform4f muGlowBottomPlane;
diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp
index 145f76964..a6bc6bbd7 100644
--- a/wadsrc/static/shaders/glsl/main.fp
+++ b/wadsrc/static/shaders/glsl/main.fp
@@ -1,5 +1,5 @@
 in vec4 pixelpos;
-in vec2 glowdist;
+in vec3 glowdist;
 
 in vec4 vWorldNormal;
 in vec4 vEyeNormal;
@@ -89,7 +89,8 @@ vec4 getTexel(vec2 st)
 			}
 			break;
 	}
-	texel *= uObjectColor;
+	if (uObjectColor2.a == 0) texel *= uObjectColor;
+	else texel *= mix(uObjectColor, uObjectColor2, glowdist.z);
 
 	return desaturate(texel);
 }
diff --git a/wadsrc/static/shaders/glsl/main.vp b/wadsrc/static/shaders/glsl/main.vp
index 1de8854c0..f4937ab66 100644
--- a/wadsrc/static/shaders/glsl/main.vp
+++ b/wadsrc/static/shaders/glsl/main.vp
@@ -6,7 +6,7 @@ in vec4 aColor;
 in vec4 aVertex2;
 in vec4 aNormal;
 out vec4 pixelpos;
-out vec2 glowdist;
+out vec3 glowdist;
 
 out vec4 vWorldNormal;
 out vec4 vEyeNormal;
@@ -50,9 +50,15 @@ void main()
 		pixelpos.xyz = worldcoord.xyz;
 		pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w;
 
-		glowdist.x = -((uGlowTopPlane.w + uGlowTopPlane.x * worldcoord.x + uGlowTopPlane.y * worldcoord.z) * uGlowTopPlane.z) - worldcoord.y;
-		glowdist.y = worldcoord.y + ((uGlowBottomPlane.w + uGlowBottomPlane.x * worldcoord.x + uGlowBottomPlane.y * worldcoord.z) * uGlowBottomPlane.z);
+		float topatpoint = -((uGlowTopPlane.w + uGlowTopPlane.x * worldcoord.x + uGlowTopPlane.y * worldcoord.z) * uGlowTopPlane.z);
+		float bottomatpoint = -((uGlowBottomPlane.w + uGlowBottomPlane.x * worldcoord.x + uGlowBottomPlane.y * worldcoord.z) * uGlowBottomPlane.z);
+		glowdist.x = topatpoint - worldcoord.y;
+		glowdist.y = worldcoord.y - bottomatpoint;
+		glowdist.z = glowdist.x / (topatpoint - bottomatpoint);
+		
 
+		return (uGlowTopPlane.w + normal.X*v->fX() + normal.Y*v->fY()) * negiC;
+		
 		if (uSplitBottomPlane.z != 0.0)
 		{
 			gl_ClipDistance[3] = -((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y;
diff --git a/wadsrc/static/shaders/glsl/shaderdefs.i b/wadsrc/static/shaders/glsl/shaderdefs.i
index 2099427d5..c109c8524 100644
--- a/wadsrc/static/shaders/glsl/shaderdefs.i
+++ b/wadsrc/static/shaders/glsl/shaderdefs.i
@@ -15,6 +15,7 @@ uniform float uAlphaThreshold;
 
 // colors
 uniform vec4 uObjectColor;
+uniform vec4 uObjectColor2;
 uniform vec4 uDynLightColor;
 uniform vec4 uFogColor;
 uniform float uDesaturationFactor;

From ee22a9371b985c35bad3a7a63be192b4f93d84ec Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Sat, 28 Jan 2017 20:44:46 +0100
Subject: [PATCH 07/11] - use Doom64 colors on sectors and linedefs.

---
 src/am_map.cpp                     |  4 ++++
 src/fragglescript/t_func.cpp       |  4 ++--
 src/gl/renderer/gl_2ddrawer.cpp    |  5 ++++-
 src/gl/renderer/gl_2ddrawer.h      |  3 ++-
 src/gl/renderer/gl_renderer.h      |  2 +-
 src/gl/renderer/gl_renderstate.cpp |  9 +++++----
 src/gl/scene/gl_flats.cpp          | 20 +++++++++++++++++---
 src/gl/scene/gl_wall.h             |  1 +
 src/gl/scene/gl_walls_draw.cpp     | 11 ++++++++---
 src/gl/system/gl_framebuffer.cpp   |  4 ++--
 src/gl/system/gl_framebuffer.h     |  2 +-
 src/p_3dfloors.cpp                 | 16 ++++++++--------
 src/p_3dfloors.h                   |  1 +
 src/v_draw.cpp                     |  2 +-
 src/v_video.h                      |  2 +-
 src/win32/fb_d3d9.cpp              |  4 ++--
 src/win32/win32iface.h             |  2 +-
 wadsrc/static/shaders/glsl/main.vp |  5 +----
 18 files changed, 62 insertions(+), 35 deletions(-)

diff --git a/src/am_map.cpp b/src/am_map.cpp
index f7f140f4d..fad6a13ac 100644
--- a/src/am_map.cpp
+++ b/src/am_map.cpp
@@ -1898,6 +1898,7 @@ void AM_drawSubsectors()
 	double scalex, scaley;
 	double originx, originy;
 	FDynamicColormap *colormap;
+	PalEntry flatcolor;
 	mpoint_t originpt;
 
 	screen->StartSimplePolys();
@@ -1941,6 +1942,7 @@ void AM_drawSubsectors()
 		colormap = sec->ColorMap;
 
 		FTextureID maptex = sec->GetTexture(sector_t::floor);
+		flatcolor = sec->SpecialColors[sector_t::floor];
 
 		scalex = sec->GetXScale(sector_t::floor);
 		scaley = sec->GetYScale(sector_t::floor);
@@ -1989,6 +1991,7 @@ void AM_drawSubsectors()
 				if (roverz < cmpz)
 				{
 					maptex = *(rover->top.texture);
+					flatcolor = *(rover->top.flatcolor);
 					floorplane = rover->top.plane;
 					sector_t *model = rover->top.model;
 					int selector = (rover->flags & FF_INVERTPLANES) ? sector_t::floor : sector_t::ceiling;
@@ -2049,6 +2052,7 @@ void AM_drawSubsectors()
 				scale / scaley,
 				rotation,
 				colormap,
+				flatcolor,
 				floorlight,
 				f_y + f_h
 				);
diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp
index 1ffd34fad..59c82c15c 100644
--- a/src/fragglescript/t_func.cpp
+++ b/src/fragglescript/t_func.cpp
@@ -3875,7 +3875,7 @@ void FParser::SF_SetColor(void)
 			color.r=intvalue(t_argv[1]);
 			color.g=intvalue(t_argv[2]);
 			color.b=intvalue(t_argv[3]);
-			color.a = (DFraggleThinker::ActiveThinker->setcolormaterial) ? 255 : 0;
+			color.a = 0;
 		}
 		else return;
 
@@ -3891,7 +3891,7 @@ void FParser::SF_SetColor(void)
 				for (int j = 0; j < 4; j++) level.sectors[i].SpecialColors[j] = color;
 				// simulates 'nocoloredspritelighting' settings.
 				int v = (color.r + color.g + color.b) / 3;
-				level.sectors[i].SpecialColors[4] = (255 + v + v) / 3;
+				level.sectors[i].SpecialColors[sector_t::sprites] = (255 + v + v) / 3;
 			}
 		}
 	}
diff --git a/src/gl/renderer/gl_2ddrawer.cpp b/src/gl/renderer/gl_2ddrawer.cpp
index ba78634a3..1907edeef 100644
--- a/src/gl/renderer/gl_2ddrawer.cpp
+++ b/src/gl/renderer/gl_2ddrawer.cpp
@@ -174,7 +174,7 @@ void F2DDrawer::AddTexture(FTexture *img, DrawParms &parms)
 
 void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
 		double originx, double originy, double scalex, double scaley,
-		DAngle rotation, FDynamicColormap *colormap, int lightlevel)
+		DAngle rotation, FDynamicColormap *colormap, PalEntry flatcolor, int lightlevel)
 {
 	FMaterial *gltexture = FMaterial::ValidateTexture(texture, false);
 
@@ -191,6 +191,7 @@ void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
 	poly.mLightLevel = lightlevel;
 	poly.mVertCount = npoints;
 	poly.mVertIndex = (int)mVertices.Reserve(npoints);
+	poly.mFlatColor = flatcolor;
 
 	bool dorotate = rotation != 0;
 
@@ -438,8 +439,10 @@ void F2DDrawer::Draw()
 			cm = dsp->mColormap;
 			gl_SetColor(dsp->mLightLevel, 0, cm, 1.f);
 			gl_RenderState.SetMaterial(dsp->mTexture, CLAMP_NONE, 0, -1, false);
+			gl_RenderState.SetObjectColor(dsp->mFlatColor|0xff000000);
 			gl_RenderState.Apply();
 			glDrawArrays(GL_TRIANGLE_FAN, dsp->mVertIndex, dsp->mVertCount);
+			gl_RenderState.SetObjectColor(0xffffffff);
 			break;
 		}
 
diff --git a/src/gl/renderer/gl_2ddrawer.h b/src/gl/renderer/gl_2ddrawer.h
index 8c27f13d8..61f3153d3 100644
--- a/src/gl/renderer/gl_2ddrawer.h
+++ b/src/gl/renderer/gl_2ddrawer.h
@@ -45,6 +45,7 @@ class F2DDrawer : public FSimpleVertexBuffer
 		FMaterial *mTexture;
 		int mLightLevel;
 		FDynamicColormap *mColormap;
+		PalEntry mFlatColor;
 	};
 
 	TArray<FSimpleVertex> mVertices;
@@ -61,7 +62,7 @@ public:
 	
 	void AddPoly(FTexture *texture, FVector2 *points, int npoints,
 		double originx, double originy, double scalex, double scaley,
-		DAngle rotation, FDynamicColormap *colormap, int lightlevel);
+		DAngle rotation, FDynamicColormap *colormap, PalEntry flatcolor, int lightlevel);
 		
 	void AddLine(int x1, int y1, int x2, int y2, int palcolor, uint32 color);
 	void AddPixel(int x1, int y1, int palcolor, uint32 color);
diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h
index 869b46d2d..95739e86d 100644
--- a/src/gl/renderer/gl_renderer.h
+++ b/src/gl/renderer/gl_renderer.h
@@ -216,7 +216,7 @@ public:
 
 	void FillSimplePoly(FTexture *texture, FVector2 *points, int npoints,
 		double originx, double originy, double scalex, double scaley,
-		DAngle rotation, FDynamicColormap *colormap, int lightlevel, int bottomclip);
+		DAngle rotation, FDynamicColormap *colormap, PalEntry flatcolor, int lightlevel, int bottomclip);
 
 	int PTM_BestColor (const uint32 *pal_in, int r, int g, int b, int first, int num);
 
diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp
index d70eb5166..c3c884013 100644
--- a/src/gl/renderer/gl_renderstate.cpp
+++ b/src/gl/renderer/gl_renderstate.cpp
@@ -169,8 +169,6 @@ bool FRenderState::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)
@@ -178,10 +176,13 @@ bool FRenderState::ApplyShader()
 		// if glowing is on, disable it.
 		activeShader->muGlowTopColor.Set(nulvec);
 		activeShader->muGlowBottomColor.Set(nulvec);
-		activeShader->muGlowTopPlane.Set(nulvec);
-		activeShader->muGlowBottomPlane.Set(nulvec);
 		activeShader->currentglowstate = 0;
 	}
+	if (mGlowEnabled || mObjectColor2.a != 0)
+	{
+		activeShader->muGlowTopPlane.Set(mGlowTopPlane.vec);
+		activeShader->muGlowBottomPlane.Set(mGlowBottomPlane.vec);
+	}
 
 	if (mSplitEnabled)
 	{
diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp
index c4296c50d..1ed0fecfa 100644
--- a/src/gl/scene/gl_flats.cpp
+++ b/src/gl/scene/gl_flats.cpp
@@ -379,6 +379,7 @@ void GLFlat::Draw(int pass, bool trans)	// trans only has meaning for GLPASS_LIG
 	case GLPASS_ALL:			// Same, but also creates the dynlight data.
 		gl_SetColor(lightlevel, rel, Colormap,1.0f);
 		gl_SetFog(lightlevel, rel, &Colormap, false);
+		gl_RenderState.SetObjectColor(FlatColor | 0xff000000);
 		if (sector->special != GLSector_Skybox)
 		{
 			gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
@@ -391,6 +392,7 @@ void GLFlat::Draw(int pass, bool trans)	// trans only has meaning for GLPASS_LIG
 			gl_RenderState.SetMaterial(gltexture, CLAMP_XY, 0, -1, false);
 			DrawSkyboxSector(pass, (pass == GLPASS_ALL || dynlightindex > -1));
 		}
+		gl_RenderState.SetObjectColor(0xffffffff);
 		break;
 
 	case GLPASS_LIGHTSONLY:
@@ -404,7 +406,8 @@ void GLFlat::Draw(int pass, bool trans)	// trans only has meaning for GLPASS_LIG
 		if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE);
 		gl_SetColor(lightlevel, rel, Colormap, alpha);
 		gl_SetFog(lightlevel, rel, &Colormap, false);
-		if (!gltexture)	
+		gl_RenderState.SetObjectColor(FlatColor | 0xff000000);
+		if (!gltexture)
 		{
 			gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
 			gl_RenderState.EnableTexture(false);
@@ -421,6 +424,7 @@ void GLFlat::Draw(int pass, bool trans)	// trans only has meaning for GLPASS_LIG
 			gl_RenderState.EnableTextureMatrix(false);
 		}
 		if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+		gl_RenderState.SetObjectColor(0xffffffff);
 		break;
 
 	case GLPASS_LIGHTTEX:
@@ -546,8 +550,16 @@ void GLFlat::SetFrom3DFloor(F3DFloor *rover, bool top, bool underside)
 	lightlist_t *light = P_GetPlaneLight(sector, plane.plane, underside);
 	lightlevel = gl_ClampLight(*light->p_lightlevel);
 	
-	if (rover->flags & FF_FOG) Colormap.LightColor = (light->extra_colormap)->Fade;
-	else Colormap.CopyFrom3DLight(light);
+	if (rover->flags & FF_FOG)
+	{
+		Colormap.LightColor = (light->extra_colormap)->Fade;
+		FlatColor = 0xffffffff;
+	}
+	else
+	{
+		Colormap.CopyFrom3DLight(light);
+		FlatColor = *plane.flatcolor;
+	}
 
 
 	alpha = rover->alpha/255.0f;
@@ -604,6 +616,7 @@ void GLFlat::ProcessSector(sector_t * frontsector)
 
 		lightlevel = gl_ClampLight(frontsector->GetFloorLight());
 		Colormap = frontsector->ColorMap;
+		FlatColor = frontsector->SpecialColors[sector_t::floor];
 		port = frontsector->ValidatePortal(sector_t::floor);
 		if ((stack = (port != NULL)))
 		{
@@ -663,6 +676,7 @@ void GLFlat::ProcessSector(sector_t * frontsector)
 
 		lightlevel = gl_ClampLight(frontsector->GetCeilingLight());
 		Colormap = frontsector->ColorMap;
+		FlatColor = frontsector->SpecialColors[sector_t::ceiling];
 		port = frontsector->ValidatePortal(sector_t::ceiling);
 		if ((stack = (port != NULL)))
 		{
diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h
index 902517a9b..151a5ef71 100644
--- a/src/gl/scene/gl_wall.h
+++ b/src/gl/scene/gl_wall.h
@@ -301,6 +301,7 @@ public:
 	FMaterial *gltexture;
 
 	FColormap Colormap;	// light and fog
+	PalEntry FlatColor;
 	ERenderStyle renderstyle;
 
 	float alpha;
diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp
index 7849114ff..05461fd55 100644
--- a/src/gl/scene/gl_walls_draw.cpp
+++ b/src/gl/scene/gl_walls_draw.cpp
@@ -24,6 +24,7 @@
 #include "p_local.h"
 #include "p_lnspec.h"
 #include "a_sharedglobal.h"
+#include "g_levellocals.h"
 #include "gl/gl_functions.h"
 
 #include "gl/system/gl_interface.h"
@@ -326,9 +327,9 @@ void GLWall::RenderTextured(int rflags)
 	if (flags & GLWF_GLOW)
 	{
 		gl_RenderState.EnableGlow(true);
-		gl_RenderState.SetGlowPlanes(topplane, bottomplane);
 		gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor);
 	}
+	gl_RenderState.SetGlowPlanes(topplane, bottomplane);
 	gl_RenderState.SetMaterial(gltexture, flags & 3, 0, -1, false);
 
 	if (type == RENDERWALL_M2SNF)
@@ -339,12 +340,14 @@ void GLWall::RenderTextured(int rflags)
 		}
 		gl_SetFog(255, 0, NULL, false);
 	}
+	gl_RenderState.SetObjectColor(seg->frontsector->SpecialColors[sector_t::walltop] | 0xff000000);
+	gl_RenderState.SetObjectColor2(seg->frontsector->SpecialColors[sector_t::wallbottom] | 0xff000000);
 
 	float absalpha = fabsf(alpha);
 	if (lightlist == NULL)
 	{
-		gl_SetColor(lightlevel, rel, Colormap, absalpha);
 		if (type != RENDERWALL_M2SNF) gl_SetFog(lightlevel, rel, &Colormap, RenderStyle == STYLE_Add);
+		gl_SetColor((seg->frontsector->MoreFlags & SECF_SPECIALCOLORSABSOLUTE)? 255 : lightlevel, rel, Colormap, absalpha);
 		RenderWall(rflags);
 	}
 	else
@@ -364,7 +367,7 @@ void GLWall::RenderTextured(int rflags)
 				FColormap thiscm;
 				thiscm.FadeColor = Colormap.FadeColor;
 				thiscm.CopyFrom3DLight(&(*lightlist)[i]);
-				gl_SetColor(thisll, rel, thiscm, absalpha);
+				gl_SetColor((seg->frontsector->MoreFlags & SECF_SPECIALCOLORSABSOLUTE) ? 255 : thisll, rel, thiscm, absalpha);
 				if (type != RENDERWALL_M2SNF) gl_SetFog(thisll, rel, &thiscm, RenderStyle == STYLE_Add);
 				gl_RenderState.SetSplitPlanes((*lightlist)[i].plane, lowplane);
 				RenderWall(rflags);
@@ -374,6 +377,8 @@ void GLWall::RenderTextured(int rflags)
 
 		gl_RenderState.EnableSplit(false);
 	}
+	gl_RenderState.SetObjectColor(0xffffffff);
+	gl_RenderState.SetObjectColor2(0);
 	gl_RenderState.SetTextureMode(tmode);
 	gl_RenderState.EnableGlow(false);
 }
diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp
index 6d4fdcff8..1a4582d80 100644
--- a/src/gl/system/gl_framebuffer.cpp
+++ b/src/gl/system/gl_framebuffer.cpp
@@ -470,11 +470,11 @@ void OpenGLFrameBuffer::Clear(int left, int top, int right, int bottom, int palc
 
 void OpenGLFrameBuffer::FillSimplePoly(FTexture *texture, FVector2 *points, int npoints,
 	double originx, double originy, double scalex, double scaley,
-	DAngle rotation, FDynamicColormap *colormap, int lightlevel, int bottomclip)
+	DAngle rotation, FDynamicColormap *colormap, PalEntry flatcolor, int lightlevel, int bottomclip)
 {
 	if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr && npoints >= 3)
 	{
-		GLRenderer->m2DDrawer->AddPoly(texture, points, npoints, originx, originy, scalex, scaley, rotation, colormap, lightlevel);
+		GLRenderer->m2DDrawer->AddPoly(texture, points, npoints, originx, originy, scalex, scaley, rotation, colormap, flatcolor, lightlevel);
 	}
 }
 
diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h
index 27c3d1cf9..0eb289ffe 100644
--- a/src/gl/system/gl_framebuffer.h
+++ b/src/gl/system/gl_framebuffer.h
@@ -71,7 +71,7 @@ public:
 
 	void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
 		double originx, double originy, double scalex, double scaley,
-		DAngle rotation, FDynamicColormap *colormap, int lightlevel, int bottomclip);
+		DAngle rotation, FDynamicColormap *colormap, PalEntry flatcolor, int lightlevel, int bottomclip);
 
 	FNativePalette *CreatePalette(FRemapTable *remap);
 
diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp
index 102ed57b0..77e34adba 100644
--- a/src/p_3dfloors.cpp
+++ b/src/p_3dfloors.cpp
@@ -136,12 +136,14 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag
 	{
 		ffloor->bottom.plane = &sec2->floorplane;
 		ffloor->bottom.texture = &sec2->planes[sector_t::floor].Texture;
+		ffloor->bottom.flatcolor = &sec2->SpecialColors[sector_t::floor];
 		ffloor->bottom.isceiling = sector_t::floor;
 	}
 	else 
 	{
 		ffloor->bottom.plane = &sec2->ceilingplane;
 		ffloor->bottom.texture = &sec2->planes[sector_t::ceiling].Texture;
+		ffloor->bottom.flatcolor = &sec2->SpecialColors[sector_t::ceiling];
 		ffloor->bottom.isceiling = sector_t::ceiling;
 	}
 	
@@ -149,6 +151,7 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag
 	{
 		ffloor->top.plane = &sec2->ceilingplane;
 		ffloor->top.texture = &sec2->planes[sector_t::ceiling].Texture;
+		ffloor->top.flatcolor = &sec2->SpecialColors[sector_t::ceiling];
 		ffloor->toplightlevel = &sec2->lightlevel;
 		ffloor->top.isceiling = sector_t::ceiling;
 	}
@@ -156,6 +159,7 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag
 	{
 		ffloor->top.plane = &sec->floorplane;
 		ffloor->top.texture = &sec2->planes[sector_t::floor].Texture;
+		ffloor->top.flatcolor = &sec2->SpecialColors[sector_t::floor];
 		ffloor->toplightlevel = &sec->lightlevel;
 		ffloor->top.isceiling = sector_t::floor;
 		ffloor->top.model = sec;
@@ -165,10 +169,7 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag
 	if (flags&FF_INVERTSECTOR)
 	{
 		// switch the planes
-		F3DFloor::planeref sp = ffloor->top;
-
-		ffloor->top=ffloor->bottom;
-		ffloor->bottom=sp;
+		std::swap(ffloor->top, ffloor->bottom);
 
 		if (flags&FF_SWIMMABLE)
 		{
@@ -192,11 +193,10 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag
 		ffloor->flags &= ~FF_ADDITIVETRANS;
 	}
 
-	if(flags & FF_THISINSIDE) {
+	if(flags & FF_THISINSIDE) 
+	{
 		// switch the planes
-		F3DFloor::planeref sp = ffloor->top;
-		ffloor->top=ffloor->bottom;
-		ffloor->bottom=sp;
+		std::swap(ffloor->top, ffloor->bottom);
 	}
 
 	sec->e->XFloor.ffloors.Push(ffloor);
diff --git a/src/p_3dfloors.h b/src/p_3dfloors.h
index fc784c55c..75b8656e4 100644
--- a/src/p_3dfloors.h
+++ b/src/p_3dfloors.h
@@ -69,6 +69,7 @@ struct F3DFloor
 		secplane_t *	plane;
 		const FTextureID *	texture;
 		sector_t *		model;
+		PalEntry *		flatcolor;
 		int				isceiling;
 		int				vindex;
 		bool			copied;
diff --git a/src/v_draw.cpp b/src/v_draw.cpp
index 3d4954ed2..9db885efb 100644
--- a/src/v_draw.cpp
+++ b/src/v_draw.cpp
@@ -1272,7 +1272,7 @@ void DCanvas::FinishSimplePolys()
 
 void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
 	double originx, double originy, double scalex, double scaley, DAngle rotation,
-	FDynamicColormap *colormap, int lightlevel, int bottomclip)
+	FDynamicColormap *colormap, PalEntry flatcolor, int lightlevel, int bottomclip)
 {
 #ifndef NO_SWRENDER
 	using namespace swrenderer;
diff --git a/src/v_video.h b/src/v_video.h
index 57d15869c..e9bb1f6a4 100644
--- a/src/v_video.h
+++ b/src/v_video.h
@@ -224,7 +224,7 @@ public:
 	// Fill a simple polygon with a texture
 	virtual void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
 		double originx, double originy, double scalex, double scaley, DAngle rotation,
-		struct FDynamicColormap *colormap, int lightlevel, int bottomclip);
+		struct FDynamicColormap *colormap, PalEntry flatcolor, int lightlevel, int bottomclip);
 
 	// Set an area to a specified color
 	virtual void Clear (int left, int top, int right, int bottom, int palcolor, uint32 color);
diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp
index 026bbc63b..4d758783e 100644
--- a/src/win32/fb_d3d9.cpp
+++ b/src/win32/fb_d3d9.cpp
@@ -3092,7 +3092,7 @@ void D3DFB::FlatFill(int left, int top, int right, int bottom, FTexture *src, bo
 
 void D3DFB::FillSimplePoly(FTexture *texture, FVector2 *points, int npoints,
 	double originx, double originy, double scalex, double scaley,
-	DAngle rotation, FDynamicColormap *colormap, int lightlevel, int bottomclip)
+	DAngle rotation, FDynamicColormap *colormap, PalEntry flatcolor, int lightlevel, int bottomclip)
 {
 	// Use an equation similar to player sprites to determine shade
 	double fadelevel = clamp((LIGHT2SHADE(lightlevel)/65536. - 12) / NUMCOLORMAPS, 0.0, 1.0);
@@ -3113,7 +3113,7 @@ void D3DFB::FillSimplePoly(FTexture *texture, FVector2 *points, int npoints,
 	}
 	if (In2D < 2)
 	{
-		Super::FillSimplePoly(texture, points, npoints, originx, originy, scalex, scaley, rotation, colormap, lightlevel, bottomclip);
+		Super::FillSimplePoly(texture, points, npoints, originx, originy, scalex, scaley, rotation, colormap, flatcolor, lightlevel, bottomclip);
 		return;
 	}
 	if (!InScene)
diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h
index b5262089b..a92672ad7 100644
--- a/src/win32/win32iface.h
+++ b/src/win32/win32iface.h
@@ -265,7 +265,7 @@ public:
 	void DrawPixel(int x, int y, int palcolor, uint32 rgbcolor);
 	void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
 		double originx, double originy, double scalex, double scaley,
-		DAngle rotation, FDynamicColormap *colormap, int lightlevel, int bottomclip) override;
+		DAngle rotation, FDynamicColormap *colormap, PalEntry flatcolor, int lightlevel, int bottomclip) override;
 	bool WipeStartScreen(int type);
 	void WipeEndScreen();
 	bool WipeDo(int ticks);
diff --git a/wadsrc/static/shaders/glsl/main.vp b/wadsrc/static/shaders/glsl/main.vp
index f4937ab66..f66ee7b04 100644
--- a/wadsrc/static/shaders/glsl/main.vp
+++ b/wadsrc/static/shaders/glsl/main.vp
@@ -54,10 +54,7 @@ void main()
 		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 = glowdist.x / (topatpoint - bottomatpoint);
-		
-
-		return (uGlowTopPlane.w + normal.X*v->fX() + normal.Y*v->fY()) * negiC;
+		glowdist.z = clamp(glowdist.x / (topatpoint - bottomatpoint), 0.0, 1.0);
 		
 		if (uSplitBottomPlane.z != 0.0)
 		{

From e96f23142060526af5bedecf3c6242e7ffdae567 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Sat, 28 Jan 2017 21:02:03 +0100
Subject: [PATCH 08/11] - added Doom64 colors for sprites.

---
 src/fragglescript/t_func.cpp |  3 ++-
 src/gl/scene/gl_flats.cpp    |  4 ++--
 src/gl/scene/gl_sprite.cpp   | 15 +++++++++++----
 src/gl/scene/gl_weapon.cpp   |  9 +++++++--
 4 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp
index 59c82c15c..20b53c8fd 100644
--- a/src/fragglescript/t_func.cpp
+++ b/src/fragglescript/t_func.cpp
@@ -3891,7 +3891,8 @@ void FParser::SF_SetColor(void)
 				for (int j = 0; j < 4; j++) level.sectors[i].SpecialColors[j] = color;
 				// simulates 'nocoloredspritelighting' settings.
 				int v = (color.r + color.g + color.b) / 3;
-				level.sectors[i].SpecialColors[sector_t::sprites] = (255 + v + v) / 3;
+				v = (255 + v + v) / 3;
+				level.sectors[i].SpecialColors[sector_t::sprites] = PalEntry(255, v, v, v);
 			}
 		}
 	}
diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp
index 1ed0fecfa..a1f5f989c 100644
--- a/src/gl/scene/gl_flats.cpp
+++ b/src/gl/scene/gl_flats.cpp
@@ -377,7 +377,7 @@ void GLFlat::Draw(int pass, bool trans)	// trans only has meaning for GLPASS_LIG
 	{
 	case GLPASS_PLAIN:			// Single-pass rendering
 	case GLPASS_ALL:			// Same, but also creates the dynlight data.
-		gl_SetColor(lightlevel, rel, Colormap,1.0f);
+		gl_SetColor((sector->MoreFlags & SECF_SPECIALCOLORSABSOLUTE) ? 255 : lightlevel, rel, Colormap,1.0f);
 		gl_SetFog(lightlevel, rel, &Colormap, false);
 		gl_RenderState.SetObjectColor(FlatColor | 0xff000000);
 		if (sector->special != GLSector_Skybox)
@@ -404,7 +404,7 @@ void GLFlat::Draw(int pass, bool trans)	// trans only has meaning for GLPASS_LIG
 
 	case GLPASS_TRANSLUCENT:
 		if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE);
-		gl_SetColor(lightlevel, rel, Colormap, alpha);
+		gl_SetColor((sector->MoreFlags & SECF_SPECIALCOLORSABSOLUTE) ? 255 : lightlevel, rel, Colormap, alpha);
 		gl_SetFog(lightlevel, rel, &Colormap, false);
 		gl_RenderState.SetObjectColor(FlatColor | 0xff000000);
 		if (!gltexture)
diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp
index adbc626ed..5ddaab7e5 100644
--- a/src/gl/scene/gl_sprite.cpp
+++ b/src/gl/scene/gl_sprite.cpp
@@ -308,6 +308,7 @@ void GLSprite::Draw(int pass)
 			gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold);
 			gl_RenderState.SetColor(0.2f,0.2f,0.2f,fuzzalpha, Colormap.desaturation);
 			additivefog = true;
+			lightlist = nullptr;	// the fuzz effect does not use the sector's light level so splitting is not needed.
 		}
 		else if (RenderStyle.BlendOp == STYLEOP_Add && RenderStyle.DestAlpha == STYLEALPHA_One)
 		{
@@ -319,15 +320,21 @@ void GLSprite::Draw(int pass)
 		glEnable(GL_POLYGON_OFFSET_FILL);
 		glPolygonOffset(-1.0f, -128.0f);
 	}
-	if (RenderStyle.BlendOp!=STYLEOP_Shadow)
+	if (RenderStyle.BlendOp != STYLEOP_Shadow)
 	{
 		if (gl_lights && GLRenderer->mLightCount && !gl_fixedcolormap && !fullbright)
 		{
 			gl_SetDynSpriteLight(gl_light_sprites ? actor : NULL, gl_light_particles ? particle : NULL);
 		}
-		gl_SetColor(lightlevel, rel, Colormap, trans);
+		PalEntry finalcol(ThingColor.a,
+			ThingColor.r * actor->Sector->SpecialColors[sector_t::sprites].r / 255,
+			ThingColor.g * actor->Sector->SpecialColors[sector_t::sprites].g / 255,
+			ThingColor.b * actor->Sector->SpecialColors[sector_t::sprites].b / 255);
+
+		gl_RenderState.SetObjectColor(finalcol);
+		gl_SetColor((actor->Sector->MoreFlags & SECF_SPECIALCOLORSABSOLUTE) ? 255 : lightlevel, rel, Colormap, trans);
 	}
-	gl_RenderState.SetObjectColor(ThingColor);
+
 
 	if (gl_isBlack(Colormap.FadeColor)) foglevel=lightlevel;
 
@@ -394,7 +401,7 @@ void GLSprite::Draw(int pass)
 				thiscm.Decolorize();
 			}
 
-			gl_SetColor(thisll, rel, thiscm, trans);
+			gl_SetColor((actor->Sector->MoreFlags & SECF_SPECIALCOLORSABSOLUTE) ? 255 : thisll, rel, thiscm, trans);
 			if (!foglayer)
 			{
 				gl_SetFog(thislight, rel, &thiscm, additivefog);
diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp
index d53e252e3..6260627ba 100644
--- a/src/gl/scene/gl_weapon.cpp
+++ b/src/gl/scene/gl_weapon.cpp
@@ -370,7 +370,12 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
 
 	// now draw the different layers of the weapon
 	gl_RenderState.EnableBrightmap(true);
-	gl_RenderState.SetObjectColor(ThingColor);
+	PalEntry finalcol(ThingColor.a,
+		ThingColor.r * viewsector->SpecialColors[sector_t::sprites].r / 255,
+		ThingColor.g * viewsector->SpecialColors[sector_t::sprites].g / 255,
+		ThingColor.b * viewsector->SpecialColors[sector_t::sprites].b / 255);
+
+	gl_RenderState.SetObjectColor(finalcol);
 	gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold);
 
 	// hack alert! Rather than changing everything in the underlying lighting code let's just temporarily change
@@ -412,7 +417,7 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
 				{
 					gl_SetDynSpriteLight(playermo, NULL);
 				}
-				gl_SetColor(ll, 0, cmc, trans, true);
+				gl_SetColor((viewsector->MoreFlags & SECF_SPECIALCOLORSABSOLUTE) ? 255 : ll, 0, cmc, trans, true);
 			}
 
 			if (psp->firstTic)

From 476aceb5d71963260236aa3f6314329db8b23adf Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Sat, 28 Jan 2017 21:22:48 +0100
Subject: [PATCH 09/11] - added new properties to UDMF spec. - implemented
 color_absolute flag,

---
 specs/udmf_zdoom.txt | 24 ++++++++++++++++++------
 src/namedef.h        |  1 +
 src/p_udmf.cpp       |  3 +++
 3 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt
index 112e54bfc..379f1aefa 100644
--- a/specs/udmf_zdoom.txt
+++ b/specs/udmf_zdoom.txt
@@ -216,13 +216,22 @@ Note: All <bool> fields default to false unless mentioned otherwise.
       ceilingterrain = <string>;      // Sets the terrain for the sector's ceiling. Default = 'use the flat texture's terrain definition.'
 	  floor_reflect = <float>;        // reflectiveness of floor (OpenGL only, not functional on sloped sectors)
 	  ceiling_reflect = <float>;      // reflectiveness of ceiling (OpenGL only, not functional on sloped sectors)
-	  floorglowcolor = <integer>;     // Sector's floor glow color as RRGGBB value, default = 'use texture's definition'. Set to -1 to disable glowing.
-	  floorglowheight = <float>;      // Height of floor glow. This only has an effect for the sector's own glow color, but not for a texture based glow.
-	  ceilingglowcolor = <integer>;   // Sector's ceiling glow color as RRGGBB value, default = 'use texture's definition'. Set to -1 to disable glowing.
-	  ceilingglowheight = <float>;    // Height of ceiling glow. This only has an effect for the sector's own glow color, but not for a texture based glow.
 	  fogdensity = <integer>;         // Sets an explicit fog density for the sector, overriding the default calculation from the light level. Value range is 0-510,
 	                                  // 0 meaning that the default is to be used, 2 equalling the density of a light level of 250, and 255 equalling the density of
-	                                  // a light level of 0.
+	                                  // a light level of 0.  (OpenGL only)
+	  floorglowcolor = <integer>;     // Sector's floor glow color as RRGGBB value, default = 'use texture's definition'. Set to -1 to disable glowing. (OpenGL 3.x and newer only)
+	  floorglowheight = <float>;      // Height of floor glow. This only has an effect for the sector's own glow color, but not for a texture based glow. (OpenGL 3.x and newer only)
+	  ceilingglowcolor = <integer>;   // Sector's ceiling glow color as RRGGBB value, default = 'use texture's definition'. Set to -1 to disable glowing. (OpenGL 3.x and newer only)
+	  ceilingglowheight = <float>;    // Height of ceiling glow. This only has an effect for the sector's own glow color, but not for a texture based glow. (OpenGL 3.x and newer only)
+	  color_floor = <int>;            // Material color of sector's floor (OpenGL only, dynamic lighting only works properly in OpenGL 3.x and later) Default is white (0xffffff)
+	  color_ceiling = <int>;          // Material color of sector's ceiling (OpenGL only, dynamic lighting only works properly in OpenGL 3.x and later) Default is white (0xffffff)
+	  color_walltop = <int>;          // Material color of top of sector's sidedefs (OpenGL only, dynamic lighting only works properly in OpenGL 3.x and later, 
+	                                     in OpenGL 2.x this will define the entire wall's color) Default is white (0xffffff)
+	  color_wallbottom = <int>;       // Material color of bottom of sector's sidedefs (OpenGL 3.x and later only) Default is white (0xffffff)
+	  color_sprites = <int>;          // Material color of sprites in sector (OpenGL only.) Default is white (0xffffff)
+	  color_absolute = <bool>         // treats the above properties as absolute, i.e. final light level is only defined by the color, the sector's light level is ignored
+	                                     for calculating the light color. The sector's light level is only used for fog density calculations.)
+									  
 
       portal_ceil_blocksound = <bool> // ceiling portal blocks sound.
       portal_ceil_disabled = <bool>   // ceiling portal disabled.
@@ -413,9 +422,12 @@ Added 'moreids' for linedefs and sectors.
 added clarification about character encoding
 added sector damage properties.
 
-1.27 05.01.2016
+1.27 05.01.2017
 floor_reflect and ceiling_reflect.
 
+1.28 28.01.2017
+sector material colors.
+
 ===============================================================================
 EOF
 ===============================================================================
diff --git a/src/namedef.h b/src/namedef.h
index ef7f1c58d..65719d175 100644
--- a/src/namedef.h
+++ b/src/namedef.h
@@ -554,6 +554,7 @@ xx(Color_Ceiling)
 xx(Color_Walltop)
 xx(Color_Wallbottom)
 xx(Color_Sprites)
+xx(Color_Absolute)
 xx(Desaturation)
 xx(SoundSequence)
 xx(Silent)
diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp
index 6c732d67f..0998f5204 100644
--- a/src/p_udmf.cpp
+++ b/src/p_udmf.cpp
@@ -1480,6 +1480,9 @@ public:
 					sec->SpecialColors[sector_t::sprites] = CheckInt(key) || 0xff000000;
 					break;
 
+				case NAME_Color_Absolute:
+					Flag(sec->MoreFlags, SECF_SPECIALCOLORSABSOLUTE, key);
+
 				case NAME_Desaturation:
 					desaturation = int(255*CheckFloat(key));
 					continue;

From 95afc97d48f320dae8bbe0dd150918af251574ac Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Sat, 28 Jan 2017 21:42:58 +0100
Subject: [PATCH 10/11] - ok, that color_absolute option was pretty much
 redundant, considering that it is already possible to explicitly set a fog
 density per sector - it was only necessary to give that priority over
 standard depth fade calculations for fog-less sectors.

---
 specs/udmf_zdoom.txt           | 4 +---
 src/gl/scene/gl_flats.cpp      | 4 ++--
 src/gl/scene/gl_sprite.cpp     | 4 ++--
 src/gl/scene/gl_walls_draw.cpp | 4 ++--
 src/gl/scene/gl_weapon.cpp     | 2 +-
 src/namedef.h                  | 1 -
 src/p_udmf.cpp                 | 3 ---
 src/r_defs.h                   | 1 -
 8 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt
index 379f1aefa..797d092ef 100644
--- a/specs/udmf_zdoom.txt
+++ b/specs/udmf_zdoom.txt
@@ -229,9 +229,7 @@ Note: All <bool> fields default to false unless mentioned otherwise.
 	                                     in OpenGL 2.x this will define the entire wall's color) Default is white (0xffffff)
 	  color_wallbottom = <int>;       // Material color of bottom of sector's sidedefs (OpenGL 3.x and later only) Default is white (0xffffff)
 	  color_sprites = <int>;          // Material color of sprites in sector (OpenGL only.) Default is white (0xffffff)
-	  color_absolute = <bool>         // treats the above properties as absolute, i.e. final light level is only defined by the color, the sector's light level is ignored
-	                                     for calculating the light color. The sector's light level is only used for fog density calculations.)
-									  
+							  
 
       portal_ceil_blocksound = <bool> // ceiling portal blocks sound.
       portal_ceil_disabled = <bool>   // ceiling portal disabled.
diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp
index a1f5f989c..1ed0fecfa 100644
--- a/src/gl/scene/gl_flats.cpp
+++ b/src/gl/scene/gl_flats.cpp
@@ -377,7 +377,7 @@ void GLFlat::Draw(int pass, bool trans)	// trans only has meaning for GLPASS_LIG
 	{
 	case GLPASS_PLAIN:			// Single-pass rendering
 	case GLPASS_ALL:			// Same, but also creates the dynlight data.
-		gl_SetColor((sector->MoreFlags & SECF_SPECIALCOLORSABSOLUTE) ? 255 : lightlevel, rel, Colormap,1.0f);
+		gl_SetColor(lightlevel, rel, Colormap,1.0f);
 		gl_SetFog(lightlevel, rel, &Colormap, false);
 		gl_RenderState.SetObjectColor(FlatColor | 0xff000000);
 		if (sector->special != GLSector_Skybox)
@@ -404,7 +404,7 @@ void GLFlat::Draw(int pass, bool trans)	// trans only has meaning for GLPASS_LIG
 
 	case GLPASS_TRANSLUCENT:
 		if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE);
-		gl_SetColor((sector->MoreFlags & SECF_SPECIALCOLORSABSOLUTE) ? 255 : lightlevel, rel, Colormap, alpha);
+		gl_SetColor(lightlevel, rel, Colormap, alpha);
 		gl_SetFog(lightlevel, rel, &Colormap, false);
 		gl_RenderState.SetObjectColor(FlatColor | 0xff000000);
 		if (!gltexture)
diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp
index 5ddaab7e5..1a69ca8ac 100644
--- a/src/gl/scene/gl_sprite.cpp
+++ b/src/gl/scene/gl_sprite.cpp
@@ -332,7 +332,7 @@ void GLSprite::Draw(int pass)
 			ThingColor.b * actor->Sector->SpecialColors[sector_t::sprites].b / 255);
 
 		gl_RenderState.SetObjectColor(finalcol);
-		gl_SetColor((actor->Sector->MoreFlags & SECF_SPECIALCOLORSABSOLUTE) ? 255 : lightlevel, rel, Colormap, trans);
+		gl_SetColor(lightlevel, rel, Colormap, trans);
 	}
 
 
@@ -401,7 +401,7 @@ void GLSprite::Draw(int pass)
 				thiscm.Decolorize();
 			}
 
-			gl_SetColor((actor->Sector->MoreFlags & SECF_SPECIALCOLORSABSOLUTE) ? 255 : thisll, rel, thiscm, trans);
+			gl_SetColor(thisll, rel, thiscm, trans);
 			if (!foglayer)
 			{
 				gl_SetFog(thislight, rel, &thiscm, additivefog);
diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp
index 05461fd55..34a4cc282 100644
--- a/src/gl/scene/gl_walls_draw.cpp
+++ b/src/gl/scene/gl_walls_draw.cpp
@@ -347,7 +347,7 @@ void GLWall::RenderTextured(int rflags)
 	if (lightlist == NULL)
 	{
 		if (type != RENDERWALL_M2SNF) gl_SetFog(lightlevel, rel, &Colormap, RenderStyle == STYLE_Add);
-		gl_SetColor((seg->frontsector->MoreFlags & SECF_SPECIALCOLORSABSOLUTE)? 255 : lightlevel, rel, Colormap, absalpha);
+		gl_SetColor(lightlevel, rel, Colormap, absalpha);
 		RenderWall(rflags);
 	}
 	else
@@ -367,7 +367,7 @@ void GLWall::RenderTextured(int rflags)
 				FColormap thiscm;
 				thiscm.FadeColor = Colormap.FadeColor;
 				thiscm.CopyFrom3DLight(&(*lightlist)[i]);
-				gl_SetColor((seg->frontsector->MoreFlags & SECF_SPECIALCOLORSABSOLUTE) ? 255 : thisll, rel, thiscm, absalpha);
+				gl_SetColor(thisll, rel, thiscm, absalpha);
 				if (type != RENDERWALL_M2SNF) gl_SetFog(thisll, rel, &thiscm, RenderStyle == STYLE_Add);
 				gl_RenderState.SetSplitPlanes((*lightlist)[i].plane, lowplane);
 				RenderWall(rflags);
diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp
index 6260627ba..62a051e58 100644
--- a/src/gl/scene/gl_weapon.cpp
+++ b/src/gl/scene/gl_weapon.cpp
@@ -417,7 +417,7 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
 				{
 					gl_SetDynSpriteLight(playermo, NULL);
 				}
-				gl_SetColor((viewsector->MoreFlags & SECF_SPECIALCOLORSABSOLUTE) ? 255 : ll, 0, cmc, trans, true);
+				gl_SetColor(ll, 0, cmc, trans, true);
 			}
 
 			if (psp->firstTic)
diff --git a/src/namedef.h b/src/namedef.h
index 65719d175..ef7f1c58d 100644
--- a/src/namedef.h
+++ b/src/namedef.h
@@ -554,7 +554,6 @@ xx(Color_Ceiling)
 xx(Color_Walltop)
 xx(Color_Wallbottom)
 xx(Color_Sprites)
-xx(Color_Absolute)
 xx(Desaturation)
 xx(SoundSequence)
 xx(Silent)
diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp
index 0998f5204..6c732d67f 100644
--- a/src/p_udmf.cpp
+++ b/src/p_udmf.cpp
@@ -1480,9 +1480,6 @@ public:
 					sec->SpecialColors[sector_t::sprites] = CheckInt(key) || 0xff000000;
 					break;
 
-				case NAME_Color_Absolute:
-					Flag(sec->MoreFlags, SECF_SPECIALCOLORSABSOLUTE, key);
-
 				case NAME_Desaturation:
 					desaturation = int(255*CheckFloat(key));
 					continue;
diff --git a/src/r_defs.h b/src/r_defs.h
index ff5cdd690..b888864b4 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -479,7 +479,6 @@ enum
 	SECF_UNDERWATERMASK	= 32+64,
 	SECF_DRAWN			= 128,	// sector has been drawn at least once
 	SECF_HIDDEN			= 256,	// Do not draw on textured automap
-	SECF_SPECIALCOLORSABSOLUTE = 512,	// The special colors ignore the light level except for fog density.
 };
 
 enum

From 4f5d5d5de78f15581144a189a69aa1b8ef5d4435 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Sat, 28 Jan 2017 21:49:52 +0100
Subject: [PATCH 11/11] - this should have been in the last commit.

---
 src/gl/renderer/gl_lightdata.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/gl/renderer/gl_lightdata.cpp b/src/gl/renderer/gl_lightdata.cpp
index 3ba557737..b0dccbcba 100644
--- a/src/gl/renderer/gl_lightdata.cpp
+++ b/src/gl/renderer/gl_lightdata.cpp
@@ -304,6 +304,11 @@ float gl_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity)
 		// uses approximations of Legacy's default settings.
 		density = fogdensity ? fogdensity : 18;
 	}
+	else if (sectorfogdensity != 0)
+	{
+		// case 2: Sector has an explicit fog density set.
+		density = sectorfogdensity;
+	}
 	else if ((fogcolor.d & 0xffffff) == 0)
 	{
 		// case 1: black fog
@@ -316,11 +321,6 @@ float gl_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity)
 			density = 0;
 		}
 	}
-	else if (sectorfogdensity != 0)
-	{
-		// case 2: Sector has an explicit fog density set.
-		density = sectorfogdensity;
-	}
 	else if (outsidefogdensity != 0 && outsidefogcolor.a != 0xff && (fogcolor.d & 0xffffff) == (outsidefogcolor.d & 0xffffff))
 	{
 		// case 3. outsidefogdensity has already been set as needed