From b8bcbe819be221b9fed81615158fdcc0dda2e861 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@zdoom.fake>
Date: Tue, 15 Jul 2014 20:49:21 +0200
Subject: [PATCH] - removed texture based dynamic lighting. For GL 3.x the
 shader approach is always better. - fixed: sky fog was not unset.

---
 src/gl/dynlights/a_dynlight.cpp   |  19 +--
 src/gl/dynlights/gl_dynlight.h    |   2 -
 src/gl/dynlights/gl_dynlight1.cpp | 108 -------------
 src/gl/renderer/gl_renderer.cpp   |   4 +-
 src/gl/renderer/gl_renderer.h     |   3 +-
 src/gl/scene/gl_drawinfo.h        |  22 +--
 src/gl/scene/gl_flats.cpp         | 163 ++------------------
 src/gl/scene/gl_portal.cpp        |   2 +-
 src/gl/scene/gl_scene.cpp         |  97 +-----------
 src/gl/scene/gl_skydome.cpp       |   1 +
 src/gl/scene/gl_sprite.cpp        |   2 +-
 src/gl/scene/gl_spritelight.cpp   |  55 ++++---
 src/gl/scene/gl_wall.h            |   2 +-
 src/gl/scene/gl_walls.cpp         |  52 +------
 src/gl/scene/gl_walls_draw.cpp    | 248 ++++++++----------------------
 src/r_defs.h                      |   6 +-
 wadsrc/static/glstuff/gllight.png | Bin 13073 -> 0 bytes
 17 files changed, 129 insertions(+), 657 deletions(-)
 delete mode 100644 wadsrc/static/glstuff/gllight.png

diff --git a/src/gl/dynlights/a_dynlight.cpp b/src/gl/dynlights/a_dynlight.cpp
index b462b62ac..bcc126ecf 100644
--- a/src/gl/dynlights/a_dynlight.cpp
+++ b/src/gl/dynlights/a_dynlight.cpp
@@ -521,14 +521,12 @@ void ADynamicLight::CollectWithinRadius(subsector_t *subSec, float radius)
 {
 	if (!subSec) return;
 
-	bool additive = (flags4&MF4_ADDITIVE) || gl_lights_additive;
-
 	subSec->validcount = ::validcount;
 
-	touching_subsectors = AddLightNode(&subSec->lighthead[additive], subSec, this, touching_subsectors);
+	touching_subsectors = AddLightNode(&subSec->lighthead, subSec, this, touching_subsectors);
 	if (subSec->sector->validcount != ::validcount)
 	{
-		touching_sector = AddLightNode(&subSec->render_sector->lighthead[additive], subSec->sector, this, touching_sector);
+		touching_sector = AddLightNode(&subSec->render_sector->lighthead, subSec->sector, this, touching_sector);
 		subSec->sector->validcount = ::validcount;
 	}
 
@@ -542,7 +540,7 @@ void ADynamicLight::CollectWithinRadius(subsector_t *subSec, float radius)
 			if (DMulScale32 (y-seg->v1->y, seg->v2->x-seg->v1->x, seg->v1->x-x, seg->v2->y-seg->v1->y) <=0)
 			{
 				seg->linedef->validcount=validcount;
-				touching_sides = AddLightNode(&seg->sidedef->lighthead[additive], seg->sidedef, this, touching_sides);
+				touching_sides = AddLightNode(&seg->sidedef->lighthead, seg->sidedef, this, touching_sides);
 			}
 		}
 
@@ -755,22 +753,15 @@ CCMD(listsublights)
 	{
 		subsector_t *sub = &subsectors[i];
 		int lights = 0;
-		int addlights = 0;
 
-		FLightNode * node = sub->lighthead[0];
+		FLightNode * node = sub->lighthead;
 		while (node != NULL)
 		{
 			lights++;
 			node = node->nextLight;
 		}
 
-		node = sub->lighthead[1];
-		while (node != NULL)
-		{
-			addlights++;
-			node = node->nextLight;
-		}
-		Printf(PRINT_LOG, "Subsector %d - %d lights, %d additive lights\n", i, lights, addlights);
+		Printf(PRINT_LOG, "Subsector %d - %d lights\n", i, lights);
 	}
 }
 
diff --git a/src/gl/dynlights/gl_dynlight.h b/src/gl/dynlights/gl_dynlight.h
index 37cbc4f93..568630898 100644
--- a/src/gl/dynlights/gl_dynlight.h
+++ b/src/gl/dynlights/gl_dynlight.h
@@ -184,8 +184,6 @@ struct FDynLightData
 
 
 bool gl_GetLight(Plane & p, ADynamicLight * light, bool checkside, bool forceadditive, FDynLightData &data);
-bool gl_SetupLight(Plane & p, ADynamicLight * light, Vector & nearPt, Vector & up, Vector & right, float & scale, int desaturation, bool checkside=true, bool forceadditive=true);
-bool gl_SetupLightTexture();
 void gl_UploadLights(FDynLightData &data);
 
 
diff --git a/src/gl/dynlights/gl_dynlight1.cpp b/src/gl/dynlights/gl_dynlight1.cpp
index 42053e8a5..cee31ee42 100644
--- a/src/gl/dynlights/gl_dynlight1.cpp
+++ b/src/gl/dynlights/gl_dynlight1.cpp
@@ -68,17 +68,6 @@ CUSTOM_CVAR (Bool, gl_lights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOIN
 	else gl_DeleteAllAttachedLights();
 }
 
-CUSTOM_CVAR (Bool, gl_dynlight_shader, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
-{
-	if (self)
-	{
-		if (gl.maxuniforms < 1024 && !(gl.flags & RFL_SHADER_STORAGE_BUFFER))
-		{
-			self = false;
-		}
-	}
-}
-
 CVAR (Bool, gl_attachedlights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
 CVAR (Bool, gl_lights_checkside, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
 CVAR (Float, gl_lights_intensity, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
@@ -155,75 +144,6 @@ bool gl_GetLight(Plane & p, ADynamicLight * light, bool checkside, bool forceadd
 }
 
 
-//==========================================================================
-//
-// Sets up the parameters to render one dynamic light onto one plane
-//
-//==========================================================================
-bool gl_SetupLight(Plane & p, ADynamicLight * light, Vector & nearPt, Vector & up, Vector & right, 
-				   float & scale, int desaturation, bool checkside, bool forceadditive)
-{
-	Vector fn, pos;
-
-    float x = FIXED2FLOAT(light->x);
-	float y = FIXED2FLOAT(light->y);
-	float z = FIXED2FLOAT(light->z);
-	
-	float dist = fabsf(p.DistToPoint(x, z, y));
-	float radius = (light->GetRadius() * gl_lights_size);
-	
-	if (radius <= 0.f) return false;
-	if (dist > radius) return false;
-	if (checkside && gl_lights_checkside && p.PointOnSide(x, z, y))
-	{
-		return false;
-	}
-	if (light->owned && light->target != NULL && !light->target->IsVisibleToPlayer())
-	{
-		return false;
-	}
-
-	scale = 1.0f / ((2.f * radius) - dist);
-
-	// project light position onto plane (find closest point on plane)
-
-
-	pos.Set(x,z,y);
-	fn=p.Normal();
-	fn.GetRightUp(right, up);
-
-#ifdef _MSC_VER
-	nearPt = pos + fn * dist;
-#else
-	Vector tmpVec = fn * dist;
-	nearPt = pos + tmpVec;
-#endif
-
-	float cs = 1.0f - (dist / radius);
-	if (gl_lights_additive || light->flags4&MF4_ADDITIVE || forceadditive) cs*=0.2f;	// otherwise the light gets too strong.
-	float r = light->GetRed() / 255.0f * cs * gl_lights_intensity;
-	float g = light->GetGreen() / 255.0f * cs * gl_lights_intensity;
-	float b = light->GetBlue() / 255.0f * cs * gl_lights_intensity;
-
-	if (light->IsSubtractive())
-	{
-		Vector v;
-		
-		gl_RenderState.BlendEquation(GL_FUNC_REVERSE_SUBTRACT);
-		v.Set(r, g, b);
-		r = v.Length() - r;
-		g = v.Length() - g;
-		b = v.Length() - b;
-	}
-	else
-	{
-		gl_RenderState.BlendEquation(GL_FUNC_ADD);
-	}
-	gl_RenderState.SetColor(r, g, b, 1.f, desaturation);
-	return true;
-}
-
-
 //==========================================================================
 //
 //
@@ -257,31 +177,3 @@ void gl_UploadLights(FDynLightData &data)
 	}
 }
 #endif
-
-//==========================================================================
-//
-//
-//
-//==========================================================================
-
-bool gl_SetupLightTexture()
-{
-
-	if (GLRenderer->gllight == NULL) return false;
-	FMaterial * pat = FMaterial::ValidateTexture(GLRenderer->gllight);
-	pat->BindPatch(0);
-	return true;
-}
-
-
-//==========================================================================
-//
-//
-//
-//==========================================================================
-
-inline fixed_t P_AproxDistance3(fixed_t dx, fixed_t dy, fixed_t dz)
-{
-	return P_AproxDistance(P_AproxDistance(dx,dy),dz);
-}
-
diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp
index ae2ba2125..42773496e 100644
--- a/src/gl/renderer/gl_renderer.cpp
+++ b/src/gl/renderer/gl_renderer.cpp
@@ -96,7 +96,7 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
 	mSkyVBO = NULL;
 	gl_spriteindex = 0;
 	mShaderManager = NULL;
-	glpart2 = glpart = gllight = mirrortexture = NULL;
+	glpart2 = glpart = mirrortexture = NULL;
 }
 
 void FGLRenderer::Initialize()
@@ -104,7 +104,6 @@ void FGLRenderer::Initialize()
 	glpart2 = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/glpart2.png"), FTexture::TEX_MiscPatch);
 	glpart = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/glpart.png"), FTexture::TEX_MiscPatch);
 	mirrortexture = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/mirror.png"), FTexture::TEX_MiscPatch);
-	gllight = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/gllight.png"), FTexture::TEX_MiscPatch);
 
 	mVBO = new FFlatVertexBuffer;
 	mSkyVBO = new FSkyVertexBuffer;
@@ -128,7 +127,6 @@ FGLRenderer::~FGLRenderer()
 	if (glpart2) delete glpart2;
 	if (glpart) delete glpart;
 	if (mirrortexture) delete mirrortexture;
-	if (gllight) delete gllight;
 	if (mFBID != 0) glDeleteFramebuffers(1, &mFBID);
 }
 
diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h
index 733123599..a2679f665 100644
--- a/src/gl/renderer/gl_renderer.h
+++ b/src/gl/renderer/gl_renderer.h
@@ -62,8 +62,7 @@ public:
 	FTexture *glpart2;
 	FTexture *glpart;
 	FTexture *mirrortexture;
-	FTexture *gllight;
-
+	
 	float mSky1Pos, mSky2Pos;
 
 	FRotator mAngles;
diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h
index 01a72701b..f4b104392 100644
--- a/src/gl/scene/gl_drawinfo.h
+++ b/src/gl/scene/gl_drawinfo.h
@@ -13,14 +13,6 @@ enum GLDrawItemType
 
 enum DrawListType
 {
-	// These are organized so that the various multipass rendering modes
-	// have to be set as few times as possible
-	GLDL_LIGHT,	
-	GLDL_LIGHTBRIGHT,
-	GLDL_LIGHTMASKED,
-	GLDL_LIGHTFOG,
-	GLDL_LIGHTFOGMASKED,
-
 	GLDL_PLAIN,
 	GLDL_MASKED,
 	GLDL_FOG,
@@ -30,25 +22,15 @@ enum DrawListType
 	GLDL_TRANSLUCENTBORDER,
 
 	GLDL_TYPES,
-
-	GLDL_FIRSTLIGHT = GLDL_LIGHT,
-	GLDL_LASTLIGHT = GLDL_LIGHTFOGMASKED,
-	GLDL_FIRSTNOLIGHT = GLDL_PLAIN,
-	GLDL_LASTNOLIGHT = GLDL_FOGMASKED,
 };
 
 enum Drawpasses
 {
-	GLPASS_BASE,		// Draws the untextured surface only
-	GLPASS_BASE_MASKED,	// Draws an untextured surface that is masked by the texture
-	GLPASS_PLAIN,		// Draws a texture that isn't affected by dynamic lights with sector light settings
-	GLPASS_LIGHT,		// Draws dynamic lights
-	GLPASS_LIGHT_ADDITIVE,	// Draws additive dynamic lights
-	GLPASS_TEXTURE,		// Draws the texture to be modulated with the light information on the base surface
+	GLPASS_PLAIN,		// Main pass without dynamic lights
+	GLPASS_ALL,			// Main pass with dynamic lights
 	GLPASS_DECALS,		// Draws a decal
 	GLPASS_DECALS_NOFOG,// Draws a decal without setting the fog (used for passes that need a fog layer)
 	GLPASS_TRANSLUCENT,	// Draws translucent objects
-	GLPASS_ALL			// Everything at once, using shaders for dynamic lights
 };
 
 //==========================================================================
diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp
index 19eb3b9e1..2767a5e80 100644
--- a/src/gl/scene/gl_flats.cpp
+++ b/src/gl/scene/gl_flats.cpp
@@ -103,26 +103,24 @@ void gl_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * glte
 }
 
 
+
 //==========================================================================
 //
 // Flats 
 //
 //==========================================================================
+extern FDynLightData lightdata;
 
-void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass)
+bool GLFlat::SetupSubsectorLights(bool lightsapplied, subsector_t * sub)
 {
 	Plane p;
-	Vector nearPt, up, right, t1;
-	float scale;
-	unsigned int k;
-	seg_t *v;
 
-	FLightNode * node = sub->lighthead[pass==GLPASS_LIGHT_ADDITIVE];
-	gl_RenderState.Apply();
+	lightdata.Clear();
+	FLightNode * node = sub->lighthead;
 	while (node)
 	{
 		ADynamicLight * light = node->lightsource;
-		
+			
 		if (light->flags2&MF2_DORMANT)
 		{
 			node=node->nextLight;
@@ -140,72 +138,9 @@ void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass)
 		}
 
 		p.Set(plane.plane);
-		if (!gl_SetupLight(p, light, nearPt, up, right, scale, Colormap.desaturation, false, foggy)) 
-		{
-			node=node->nextLight;
-			continue;
-		}
-		draw_dlightf++;
-		gl_RenderState.Apply();
-
-		// Render the light
-		FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
-		for (k = 0, v = sub->firstline; k < sub->numlines; k++, v++)
-		{
-			vertex_t *vt = v->v1;
-			float zc = plane.plane.ZatPoint(vt->fx, vt->fy) + dz;
-
-			t1.Set(vt->fx, zc, vt->fy);
-			Vector nearToVert = t1 - nearPt;
-			ptr->Set(vt->fx, zc, vt->fy, (nearToVert.Dot(right) * scale) + 0.5f, (nearToVert.Dot(up) * scale) + 0.5f);
-			ptr++;
-		}
-		GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN);
+		gl_GetLight(p, light, false, false, lightdata);
 		node = node->nextLight;
 	}
-}
-
-
-//==========================================================================
-//
-// Flats 
-//
-//==========================================================================
-extern FDynLightData lightdata;
-
-bool GLFlat::SetupSubsectorLights(bool lightsapplied, subsector_t * sub)
-{
-	Plane p;
-
-	lightdata.Clear();
-	for(int i=0;i<2;i++)
-	{
-		FLightNode * node = sub->lighthead[i];
-		while (node)
-		{
-			ADynamicLight * light = node->lightsource;
-			
-			if (light->flags2&MF2_DORMANT)
-			{
-				node=node->nextLight;
-				continue;
-			}
-			iter_dlightf++;
-
-			// we must do the side check here because gl_SetupLight needs the correct plane orientation
-			// which we don't have for Legacy-style 3D-floors
-			fixed_t planeh = plane.plane.ZatPoint(light->x, light->y);
-			if (gl_lights_checkside && ((planeh<light->z && ceiling) || (planeh>light->z && !ceiling)))
-			{
-				node=node->nextLight;
-				continue;
-			}
-
-			p.Set(plane.plane);
-			gl_GetLight(p, light, false, false, lightdata);
-			node = node->nextLight;
-		}
-	}
 
 	int numlights[3];
 
@@ -347,7 +282,6 @@ void GLFlat::DrawSubsectors(int pass, bool istrans)
 //==========================================================================
 void GLFlat::Draw(int pass)
 {
-	int i;
 	int rel = getExtraLight();
 
 #ifdef _DEBUG
@@ -360,65 +294,15 @@ void GLFlat::Draw(int pass)
 
 	switch (pass)
 	{
-	case GLPASS_BASE:
-		gl_SetColor(lightlevel, rel, Colormap,1.0f);
-		if (!foggy) gl_SetFog(lightlevel, rel, &Colormap, false);
-		DrawSubsectors(pass, false);
-		break;
-
 	case GLPASS_PLAIN:			// Single-pass rendering
 	case GLPASS_ALL:
-	case GLPASS_BASE_MASKED:
 		gl_SetColor(lightlevel, rel, Colormap,1.0f);
-		if (!foggy || pass != GLPASS_BASE_MASKED) gl_SetFog(lightlevel, rel, &Colormap, false);
-		// fall through
-	case GLPASS_TEXTURE:
-	{
+		gl_SetFog(lightlevel, rel, &Colormap, false);
 		gltexture->Bind();
 		gl_SetPlaneTextureRotation(&plane, gltexture);
 		DrawSubsectors(pass, false);
 		gl_RenderState.EnableTextureMatrix(false);
 		break;
-	}
-
-	case GLPASS_LIGHT:
-	case GLPASS_LIGHT_ADDITIVE:
-
-		if (!foggy)	gl_SetFog((255+lightlevel)>>1, 0, &Colormap, false);
-		else gl_SetFog(lightlevel, 0, &Colormap, true);	
-
-		if (sub)
-		{
-			DrawSubsectorLights(sub, pass);
-		}
-		else
-		{
-			// Draw the subsectors belonging to this sector
-			for (i=0; i<sector->subsectorcount; i++)
-			{
-				subsector_t * sub = sector->subsectors[i];
-
-				if (gl_drawinfo->ss_renderflags[sub-subsectors]&renderflags)
-				{
-					DrawSubsectorLights(sub, pass);
-				}
-			}
-
-			// Draw the subsectors assigned to it due to missing textures
-			if (!(renderflags&SSRF_RENDER3DPLANES))
-			{
-				gl_subsectorrendernode * node = (renderflags&SSRF_RENDERFLOOR)?
-					gl_drawinfo->GetOtherFloorPlanes(sector->sectornum) :
-					gl_drawinfo->GetOtherCeilingPlanes(sector->sectornum);
-
-				while (node)
-				{
-					DrawSubsectorLights(node->sub, pass);
-					node = node->next;
-				}
-			}
-		}
-		break;
 
 	case GLPASS_TRANSLUCENT:
 		if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE);
@@ -462,38 +346,15 @@ inline void GLFlat::PutFlat(bool fog)
 	}
 	if (renderstyle!=STYLE_Translucent || alpha < 1.f - FLT_EPSILON || fog)
 	{
-		int list = (renderflags&SSRF_RENDER3DPLANES) ? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER;
-		gl_drawinfo->drawlists[list].AddFlat (this);
+		// translucent 3D floors go into the regular translucent list, translucent portals go into the translucent border list.
+		list = (renderflags&SSRF_RENDER3DPLANES) ? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER;
 	}
 	else if (gltexture != NULL)
 	{
-		static DrawListType list_indices[2][2][2]={
-			{ { GLDL_PLAIN, GLDL_FOG      }, { GLDL_MASKED,      GLDL_FOGMASKED      } },
-			{ { GLDL_LIGHT, GLDL_LIGHTFOG }, { GLDL_LIGHTMASKED, GLDL_LIGHTFOGMASKED } }
-		};
-
-		bool light = false;
 		bool masked = gltexture->isMasked() && ((renderflags&SSRF_RENDER3DPLANES) || stack);
-
-		if (!gl_fixedcolormap)
-		{
-			foggy = gl_CheckFog(&Colormap, lightlevel) || level.flags&LEVEL_HASFADETABLE;
-
-			if (gl_lights && !gl_dynlight_shader && GLRenderer->mLightCount)	// Are lights touching this sector?
-			{
-				for(int i=0;i<sector->subsectorcount;i++) if (sector->subsectors[i]->lighthead[0] != NULL)
-				{
-					light=true;
-				}
-			}
-		}
-		else foggy = false;
-
-		list = list_indices[light][masked][foggy];
-		if (list == GLDL_LIGHT && gltexture->tex->gl_info.Brightmap) list = GLDL_LIGHTBRIGHT;
-
-		gl_drawinfo->drawlists[list].AddFlat (this);
+		list = masked ? GLDL_MASKED : GLDL_PLAIN;
 	}
+	gl_drawinfo->drawlists[list].AddFlat (this);
 }
 
 //==========================================================================
diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp
index 0cc602967..afc5cf1f2 100644
--- a/src/gl/scene/gl_portal.cpp
+++ b/src/gl/scene/gl_portal.cpp
@@ -144,7 +144,7 @@ void GLPortal::DrawPortalStencil()
 
 		for (unsigned int i = 0; i<lines.Size(); i++)
 		{
-			lines[i].RenderWall(GLWall::RWF_NORENDER, NULL, &mPrimIndices[i * 2]);
+			lines[i].RenderWall(GLWall::RWF_NORENDER, &mPrimIndices[i * 2]);
 		}
 
 		if (cap)
diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp
index e6dc3098c..110a36420 100644
--- a/src/gl/scene/gl_scene.cpp
+++ b/src/gl/scene/gl_scene.cpp
@@ -351,120 +351,31 @@ void FGLRenderer::RenderScene(int recursion)
 
 	int pass;
 
-	if (mLightCount > 0 && gl_fixedcolormap == CM_DEFAULT && gl_lights && gl_dynlight_shader)
+	if (mLightCount > 0 && gl_fixedcolormap == CM_DEFAULT && gl_lights)
 	{
 		pass = GLPASS_ALL;
 	}
-	else if (gl_texture)
+	else
 	{
 		pass = GLPASS_PLAIN;
 	}
-	else
-	{
-		pass = GLPASS_BASE;
-	}
 
 	gl_RenderState.EnableTexture(gl_texture);
-	gl_RenderState.EnableBrightmap(gl_fixedcolormap == CM_DEFAULT);
+	gl_RenderState.EnableBrightmap(true);
 	gl_drawinfo->drawlists[GLDL_PLAIN].Sort();
 	gl_drawinfo->drawlists[GLDL_PLAIN].Draw(pass);
-	gl_drawinfo->drawlists[GLDL_FOG].Sort();
-	gl_drawinfo->drawlists[GLDL_FOG].Draw(pass);
-	gl_drawinfo->drawlists[GLDL_LIGHTFOG].Sort();
-	gl_drawinfo->drawlists[GLDL_LIGHTFOG].Draw(pass);
 
 
-	// Part 2: masked geometry. This is set up so that only pixels with alpha>0.5 will show
+	// Part 2: masked geometry. This is set up so that only pixels with alpha>gl_mask_threshold will show
 	if (!gl_texture) 
 	{
 		gl_RenderState.EnableTexture(true);
 		gl_RenderState.SetTextureMode(TM_MASK);
 	}
-	if (pass == GLPASS_BASE) pass = GLPASS_BASE_MASKED;
 	gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
 	gl_drawinfo->drawlists[GLDL_MASKED].Sort();
 	gl_drawinfo->drawlists[GLDL_MASKED].Draw(pass);
-	gl_drawinfo->drawlists[GLDL_FOGMASKED].Sort();
-	gl_drawinfo->drawlists[GLDL_FOGMASKED].Draw(pass);
-	gl_drawinfo->drawlists[GLDL_LIGHTFOGMASKED].Sort();
-	gl_drawinfo->drawlists[GLDL_LIGHTFOGMASKED].Draw(pass);
 
-	// And now the multipass stuff
-	if (!gl_dynlight_shader && gl_lights)
-	{
-		// First pass: empty background with sector light only
-
-		// Part 1: solid geometry. This is set up so that there are no transparent parts
-
-		// remove any remaining texture bindings and shaders whick may get in the way.
-		gl_RenderState.EnableTexture(false);
-		gl_RenderState.EnableBrightmap(false);
-		gl_RenderState.Apply();
-		gl_drawinfo->drawlists[GLDL_LIGHT].Draw(GLPASS_BASE);
-		gl_RenderState.EnableTexture(true);
-
-		// Part 2: masked geometry. This is set up so that only pixels with alpha>0.5 will show
-		// This creates a blank surface that only fills the nontransparent parts of the texture
-		gl_RenderState.SetTextureMode(TM_MASK);
-		gl_RenderState.EnableBrightmap(true);
-		gl_drawinfo->drawlists[GLDL_LIGHTBRIGHT].Draw(GLPASS_BASE_MASKED);
-		gl_drawinfo->drawlists[GLDL_LIGHTMASKED].Draw(GLPASS_BASE_MASKED);
-		gl_RenderState.EnableBrightmap(false);
-		gl_RenderState.SetTextureMode(TM_MODULATE);
-
-
-		// second pass: draw lights (on fogged surfaces they are added to the textures!)
-		glDepthMask(false);
-		if (mLightCount && !gl_fixedcolormap)
-		{
-			if (gl_SetupLightTexture())
-			{
-				gl_RenderState.BlendFunc(GL_ONE, GL_ONE);
-				glDepthFunc(GL_EQUAL);
-				gl_RenderState.SetSoftLightLevel(255);
-				for(int i=GLDL_FIRSTLIGHT; i<=GLDL_LASTLIGHT; i++)
-				{
-					gl_drawinfo->drawlists[i].Draw(GLPASS_LIGHT);
-				}
-				gl_RenderState.BlendEquation(GL_FUNC_ADD);
-			}
-			else gl_lights=false;
-		}
-
-		// third pass: modulated texture
-		gl_RenderState.ResetColor();
-		gl_RenderState.BlendFunc(GL_DST_COLOR, GL_ZERO);
-		gl_RenderState.EnableFog(false);
-		glDepthFunc(GL_LEQUAL);
-		if (gl_texture) 
-		{
-			gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
-			gl_drawinfo->drawlists[GLDL_LIGHT].Sort();
-			gl_drawinfo->drawlists[GLDL_LIGHT].Draw(GLPASS_TEXTURE);
-			gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
-			gl_drawinfo->drawlists[GLDL_LIGHTBRIGHT].Sort();
-			gl_drawinfo->drawlists[GLDL_LIGHTBRIGHT].Draw(GLPASS_TEXTURE);
-			gl_drawinfo->drawlists[GLDL_LIGHTMASKED].Sort();
-			gl_drawinfo->drawlists[GLDL_LIGHTMASKED].Draw(GLPASS_TEXTURE);
-		}
-
-		// fourth pass: additive lights
-		gl_RenderState.EnableFog(true);
-		if (gl_lights && mLightCount && !gl_fixedcolormap)
-		{
-			gl_RenderState.BlendFunc(GL_ONE, GL_ONE);
-			glDepthFunc(GL_EQUAL);
-			if (gl_SetupLightTexture())
-			{
-				for(int i=0; i<GLDL_TRANSLUCENT; i++)
-				{
-					gl_drawinfo->drawlists[i].Draw(GLPASS_LIGHT_ADDITIVE);
-				}
-				gl_RenderState.BlendEquation(GL_FUNC_ADD);
-			}
-			else gl_lights=false;
-		}
-	}
 
 	gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
diff --git a/src/gl/scene/gl_skydome.cpp b/src/gl/scene/gl_skydome.cpp
index a2c0cf981..d0932a89f 100644
--- a/src/gl/scene/gl_skydome.cpp
+++ b/src/gl/scene/gl_skydome.cpp
@@ -511,6 +511,7 @@ void GLSkyPortal::DrawContents()
 			gl_RenderState.Apply();
 			glDrawArrays(GL_TRIANGLES, 0, 12);
 			gl_RenderState.EnableTexture(true);
+			gl_RenderState.SetObjectColor(0xffffffff);
 		}
 		gl_RenderState.SetVertexBuffer(GLRenderer->mVBO);
 	}
diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp
index c70422b32..554b8ff1f 100644
--- a/src/gl/scene/gl_sprite.cpp
+++ b/src/gl/scene/gl_sprite.cpp
@@ -112,7 +112,7 @@ CVAR(Bool, gl_nolayer, false, 0)
 //==========================================================================
 void GLSprite::Draw(int pass)
 {
-	if (pass!=GLPASS_PLAIN && pass != GLPASS_ALL && pass!=GLPASS_TRANSLUCENT) return;
+	if (pass == GLPASS_DECALS) return;
 
 
 
diff --git a/src/gl/scene/gl_spritelight.cpp b/src/gl/scene/gl_spritelight.cpp
index e4e2e855a..e66941283 100644
--- a/src/gl/scene/gl_spritelight.cpp
+++ b/src/gl/scene/gl_spritelight.cpp
@@ -71,47 +71,44 @@ void gl_SetDynSpriteLight(AActor *self, fixed_t x, fixed_t y, fixed_t z, subsect
 	float out[3] = { 0.0f, 0.0f, 0.0f };
 	
 	// Go through both light lists
-	for (int i = 0; i < 2; i++)
+	FLightNode * node = subsec->lighthead;
+	while (node)
 	{
-		FLightNode * node = subsec->lighthead[i];
-		while (node)
+		light=node->lightsource;
+		if (!light->owned || light->target == NULL || light->target->IsVisibleToPlayer())
 		{
-			light = node->lightsource;
-			if (!light->owned || light->target == NULL || light->target->IsVisibleToPlayer())
+			if (!(light->flags2&MF2_DORMANT) &&
+				(!(light->flags4&MF4_DONTLIGHTSELF) || light->target != self))
 			{
-				if (!(light->flags2&MF2_DORMANT) &&
-					(!(light->flags4&MF4_DONTLIGHTSELF) || light->target != self))
+				float dist = FVector3(FIXED2FLOAT(x - light->x), FIXED2FLOAT(y - light->y), FIXED2FLOAT(z - light->z)).Length();
+				radius = light->GetRadius() * gl_lights_size;
+
+				if (dist < radius)
 				{
-					float dist = FVector3(FIXED2FLOAT(x - light->x), FIXED2FLOAT(y - light->y), FIXED2FLOAT(z - light->z)).Length();
-					radius = light->GetRadius() * gl_lights_size;
+					frac = 1.0f - (dist / radius);
 
-					if (dist < radius)
+					if (frac > 0)
 					{
-						frac = 1.0f - (dist / radius);
-
-						if (frac > 0)
+						lr = light->GetRed() / 255.0f * gl_lights_intensity;
+						lg = light->GetGreen() / 255.0f * gl_lights_intensity;
+						lb = light->GetBlue() / 255.0f * gl_lights_intensity;
+						if (light->IsSubtractive())
 						{
-							lr = light->GetRed() / 255.0f * gl_lights_intensity;
-							lg = light->GetGreen() / 255.0f * gl_lights_intensity;
-							lb = light->GetBlue() / 255.0f * gl_lights_intensity;
-							if (light->IsSubtractive())
-							{
-								float bright = FVector3(lr, lg, lb).Length();
-								FVector3 lightColor(lr, lg, lb);
-								lr = (bright - lr) * -1;
-								lg = (bright - lg) * -1;
-								lb = (bright - lb) * -1;
-							}
-
-							out[0] += lr * frac;
-							out[1] += lg * frac;
-							out[2] += lb * frac;
+							float bright = FVector3(lr, lg, lb).Length();
+							FVector3 lightColor(lr, lg, lb);
+							lr = (bright - lr) * -1;
+							lg = (bright - lg) * -1;
+							lb = (bright - lb) * -1;
 						}
+
+						out[0] += lr * frac;
+						out[1] += lg * frac;
+						out[2] += lb * frac;
 					}
 				}
 			}
-			node = node->nextLight;
 		}
+		node = node->nextLight;
 	}
 	gl_RenderState.SetDynLight(out[0], out[1], out[2]);
 }
diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h
index 28fa51868..fe2ec6e8e 100644
--- a/src/gl/scene/gl_wall.h
+++ b/src/gl/scene/gl_wall.h
@@ -169,7 +169,7 @@ private:
 
 	void SetupLights();
 	bool PrepareLight(texcoord * tcs, ADynamicLight * light);
-	void RenderWall(int textured, ADynamicLight * light=NULL, unsigned int *store = NULL);
+	void RenderWall(int textured, unsigned int *store = NULL);
 
 	void FloodPlane(int pass);
 
diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp
index f720f1678..60e9287bf 100644
--- a/src/gl/scene/gl_walls.cpp
+++ b/src/gl/scene/gl_walls.cpp
@@ -114,9 +114,8 @@ void GLWall::PutWall(bool translucent)
 		4,		//RENDERWALL_SECTORSTACK,      // special
 		4,		//RENDERWALL_PLANEMIRROR,      // special
 		4,		//RENDERWALL_MIRROR,           // special
-		1,		//RENDERWALL_MIRRORSURFACE,    // needs special handling
-		2,		//RENDERWALL_M2SNF,            // depends on render and texture settings, no fog
-		2,		//RENDERWALL_M2SFOG,            // depends on render and texture settings, no fog
+		1,		//RENDERWALL_MIRRORSURFACE,    // only created here from RENDERWALL_MIRROR
+		2,		//RENDERWALL_M2SNF,            // depends on render and texture settings, no fog, used on mid texture lines with a fog boundary.
 		3,		//RENDERWALL_COLOR,            // translucent
 		2,		//RENDERWALL_FFBLOCK           // depends on render and texture settings
 		4,		//RENDERWALL_COLORLAYER        // color layer needs special handling
@@ -145,47 +144,11 @@ void GLWall::PutWall(bool translucent)
 	}
 	else if (passflag[type]!=4)	// non-translucent walls
 	{
-		static DrawListType list_indices[2][2][2]={
-			{ { GLDL_PLAIN, GLDL_FOG      }, { GLDL_MASKED,      GLDL_FOGMASKED      } },
-			{ { GLDL_LIGHT, GLDL_LIGHTFOG }, { GLDL_LIGHTMASKED, GLDL_LIGHTFOGMASKED } }
-		};
 
 		bool masked;
-		bool light = false;
 
-		if (!gl_fixedcolormap)
-		{
-			if (gl_lights && !gl_dynlight_shader)
-			{
-				if (seg->sidedef == NULL)
-				{
-					light = false;
-				}
-				else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
-				{
-					light = seg->sidedef->lighthead[0] != NULL;
-				}
-				else if (sub)
-				{
-					// for polyobjects we cannot use the side's light list. 
-					// We must use the subsector's.
-					light = sub->lighthead[0] != NULL;
-				}
-			}
-		}
-		else 
-		{
-			flags&=~GLWF_FOGGY;
-		}
-
-		masked = passflag[type]==1? false : (light && type!=RENDERWALL_FFBLOCK) || (gltexture && gltexture->isMasked());
-
-		list = list_indices[light][masked][!!(flags&GLWF_FOGGY)];
-		if (list == GLDL_LIGHT)
-		{
-			if (gltexture->tex->gl_info.Brightmap) list = GLDL_LIGHTBRIGHT;
-			if (flags & GLWF_GLOW) list = GLDL_LIGHTBRIGHT;
-		}
+		masked = passflag[type]==1? false : (gltexture && gltexture->isMasked());
+		list = masked ? GLDL_MASKED : GLDL_PLAIN;
 		gl_drawinfo->drawlists[list].AddWall(this);
 
 	}
@@ -1514,11 +1477,12 @@ void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector)
 	glseg.x2= FIXED2FLOAT(v2->x);
 	glseg.y2= FIXED2FLOAT(v2->y);
 	Colormap=frontsector->ColorMap;
-	flags = (!gl_isBlack(Colormap.FadeColor) || level.flags&LEVEL_HASFADETABLE)? GLWF_FOGGY : 0;
+	flags = 0;
 
 	int rel = 0;
 	int orglightlevel = gl_ClampLight(frontsector->lightlevel);
-	lightlevel = gl_ClampLight(seg->sidedef->GetLightLevel(!!(flags&GLWF_FOGGY), orglightlevel, false, &rel));
+	bool foggy = (!gl_isBlack(Colormap.FadeColor) || level.flags&LEVEL_HASFADETABLE);	// fog disables fake contrast
+	lightlevel = gl_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, false, &rel));
 	if (orglightlevel >= 253)			// with the software renderer fake contrast won't be visible above this.
 	{
 		rellight = 0;					
@@ -1764,7 +1728,7 @@ void GLWall::ProcessLowerMiniseg(seg_t *seg, sector_t * frontsector, sector_t *
 		glseg.fracleft = 0;
 		glseg.fracright = 1;
 
-		flags = (!gl_isBlack(Colormap.FadeColor) || level.flags&LEVEL_HASFADETABLE)? GLWF_FOGGY : 0;
+		flags = 0;
 
 		// can't do fake contrast without a sidedef
 		lightlevel = gl_ClampLight(frontsector->lightlevel);
diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp
index e28f6315c..8cdae097a 100644
--- a/src/gl/scene/gl_walls_draw.cpp
+++ b/src/gl/scene/gl_walls_draw.cpp
@@ -62,57 +62,6 @@
 
 EXTERN_CVAR(Bool, gl_seamless)
 
-//==========================================================================
-//
-// Sets up the texture coordinates for one light to be rendered
-//
-//==========================================================================
-bool GLWall::PrepareLight(texcoord * tcs, ADynamicLight * light)
-{
-	float vtx[]={glseg.x1,zbottom[0],glseg.y1, glseg.x1,ztop[0],glseg.y1, glseg.x2,ztop[1],glseg.y2, glseg.x2,zbottom[1],glseg.y2};
-	Plane p;
-	Vector nearPt, up, right;
-	float scale;
-
-	p.Init(vtx,4);
-
-	if (!p.ValidNormal()) 
-	{
-		return false;
-	}
-
-	if (!gl_SetupLight(p, light, nearPt, up, right, scale, Colormap.desaturation, true, !!(flags&GLWF_FOGGY))) 
-	{
-		return false;
-	}
-
-	if (tcs != NULL)
-	{
-		Vector t1;
-		int outcnt[4]={0,0,0,0};
-
-		for(int i=0;i<4;i++)
-		{
-			t1.Set(&vtx[i*3]);
-			Vector nearToVert = t1 - nearPt;
-			tcs[i].u = (nearToVert.Dot(right) * scale) + 0.5f;
-			tcs[i].v = (nearToVert.Dot(up) * scale) + 0.5f;
-
-			// quick check whether the light touches this polygon
-			if (tcs[i].u<0) outcnt[0]++;
-			if (tcs[i].u>1) outcnt[1]++;
-			if (tcs[i].v<0) outcnt[2]++;
-			if (tcs[i].v>1) outcnt[3]++;
-
-		}
-		// The light doesn't touch this polygon
-		if (outcnt[0]==4 || outcnt[1]==4 || outcnt[2]==4 || outcnt[3]==4) return false;
-	}
-
-	draw_dlight++;
-	return true;
-}
-
 //==========================================================================
 //
 // Collect lights for shader
@@ -132,77 +81,74 @@ void GLWall::SetupLights()
 	{
 		return;
 	}
-	for(int i=0;i<2;i++)
+	FLightNode *node;
+	if (seg->sidedef == NULL)
 	{
-		FLightNode *node;
-		if (seg->sidedef == NULL)
-		{
-			node = NULL;
-		}
-		else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
-		{
-			node = seg->sidedef->lighthead[i];
-		}
-		else if (sub)
-		{
-			// Polobject segs cannot be checked per sidedef so use the subsector instead.
-			node = sub->lighthead[i];
-		}
-		else node = NULL;
+		node = NULL;
+	}
+	else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
+	{
+		node = seg->sidedef->lighthead;
+	}
+	else if (sub)
+	{
+		// Polobject segs cannot be checked per sidedef so use the subsector instead.
+		node = sub->lighthead;
+	}
+	else node = NULL;
 
-		// Iterate through all dynamic lights which touch this wall and render them
-		while (node)
+	// Iterate through all dynamic lights which touch this wall and render them
+	while (node)
+	{
+		if (!(node->lightsource->flags2&MF2_DORMANT))
 		{
-			if (!(node->lightsource->flags2&MF2_DORMANT))
+			iter_dlight++;
+
+			Vector fn, pos;
+
+			float x = FIXED2FLOAT(node->lightsource->x);
+			float y = FIXED2FLOAT(node->lightsource->y);
+			float z = FIXED2FLOAT(node->lightsource->z);
+			float dist = fabsf(p.DistToPoint(x, z, y));
+			float radius = (node->lightsource->GetRadius() * gl_lights_size);
+			float scale = 1.0f / ((2.f * radius) - dist);
+
+			if (radius > 0.f && dist < radius)
 			{
-				iter_dlight++;
+				Vector nearPt, up, right;
 
-				Vector fn, pos;
+				pos.Set(x,z,y);
+				fn=p.Normal();
+				fn.GetRightUp(right, up);
 
-				float x = FIXED2FLOAT(node->lightsource->x);
-				float y = FIXED2FLOAT(node->lightsource->y);
-				float z = FIXED2FLOAT(node->lightsource->z);
-				float dist = fabsf(p.DistToPoint(x, z, y));
-				float radius = (node->lightsource->GetRadius() * gl_lights_size);
-				float scale = 1.0f / ((2.f * radius) - dist);
+				Vector tmpVec = fn * dist;
+				nearPt = pos + tmpVec;
 
-				if (radius > 0.f && dist < radius)
+				Vector t1;
+				int outcnt[4]={0,0,0,0};
+				texcoord tcs[4];
+
+				// do a quick check whether the light touches this polygon
+				for(int i=0;i<4;i++)
 				{
-					Vector nearPt, up, right;
+					t1.Set(&vtx[i*3]);
+					Vector nearToVert = t1 - nearPt;
+					tcs[i].u = (nearToVert.Dot(right) * scale) + 0.5f;
+					tcs[i].v = (nearToVert.Dot(up) * scale) + 0.5f;
 
-					pos.Set(x,z,y);
-					fn=p.Normal();
-					fn.GetRightUp(right, up);
+					if (tcs[i].u<0) outcnt[0]++;
+					if (tcs[i].u>1) outcnt[1]++;
+					if (tcs[i].v<0) outcnt[2]++;
+					if (tcs[i].v>1) outcnt[3]++;
 
-					Vector tmpVec = fn * dist;
-					nearPt = pos + tmpVec;
-
-					Vector t1;
-					int outcnt[4]={0,0,0,0};
-					texcoord tcs[4];
-
-					// do a quick check whether the light touches this polygon
-					for(int i=0;i<4;i++)
-					{
-						t1.Set(&vtx[i*3]);
-						Vector nearToVert = t1 - nearPt;
-						tcs[i].u = (nearToVert.Dot(right) * scale) + 0.5f;
-						tcs[i].v = (nearToVert.Dot(up) * scale) + 0.5f;
-
-						if (tcs[i].u<0) outcnt[0]++;
-						if (tcs[i].u>1) outcnt[1]++;
-						if (tcs[i].v<0) outcnt[2]++;
-						if (tcs[i].v>1) outcnt[3]++;
-
-					}
-					if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4) 
-					{
-						gl_GetLight(p, node->lightsource, true, false, lightdata);
-					}
+				}
+				if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4) 
+				{
+					gl_GetLight(p, node->lightsource, true, false, lightdata);
 				}
 			}
-			node = node->nextLight;
 		}
+		node = node->nextLight;
 	}
 	int numlights[3];
 
@@ -223,29 +169,20 @@ void GLWall::SetupLights()
 //
 //==========================================================================
 
-void GLWall::RenderWall(int textured, ADynamicLight * light, unsigned int *store)
+void GLWall::RenderWall(int textured, unsigned int *store)
 {
 	static texcoord tcs[4]; // making this variable static saves us a relatively costly stack integrity check.
 	bool split = (gl_seamless && !(textured&RWF_NOSPLIT) && seg->sidedef != NULL && !(seg->sidedef->Flags & WALLF_POLYOBJ));
 
-	if (!light)
+	tcs[0]=lolft;
+	tcs[1]=uplft;
+	tcs[2]=uprgt;
+	tcs[3]=lorgt;
+	if ((flags&GLWF_GLOW) && (textured & RWF_GLOW))
 	{
-		tcs[0]=lolft;
-		tcs[1]=uplft;
-		tcs[2]=uprgt;
-		tcs[3]=lorgt;
-		if ((flags&GLWF_GLOW) && (textured & RWF_GLOW))
-		{
-			gl_RenderState.SetGlowPlanes(topplane, bottomplane);
-			gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor);
-		}
-
+		gl_RenderState.SetGlowPlanes(topplane, bottomplane);
+		gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor);
 	}
-	else
-	{
-		if (!PrepareLight(tcs, light)) return;
-	}
-
 
 	if (!(textured & RWF_NORENDER))
 	{
@@ -422,7 +359,6 @@ void GLWall::RenderTranslucentWall()
 //==========================================================================
 void GLWall::Draw(int pass)
 {
-	FLightNode * node;
 	int rel;
 
 #ifdef _DEBUG
@@ -461,64 +397,6 @@ void GLWall::Draw(int pass)
 		gl_RenderState.EnableLight(false);
 		break;
 
-	case GLPASS_BASE:			// Base pass for non-masked polygons (all opaque geometry)
-	case GLPASS_BASE_MASKED:	// Base pass for masked polygons (2sided mid-textures and transparent 3D floors)
-		rel = rellight + getExtraLight();
-		gl_SetColor(lightlevel, rel, Colormap,1.0f);
-		if (!(flags&GLWF_FOGGY)) 
-		{
-			if (type!=RENDERWALL_M2SNF) gl_SetFog(lightlevel, rel, &Colormap, false);
-			else gl_SetFog(255, 0, NULL, false);
-		}
-		gl_RenderState.EnableGlow(!!(flags & GLWF_GLOW));
-		// fall through
-
-		if (pass != GLPASS_BASE)
-		{
-			gltexture->Bind(flags, 0);
-		}
-		RenderWall(RWF_TEXTURED|RWF_GLOW);
-		gl_RenderState.EnableGlow(false);
-		gl_RenderState.EnableLight(false);
-		break;
-
-	case GLPASS_TEXTURE:		// modulated texture
-		gltexture->Bind(flags, 0);
-		RenderWall(RWF_TEXTURED);
-		break;
-
-	case GLPASS_LIGHT:
-	case GLPASS_LIGHT_ADDITIVE:
-		// black fog is diminishing light and should affect lights less than the rest!
-		if (!(flags&GLWF_FOGGY)) gl_SetFog((255+lightlevel)>>1, 0, NULL, false);
-		else gl_SetFog(lightlevel, 0, &Colormap, true);	
-
-		if (seg->sidedef == NULL)
-		{
-			node = NULL;
-		}
-		else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
-		{
-			// Iterate through all dynamic lights which touch this wall and render them
-			node = seg->sidedef->lighthead[pass==GLPASS_LIGHT_ADDITIVE];
-		}
-		else if (sub)
-		{
-			// To avoid constant rechecking for polyobjects use the subsector's lightlist instead
-			node = sub->lighthead[pass==GLPASS_LIGHT_ADDITIVE];
-		}
-		else node = NULL;
-		while (node)
-		{
-			if (!(node->lightsource->flags2&MF2_DORMANT))
-			{
-				iter_dlight++;
-				RenderWall(RWF_TEXTURED, node->lightsource);
-			}
-			node = node->nextLight;
-		}
-		break;
-
 	case GLPASS_DECALS:
 	case GLPASS_DECALS_NOFOG:
 		if (seg->sidedef && seg->sidedef->AttachedDecals)
diff --git a/src/r_defs.h b/src/r_defs.h
index 6b76803b4..dea227cc5 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -772,7 +772,7 @@ struct sector_t
 	int							subsectorcount;		// list of subsectors
 	subsector_t **				subsectors;
 	FPortal *					portals[2];			// floor and ceiling portals
-	FLightNode *				lighthead[2];
+	FLightNode *				lighthead;
 
 	enum
 	{
@@ -949,7 +949,7 @@ struct side_t
 	vertex_t *V2() const;
 
 	//For GL
-	FLightNode * lighthead[2];				// all blended lights that may affect this wall
+	FLightNode * lighthead;				// all blended lights that may affect this wall
 
 	seg_t **segs;	// all segs belonging to this sidedef in ascending order. Used for precise rendering
 	int numsegs;
@@ -1082,7 +1082,7 @@ struct subsector_t
 
 	void BuildPolyBSP();
 	// subsector related GL data
-	FLightNode *	lighthead[2];	// Light nodes (blended and additive)
+	FLightNode *	lighthead;	// Light nodes (blended and additive)
 	int				validcount;
 	short			mapsection;
 	char			hacked;			// 1: is part of a render hack
diff --git a/wadsrc/static/glstuff/gllight.png b/wadsrc/static/glstuff/gllight.png
deleted file mode 100644
index a3a296b9f856f4654aae244e3400a4f33fd95902..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 13073
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