diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index ffe5196d14abc083ed1c184241a077fe88a4929b..f6c5eb77404bbcbf7d5ca80fafea474525e782c0 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -265,44 +265,23 @@ static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t
 	return (FUINT)finallight;
 }
 
-static FUINT HWR_CalcSlopeLight(FUINT lightnum, angle_t dir, fixed_t delta)
+static FUINT HWR_CalcSlopeLight(FUINT lightnum, pslope_t *slope)
 {
 	INT16 finallight = lightnum;
 
-	if (cv_glfakecontrast.value != 0 && cv_glslopecontrast.value != 0)
+	if (slope != NULL && cv_glfakecontrast.value != 0 && cv_glslopecontrast.value != 0)
 	{
-		const UINT8 contrast = 8;
 		fixed_t extralight = 0;
 
 		if (cv_glfakecontrast.value == 2) // Smooth setting
-		{
-			fixed_t dirmul = abs(FixedDiv(AngleFixed(dir) - (180<<FRACBITS), 180<<FRACBITS));
-
-			extralight = -(contrast<<FRACBITS) + (dirmul * (contrast * 2));
-
-			extralight = FixedMul(extralight, delta*4) >> FRACBITS;
-		}
+			extralight += slope->hwLightOffset;
 		else
-		{
-			dir = ((dir + ANGLE_45) / ANGLE_90) * ANGLE_90;
-
-			if (dir == ANGLE_180)
-				extralight = -contrast;
-			else if (dir == 0)
-				extralight = contrast;
-
-			if (delta >= FRACUNIT/2)
-				extralight *= 2;
-		}
+			extralight += slope->lightOffset * 8;
 
 		if (extralight != 0)
 		{
 			finallight += extralight;
-
-			if (finallight < 0)
-				finallight = 0;
-			if (finallight > 255)
-				finallight = 255;
+			finallight = min(max(finallight, 0) , 255);
 		}
 	}
 
@@ -499,7 +478,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
 		SETUP3DVERT(v3d, pv->x, pv->y);
 
 	if (slope)
-		lightlevel = HWR_CalcSlopeLight(lightlevel, R_PointToAngle2(0, 0, slope->normal.x, slope->normal.y), abs(slope->zdelta));
+		lightlevel = HWR_CalcSlopeLight(lightlevel, slope);
 
 	HWR_Lighting(&Surf, lightlevel, planecolormap);
 
diff --git a/src/p_slopes.c b/src/p_slopes.c
index a78d5c46f75c2eb39323b91da42a666511b242d4..65df1a010ec05070f7d6bd8ab642ecd18cd2b3cb 100644
--- a/src/p_slopes.c
+++ b/src/p_slopes.c
@@ -30,12 +30,48 @@ UINT16 slopecount = 0;
 
 static void P_UpdateMidtextureSlopesForSector(sector_t *sector);
 
+// Calculate light
+static void P_UpdateSlopeLightOffset(pslope_t *slope)
+{
+	const boolean ceiling = (slope->normal.z < 0);
+	const UINT8 contrast = 8;
+
+	fixed_t contrastFixed = ((fixed_t)contrast) * FRACUNIT;
+	fixed_t zMul = FRACUNIT;
+	angle_t slopeDir = ANGLE_MAX;
+	fixed_t extralight = 0;
+
+	if (slope->normal.z == 0)
+	{
+		slope->lightOffset = slope->hwLightOffset = 0;
+		return;
+	}
+
+	slopeDir = R_PointToAngle2(0, 0, abs(slope->normal.y), abs(slope->normal.x));
+	if (ceiling == true)
+	{
+		slopeDir ^= ANGLE_180;
+	}
+
+	zMul = min(FRACUNIT, abs(slope->zdelta)*3/2); // *3/2, to make 60 degree slopes match walls.
+	contrastFixed = FixedMul(contrastFixed, zMul);
+	extralight = -contrastFixed + FixedMul(FixedDiv(AngleFixed(slopeDir), 90*FRACUNIT), (contrastFixed * 2));
+
+	// Between -2 and 2 for software, -8 and 8 for hardware
+	slope->lightOffset = FixedFloor((extralight / 8) + (FRACUNIT / 2)) / FRACUNIT;
+#ifdef HWRENDER
+	slope->hwLightOffset = FixedFloor(extralight + (FRACUNIT / 2)) / FRACUNIT;
+#endif
+}
+
 // Calculate line normal
 void P_CalculateSlopeNormal(pslope_t *slope)
 {
 	slope->normal.z = FINECOSINE(slope->zangle>>ANGLETOFINESHIFT);
 	slope->normal.x = FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.x);
 	slope->normal.y = FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.y);
+
+	P_UpdateSlopeLightOffset(slope);
 }
 
 static void CalculateNormalDir(pslope_t *slope, dvector3_t *dnormal)
@@ -121,6 +157,8 @@ static void ReconfigureViaVertexes (pslope_t *slope, const vector3_t v1, const v
 		slope->zangle = InvAngle(R_PointToAngle2(0, 0, FRACUNIT, slope->zdelta));
 	}
 
+	P_UpdateSlopeLightOffset(slope);
+
 	P_CalculateSlopeVectors(slope);
 }
 
diff --git a/src/r_defs.h b/src/r_defs.h
index ac479b78d95968827c42354a3807f5889003b73b..73e9e5d382cdca692093e2cc9fbb3984dd3c9caa 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -354,6 +354,11 @@ typedef struct pslope_s
 	boolean moved;
 
 	UINT8 flags; // Slope options
+
+	SINT8 lightOffset;
+#ifdef HWRENDER	
+	INT16 hwLightOffset;	
+#endif
 } pslope_t;
 
 typedef enum
diff --git a/src/r_plane.c b/src/r_plane.c
index bfc7614006f91256eb5b026f0a5d163f798b10a7..daa752af589db4e1f78abc1c7e27080aeb097588 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -473,6 +473,12 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li
 	offset_x = ((INT64)offset_x * xscale) / FRACUNIT;
 	offset_y = ((INT64)offset_y * yscale) / FRACUNIT;
 
+
+	if (slope != NULL)
+	{
+		lightlevel += (slope->lightOffset / 8);
+	}
+
 	// This appears to fix the Nimbus Ruins sky bug.
 	if (picnum == skyflatnum && pfloor)
 	{