diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c
index b9ab2592d3f00a4fcdb4c1af31e2eaae484cd584..5ebde15b68076278011355d550d35fd847cb766c 100644
--- a/src/hardware/hw_batching.c
+++ b/src/hardware/hw_batching.c
@@ -17,6 +17,7 @@
 // The texture for the next polygon given to HWR_ProcessPolygon.
 // Set with HWR_SetCurrentTexture.
 GLMipmap_t *current_texture = NULL;
+GLMipmap_t *current_brightmap = NULL; // rr
 
 boolean currently_batching = false;
 
@@ -61,7 +62,7 @@ void HWR_StartBatching(void)
 // This replaces the direct calls to pfnSetTexture in cases where batching is available.
 // The texture selection is saved for the next HWR_ProcessPolygon call.
 // Doing this was easier than getting a texture pointer to HWR_ProcessPolygon.
-void HWR_SetCurrentTexture(GLMipmap_t *texture)
+/*void HWR_SetCurrentTexture(GLMipmap_t *texture)
 {
     if (currently_batching)
     {
@@ -71,6 +72,34 @@ void HWR_SetCurrentTexture(GLMipmap_t *texture)
     {
         HWD.pfnSetTexture(texture);
     }
+}*/
+
+// rr
+void HWR_SetCurrentTexture(GLMipmap_t *texture)
+{
+	if (currently_batching)
+	{
+		if (texture != NULL)
+		{
+			if (texture->flags & TF_BRIGHTMAP)
+			{
+				current_brightmap = texture;
+			}
+			else
+			{
+				current_texture = texture;
+				current_brightmap = NULL;
+			}
+		}
+		else
+		{
+			current_texture = current_brightmap = NULL;
+		}
+	}
+	else
+	{
+		HWD.pfnSetTexture(texture);
+	}
 }
 
 // If batching is enabled, this function collects the polygon data and the chosen texture
@@ -114,6 +143,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
 		polygonArray[polygonArraySize].numVerts = iNumPts;
 		polygonArray[polygonArraySize].polyFlags = PolyFlags;
 		polygonArray[polygonArraySize].texture = current_texture;
+		polygonArray[polygonArraySize].brightmap = current_brightmap; // rr
 		polygonArray[polygonArraySize].shader = (shader_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
 		polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
 		// default to polygonArraySize so we don't lose order on horizon lines
@@ -129,6 +159,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
 			if (current_texture)
 			{
 				DIGEST(hash, current_texture->downloaded);
+				//DIGEST(hash, current_brightmap->downloaded); // rr
 			}
 			DIGEST(hash, PolyFlags);
 			DIGEST(hash, pSurf->PolyColor.rgba);
@@ -140,6 +171,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
 				DIGEST(hash, pSurf->LightInfo.light_level);
 				DIGEST(hash, pSurf->LightInfo.fade_start);
 				DIGEST(hash, pSurf->LightInfo.fade_end);
+				DIGEST(hash, pSurf->LightInfo.directional); // rr
 			}
 #undef DIGEST
 			// remove the sign bit to ensure that skybox and horizon line comes first.
@@ -178,6 +210,8 @@ void HWR_RenderBatches(void)
 	int nextShader = 0;
 	GLMipmap_t *currentTexture;
 	GLMipmap_t *nextTexture = NULL;
+	GLMipmap_t *currentBrightmap = NULL; // rr
+	GLMipmap_t *nextBrightmap = NULL; // rr
 	FBITFIELD currentPolyFlags = 0;
 	FBITFIELD nextPolyFlags = 0;
 	FSurfaceInfo currentSurfaceInfo;
@@ -191,6 +225,7 @@ void HWR_RenderBatches(void)
 	nextSurfaceInfo.LightInfo.fade_end = 0;
 	nextSurfaceInfo.LightInfo.fade_start = 0;
 	nextSurfaceInfo.LightInfo.light_level = 0;
+	nextSurfaceInfo.LightInfo.directional = false; // rr
 
 	currently_batching = false;// no longer collecting batches
 	if (!polygonArraySize)
@@ -226,6 +261,7 @@ void HWR_RenderBatches(void)
 
 	currentShader = polygonArray[polygonIndexArray[0]].shader;
 	currentTexture = polygonArray[polygonIndexArray[0]].texture;
+	currentBrightmap = polygonArray[polygonIndexArray[0]].brightmap; // rr - 3rd in sort order now
 	currentPolyFlags = polygonArray[polygonIndexArray[0]].polyFlags;
 	currentSurfaceInfo = polygonArray[polygonIndexArray[0]].surf;
 	// For now, will sort and track the colors. Vertex attributes could be used instead of uniforms
@@ -238,10 +274,21 @@ void HWR_RenderBatches(void)
 		HWD.pfnSetShader(currentShader);
 	}
 
-	if (currentPolyFlags & PF_NoTexture)
+	/*if (currentPolyFlags & PF_NoTexture)
 		currentTexture = NULL;
     else
-	    HWD.pfnSetTexture(currentTexture);
+	    HWD.pfnSetTexture(currentTexture);*/
+	// rr
+	if (currentPolyFlags & PF_NoTexture)
+	{
+		currentTexture = currentBrightmap = NULL;
+	}
+	else
+	{
+		HWD.pfnSetTexture(currentTexture);
+		if (currentBrightmap)
+			HWD.pfnSetTexture(currentBrightmap);
+	}
 
 	while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons)
 	{
@@ -314,15 +361,18 @@ void HWR_RenderBatches(void)
 				changeState = true;
 				nextShader = polygonArray[nextIndex].shader;
 				nextTexture = polygonArray[nextIndex].texture;
+				nextBrightmap = polygonArray[nextIndex].brightmap; // rr
 				nextPolyFlags = polygonArray[nextIndex].polyFlags;
 				nextSurfaceInfo = polygonArray[nextIndex].surf;
 				if (nextPolyFlags & PF_NoTexture)
-					nextTexture = 0;
+					//nextTexture = 0;
+					nextTexture = nextBrightmap = 0; // rr
 				if (currentShader != nextShader && cv_glshaders.value && gl_shadersavailable)
 				{
 					changeShader = true;
 				}
-				if (currentTexture != nextTexture)
+				//if (currentTexture != nextTexture)
+				if (currentTexture != nextTexture || currentBrightmap != nextBrightmap) // rr
 				{
 					changeTexture = true;
 				}
@@ -337,7 +387,8 @@ void HWR_RenderBatches(void)
 						currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba ||
 						currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level ||
 						currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
-						currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end)
+						currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end ||
+						currentSurfaceInfo.LightInfo.directional != nextSurfaceInfo.LightInfo.directional) // rr
 					{
 						changeSurfaceInfo = true;
 					}
@@ -384,6 +435,12 @@ void HWR_RenderBatches(void)
 				// texture should be already ready for use from calls to SetTexture during batch collection
 			    HWD.pfnSetTexture(nextTexture);
 				currentTexture = nextTexture;
+				
+				// rr
+				if (nextBrightmap)
+					HWD.pfnSetTexture(nextBrightmap);
+				currentBrightmap = nextBrightmap;
+				
 				changeTexture = false;
 
 				ps_hw_numtextures.value.i++;