diff --git a/src/d_main.c b/src/d_main.c
index 24d026827958b521dab5f61860a3fa1c9e6c761c..6d1335d36b1fbc8b86540fbe141d785647d539dc 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -267,7 +267,7 @@ static void D_Display(void)
 			 && wipetypepre != UINT8_MAX)
 			{
 				F_WipeStartScreen();
-				V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
+				F_WipeColorFill(31);
 				F_WipeEndScreen();
 				F_RunWipe(wipetypepre, gamestate != GS_TIMEATTACK && gamestate != GS_TITLESCREEN);
 			}
diff --git a/src/f_finale.c b/src/f_finale.c
index eb1415042bc2a10efa6f0798db80b53a93db101d..b9a2cfc9b8be0d9c5f52ffe14eea49829db9e109 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -763,7 +763,7 @@ void F_IntroDrawer(void)
 			if (rendermode != render_none)
 			{
 				F_WipeStartScreen();
-				V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
+				F_WipeColorFill(31);
 				F_WipeEndScreen();
 				F_RunWipe(99,true);
 			}
@@ -773,10 +773,11 @@ void F_IntroDrawer(void)
 		else if (intro_scenenum == 10)
 		{
 			// The only fade to white in the entire damn game.
+			// (not true)
 			if (rendermode != render_none)
 			{
 				F_WipeStartScreen();
-				V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0);
+				F_WipeColorFill(0);
 				F_WipeEndScreen();
 				F_RunWipe(99,true);
 			}
@@ -786,7 +787,7 @@ void F_IntroDrawer(void)
 			if (rendermode != render_none)
 			{
 				F_WipeStartScreen();
-				V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
+				F_WipeColorFill(31);
 				F_WipeEndScreen();
 				F_RunWipe(99,true);
 			}
@@ -833,7 +834,7 @@ void F_IntroDrawer(void)
 			patch_t *radar = W_CachePatchName("RADAR", PU_CACHE);
 
 			F_WipeStartScreen();
-			V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
+			F_WipeColorFill(31);
 			V_DrawScaledPatch(0, 0, 0, radar);
 			W_UnlockCachedPatch(radar);
 			V_DrawString(8, 128, 0, cutscene_disptext);
@@ -846,7 +847,7 @@ void F_IntroDrawer(void)
 			patch_t *grass = W_CachePatchName("SGRASS5", PU_CACHE);
 
 			F_WipeStartScreen();
-			V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
+			F_WipeColorFill(31);
 			V_DrawScaledPatch(0, 0, 0, grass);
 			W_UnlockCachedPatch(grass);
 			V_DrawString(8, 128, 0, cutscene_disptext);
@@ -859,7 +860,7 @@ void F_IntroDrawer(void)
 			patch_t *confront = W_CachePatchName("CONFRONT", PU_CACHE);
 
 			F_WipeStartScreen();
-			V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
+			F_WipeColorFill(31);
 			V_DrawSmallScaledPatch(0, 0, 0, confront);
 			W_UnlockCachedPatch(confront);
 			V_DrawString(8, 128, 0, cutscene_disptext);
@@ -872,7 +873,7 @@ void F_IntroDrawer(void)
 			patch_t *sdo = W_CachePatchName("SONICDO2", PU_CACHE);
 
 			F_WipeStartScreen();
-			V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
+			F_WipeColorFill(31);
 			V_DrawSmallScaledPatch(0, 0, 0, sdo);
 			W_UnlockCachedPatch(sdo);
 			V_DrawString(224, 8, 0, cutscene_disptext);
diff --git a/src/f_finale.h b/src/f_finale.h
index 0619a7e74b2431a26fddf9f02d1dd8e45db98b09..4766af652a5401fe38c5caa5580c39e3fd41ffc4 100644
--- a/src/f_finale.h
+++ b/src/f_finale.h
@@ -138,6 +138,8 @@ void F_WipeStartScreen(void);
 void F_WipeEndScreen(void);
 void F_RunWipe(UINT8 wipetype, boolean drawMenu);
 void F_WipeTicker(void);
+void F_WipeTitleCard(void);
+void F_WipeColorFill(UINT8 color);
 tic_t F_GetWipeLength(UINT8 wipetype);
 boolean F_WipeExists(UINT8 wipetype);
 
diff --git a/src/f_wipe.c b/src/f_wipe.c
index e67e7e3adba34804d7b4799f4cd0a7143494aa7d..8b69f39ca56b489f6bd214b8033c9c15bdf41edd 100644
--- a/src/f_wipe.c
+++ b/src/f_wipe.c
@@ -103,6 +103,7 @@ static fixed_t paldiv = 0;
 
 static UINT8 curwipetype;
 static UINT8 curwipeframe;
+static UINT8 wipecolorfill = 31;
 
 /** Create fademask_t from lump
   *
@@ -186,7 +187,7 @@ static fademask_t *F_GetFadeMask(UINT8 masknum, UINT8 scrnnum) {
 	return NULL;
 }
 
-static void F_WipeTitleCard(void)
+void F_WipeTitleCard(void)
 {
 	if (wipestyle == WIPESTYLE_LEVEL
 		&& (!titlemapinaction)
@@ -199,6 +200,12 @@ static void F_WipeTitleCard(void)
 		ST_drawLevelTitle(TICRATE);
 }
 
+void F_WipeColorFill(UINT8 color)
+{
+	wipecolorfill = color;
+	V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, wipecolorfill);
+}
+
 /**	Wipe ticker
   *
   * \param	fademask	pixels to change
@@ -430,10 +437,17 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
 
 #ifdef HWRENDER
 		if (rendermode == render_opengl)
-			HWR_DoWipe(wipetype, wipeframe-1); // send in the wipe type and wipeframe because we need to cache the graphic
+		{
+			// send in the wipe type and wipe frame because we need to cache the graphic
+			if (wipestyle == WIPESTYLE_LEVEL)
+				HWR_DoTintedWipe(wipetype, wipeframe-1);
+			else
+				HWR_DoWipe(wipetype, wipeframe-1);
+		}
 		else
 #endif
 			F_DoWipe(fmask);
+
 		I_OsPolling();
 		I_UpdateNoBlit();
 
@@ -473,8 +487,9 @@ void F_WipeTicker(void)
 	}
 
 #ifdef HWRENDER
+	// send in the wipe type and wipe frame because we need to cache the graphic
 	if (rendermode == render_opengl)
-		HWR_DoWipeLevel(curwipetype, curwipeframe-1);
+		HWR_DoLevelWipe(curwipetype, curwipeframe-1, wipecolorfill); // also send the wipe color
 	else
 #endif
 		F_DoWipe(fmask);
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 92def01a9dffb440ac904680aa0f373c20efc778..9d1c2d21937c7076b41e32c30e0c72941b14cd31 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -39,6 +39,7 @@
 #include "../st_stuff.h"
 #include "../i_system.h"
 #include "../m_cheat.h"
+#include "../f_finale.h"
 #ifdef ESLOPE
 #include "../p_slopes.h"
 #endif
@@ -6991,73 +6992,82 @@ void HWR_DrawIntermissionBG(void)
 	HWD.pfnDrawIntermissionBG();
 }
 
-void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum)
+//
+// hwr mode wipes
+//
+static char wipelumpname[9];
+static lumpnum_t wipelumpnum;
+
+// puts wipe lumpname in wipename[9]
+static boolean check_wipe(UINT8 wipenum, UINT8 scrnnum)
 {
-	static char lumpname[9] = "FADEmmss";
-	lumpnum_t lumpnum;
 	size_t lsize;
 
-	if (wipenum > 99 || scrnnum > 99) // not a valid wipe number
-		return; // shouldn't end up here really, the loop should've stopped running beforehand
+	// write FADE prefix into wipelumpname
+	strncpy(wipelumpname, "FADEmmss", 8);
 
-	// puts the numbers into the lumpname
-	sprintf(&lumpname[4], "%.2hu%.2hu", (UINT16)wipenum, (UINT16)scrnnum);
-	lumpnum = W_CheckNumForName(lumpname);
+	// not a valid wipe number
+	if (wipenum > 99 || scrnnum > 99)
+		return false; // shouldn't end up here really, the loop should've stopped running beforehand
 
-	if (lumpnum == LUMPERROR) // again, shouldn't be here really
-		return;
+	// puts the numbers into the wipename
+	sprintf(&wipelumpname[4], "%.2hu%.2hu", (UINT16)wipenum, (UINT16)scrnnum);
+	wipelumpnum = W_CheckNumForName(wipelumpname);
 
-	lsize = W_LumpLength(lumpnum);
+	// again, shouldn't be here really
+	if (wipelumpnum == LUMPERROR)
+		return false;
 
+	lsize = W_LumpLength(wipelumpnum);
 	if (!(lsize == 256000 || lsize == 64000 || lsize == 16000 || lsize == 4000))
 	{
-		CONS_Alert(CONS_WARNING, "Fade mask lump %s of incorrect size, ignored\n", lumpname);
-		return; // again, shouldn't get here if it is a bad size
+		CONS_Alert(CONS_WARNING, "Fade mask lump %s of incorrect size, ignored\n", wipelumpname);
+		return false; // again, shouldn't get here if it is a bad size
 	}
 
-	HWR_GetFadeMask(lumpnum);
+	return true;
+}
 
+void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum)
+{
+	if (!check_wipe(wipenum, scrnnum))
+		return;
+
+	HWR_GetFadeMask(wipelumpnum);
 	HWD.pfnDoScreenWipe(HWRWipeCounter); // Still send in wipecounter since old stuff might not support multitexturing
 
 	HWRWipeCounter += 0.05f; // increase opacity of end screen
-
 	if (HWRWipeCounter > 1.0f)
 		HWRWipeCounter = 1.0f;
 }
 
-void HWR_DoWipeLevel(UINT8 wipenum, UINT8 scrnnum)
+void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum)
 {
-	static char lumpname[9] = "FADEmmss";
-	lumpnum_t lumpnum;
-	size_t lsize;
+	if (!check_wipe(wipenum, scrnnum))
+		return;
 
-	if (wipenum > 99 || scrnnum > 99) // not a valid wipe number
-		return; // shouldn't end up here really, the loop should've stopped running beforehand
+	HWR_GetFadeMask(wipelumpnum);
+	HWD.pfnDoScreenWipe(HWRWipeCounter);
 
-	// puts the numbers into the lumpname
-	sprintf(&lumpname[4], "%.2hu%.2hu", (UINT16)wipenum, (UINT16)scrnnum);
-	lumpnum = W_CheckNumForName(lumpname);
+	HWRWipeCounter += 0.05f; // increase opacity of end screen
+	if (HWRWipeCounter > 1.0f)
+		HWRWipeCounter = 1.0f;
+}
 
-	if (lumpnum == LUMPERROR) // again, shouldn't be here really
+void HWR_DoLevelWipe(UINT8 wipenum, UINT8 scrnnum, UINT8 wipecolorfill)
+{
+	if (!check_wipe(wipenum, scrnnum))
 		return;
 
-	lsize = W_LumpLength(lumpnum);
-
-	if (!(lsize == 256000 || lsize == 64000 || lsize == 16000 || lsize == 4000))
-	{
-		CONS_Alert(CONS_WARNING, "Fade mask lump %s of incorrect size, ignored\n", lumpname);
-		return; // again, shouldn't get here if it is a bad size
-	}
-
 	HWR_EndScreenWipe();
-	V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
+	V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, wipecolorfill);
 	HWR_StartScreenWipe();
-	HWR_GetFadeMask(lumpnum);
+	HWR_GetFadeMask(wipelumpnum);
 
 	HWD.pfnDoScreenWipeLevel();
+	F_WipeTitleCard();
 
 	HWRWipeCounter += 0.05f; // increase opacity of end screen
-
 	if (HWRWipeCounter > 1.0f)
 		HWRWipeCounter = 1.0f;
 }
diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h
index 6d340ec6b9f5fa279fee98957a35a9b1b5363c19..e1cb01444022653bdbec0df4ee64425ed8e7ed74 100644
--- a/src/hardware/hw_main.h
+++ b/src/hardware/hw_main.h
@@ -67,7 +67,8 @@ void HWR_StartScreenWipe(void);
 void HWR_EndScreenWipe(void);
 void HWR_DrawIntermissionBG(void);
 void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum);
-void HWR_DoWipeLevel(UINT8 wipenum, UINT8 scrnnum);
+void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum);
+void HWR_DoLevelWipe(UINT8 wipenum, UINT8 scrnnum, UINT8 wipecolorfill);
 void HWR_MakeScreenFinalTexture(void);
 void HWR_DrawScreenFinalTexture(int width, int height);
 
diff --git a/src/p_setup.c b/src/p_setup.c
index 1223c85d04a619a2454d4f84e45b1994bfa32acc..ea619c641fc5a1870066d0bce8205b76c7c168b9 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -2691,10 +2691,15 @@ boolean P_SetupLevel(boolean skipprecip)
 		F_WipeStartScreen();
 		wipestyleflags |= WSF_FADEOUT|WSF_TOWHITE;
 
+#ifdef HWRENDER
+		// uh..........
+		if (rendermode == render_opengl)
+			F_WipeColorFill(0);
+#endif
+
 		F_WipeEndScreen();
 		F_RunWipe(wipedefs[wipe_speclevel_towhite], false);
 
-		V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0);
 		I_OsPolling();
 		I_FinishUpdate(); // page flip or blit buffer
 		if (moviemode)
@@ -2734,7 +2739,12 @@ boolean P_SetupLevel(boolean skipprecip)
 	{
 		F_WipeStartScreen();
 		wipestyleflags |= WSF_FADEOUT;
-		//V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
+
+#ifdef HWRENDER
+		// uh..........
+		if (rendermode == render_opengl)
+			F_WipeColorFill(31);
+#endif
 
 		F_WipeEndScreen();
 		// for titlemap: run a specific wipe if specified
@@ -3130,7 +3140,7 @@ boolean P_SetupLevel(boolean skipprecip)
 
 	// Remove the loading shit from the screen
 	if (rendermode != render_none && !titlemapinaction)
-		V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
+		F_WipeColorFill(levelfadecol);
 
 	if (precache || dedicated)
 		R_PrecacheLevel();
@@ -3203,7 +3213,7 @@ boolean P_SetupLevel(boolean skipprecip)
 				I_Sleep();
 			lasttime = nowtime;
 
-			V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
+			F_WipeColorFill(levelfadecol);
 			stplyr = &players[consoleplayer];
 			ST_drawLevelTitle(nowtime - starttime);
 			if (splitscreen)