diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c
index 64f74b1f4e9bae98553b881df46309148344a00a..56f5416cf13f8d4c3176d93b122094d4bfd0bacb 100644
--- a/src/hardware/hw_cache.c
+++ b/src/hardware/hw_cache.c
@@ -98,13 +98,11 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
 		if (position + count >= pblockheight)
 			count = pblockheight - position;
 
-		dest = block + (position*blockmodulo);
-		while (count > 0)
+		for (dest = block + (position*blockmodulo); count > 0; count--, dest += blockmodulo, yfrac += yfracstep)
 		{
-			count--;
-
 			texel = source[yfrac>>FRACBITS];
 			alpha = 0xFF;
+
 			// Make pixel transparent if chroma keyed
 			if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX))
 				alpha = 0x00;
@@ -115,11 +113,20 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
 			switch (bpp)
 			{
 				case 2:
+				{
+					texelu16 = *((UINT16*)dest);
 					if ((originPatch != NULL) && (originPatch->style != AST_COPY))
-						texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha);
+					{
+						if (originPatch->style == AST_TRANSLUCENT && originPatch->alpha < ASTTextureBlendingThreshold[0])
+							continue;
+						if (!(texelu16 & 0xFF00) && originPatch->alpha <= ASTTextureBlendingThreshold[1])
+							continue;
+						texel = ASTBlendPaletteIndexes(texelu16 & 0xFF, texel, originPatch->style, originPatch->alpha);
+					}
 					texelu16 = (UINT16)((alpha<<8) | texel);
 					memcpy(dest, &texelu16, sizeof(UINT16));
 					break;
+				}
 				case 3:
 					colortemp = palette[texel];
 					if ((originPatch != NULL) && (originPatch->style != AST_COPY))
@@ -149,9 +156,6 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
 						*dest = texel;
 					break;
 			}
-
-			dest += blockmodulo;
-			yfrac += yfracstep;
 		}
 	}
 }
@@ -202,13 +206,11 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block,
 		if (position + count >= pblockheight)
 			count = pblockheight - position;
 
-		dest = block + (position*blockmodulo);
-		while (count > 0)
+		for (dest = block + (position*blockmodulo); count > 0; count--, dest += blockmodulo, yfrac -= yfracstep)
 		{
-			count--;
-
 			texel = source[yfrac>>FRACBITS];
 			alpha = 0xFF;
+
 			// Make pixel transparent if chroma keyed
 			if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX))
 				alpha = 0x00;
@@ -219,8 +221,15 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block,
 			switch (bpp)
 			{
 				case 2:
+					texelu16 = *((UINT16*)dest);
 					if ((originPatch != NULL) && (originPatch->style != AST_COPY))
-						texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha);
+					{
+						if (originPatch->style == AST_TRANSLUCENT && originPatch->alpha < ASTTextureBlendingThreshold[0])
+							continue;
+						if (!(texelu16 & 0xFF00) && originPatch->alpha <= ASTTextureBlendingThreshold[1])
+							continue;
+						texel = ASTBlendPaletteIndexes(texelu16 & 0xFF, texel, originPatch->style, originPatch->alpha);
+					}
 					texelu16 = (UINT16)((alpha<<8) | texel);
 					memcpy(dest, &texelu16, sizeof(UINT16));
 					break;
@@ -253,9 +262,6 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block,
 						*dest = texel;
 					break;
 			}
-
-			dest += blockmodulo;
-			yfrac -= yfracstep;
 		}
 	}
 }
@@ -433,7 +439,7 @@ static UINT8 *MakeBlock(GLMipmap_t *grMipmap)
 // Create a composite texture from patches, adapt the texture size to a power of 2
 // height and width for the hardware texture cache.
 //
-static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
+static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex, GLMipmap_t *mipmap)
 {
 	UINT8 *block;
 	texture_t *texture;
@@ -441,57 +447,19 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
 	INT32 blockwidth, blockheight, blocksize;
 
 	INT32 i;
-	boolean skyspecial = false; //poor hack for Legacy large skies..
-
-	RGBA_t *palette;
-	palette = HWR_GetTexturePalette();
 
 	texture = textures[texnum];
 
-	// hack the Legacy skies..
-	if (texture->name[0] == 'S' &&
-	    texture->name[1] == 'K' &&
-	    texture->name[2] == 'Y' &&
-	    (texture->name[4] == 0 ||
-	     texture->name[5] == 0)
-	   )
-	{
-		skyspecial = true;
-		grtex->mipmap.flags = TF_WRAPXY; // don't use the chromakey for sky
-	}
-	else
-		grtex->mipmap.flags = TF_CHROMAKEYED | TF_WRAPXY;
-
-	grtex->mipmap.width = (UINT16)texture->width;
-	grtex->mipmap.height = (UINT16)texture->height;
-	if (skyspecial)
-		grtex->mipmap.format = GL_TEXFMT_RGBA; // that skyspecial code below assumes this format ...
-	else
-		grtex->mipmap.format = textureformat;
+	mipmap->flags = TF_WRAPXY;
+	mipmap->width = (UINT16)texture->width;
+	mipmap->height = (UINT16)texture->height;
+	mipmap->format = textureformat;
 
 	blockwidth = texture->width;
 	blockheight = texture->height;
 	blocksize = (blockwidth * blockheight);
 	block = MakeBlock(&grtex->mipmap);
 
-	if (skyspecial) //Hurdler: not efficient, but better than holes in the sky (and it's done only at level loading)
-	{
-		INT32 j;
-		RGBA_t col;
-
-		col = palette[HWR_PATCHES_CHROMAKEY_COLORINDEX];
-		for (j = 0; j < blockheight; j++)
-		{
-			for (i = 0; i < blockwidth; i++)
-			{
-				block[4*(j*blockwidth+i)+0] = col.s.red;
-				block[4*(j*blockwidth+i)+1] = col.s.green;
-				block[4*(j*blockwidth+i)+2] = col.s.blue;
-				block[4*(j*blockwidth+i)+3] = 0xff;
-			}
-		}
-	}
-
 	// Composite the columns together.
 	for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
 	{
@@ -526,13 +494,13 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
 			Patch_Free(realpatch);
 	}
 	//Hurdler: not efficient at all but I don't remember exactly how HWR_DrawPatchInCache works :(
-	if (format2bpp(grtex->mipmap.format)==4)
+	if (format2bpp(mipmap->format)==4)
 	{
 		for (i = 3; i < blocksize*4; i += 4) // blocksize*4 because blocksize doesn't include the bpp
 		{
 			if (block[i] == 0)
 			{
-				grtex->mipmap.flags |= TF_TRANSPARENT;
+				mipmap->flags |= TF_TRANSPARENT;
 				break;
 			}
 		}
@@ -661,8 +629,6 @@ void HWR_FreeTextureColormaps(patch_t *patch)
 			Z_Free(next->data);
 		if (next->colormap)
 			Z_Free(next->colormap);
-		next->data = NULL;
-		next->colormap = NULL;
 		HWD.pfnDeleteTexture(next);
 
 		// Free the old colormap mipmap from memory.
@@ -714,12 +680,25 @@ void HWR_InitMapTextures(void)
 	gl_maptexturesloaded = false;
 }
 
+static void DeleteTextureMipmap(GLMipmap_t *grMipmap)
+{
+	HWD.pfnDeleteTexture(grMipmap);
+
+	// Chroma-keyed textures do not own their texture data, so do not free it
+	if (!(grMipmap->flags & TF_CHROMAKEYED))
+		Z_Free(grMipmap->data);
+}
+
 static void FreeMapTexture(GLMapTexture_t *tex)
 {
-	HWD.pfnDeleteTexture(&tex->mipmap);
-	if (tex->mipmap.data)
-		Z_Free(tex->mipmap.data);
-	tex->mipmap.data = NULL;
+	if (tex->mipmap.nextcolormap)
+	{
+		DeleteTextureMipmap(tex->mipmap.nextcolormap);
+		free(tex->mipmap.nextcolormap);
+		tex->mipmap.nextcolormap = NULL;
+	}
+
+	DeleteTextureMipmap(&tex->mipmap);
 }
 
 void HWR_FreeMapTextures(void)
@@ -762,41 +741,47 @@ void HWR_LoadMapTextures(size_t pnumtextures)
 // --------------------------------------------------------------------------
 // Make sure texture is downloaded and set it as the source
 // --------------------------------------------------------------------------
-GLMapTexture_t *HWR_GetTexture(INT32 tex)
+static void GetMapTexture(INT32 tex, GLMapTexture_t *grtex, GLMipmap_t *mipmap)
 {
-	GLMapTexture_t *grtex;
-#ifdef PARANOIA
-	if ((unsigned)tex >= gl_numtextures)
-		I_Error("HWR_GetTexture: tex >= numtextures\n");
-#endif
-
-	// Every texture in memory, stored in the
-	// hardware renderer's bit depth format. Wow!
-	grtex = &gl_textures[tex];
-
 	// Generate texture if missing from the cache
-	if (!grtex->mipmap.data && !grtex->mipmap.downloaded)
-		HWR_GenerateTexture(tex, grtex);
+	if (!mipmap->data && !mipmap->downloaded)
+		HWR_GenerateTexture(tex, grtex, mipmap);
 
 	// If hardware does not have the texture, then call pfnSetTexture to upload it
-	if (!grtex->mipmap.downloaded)
-		HWD.pfnSetTexture(&grtex->mipmap);
-	HWR_SetCurrentTexture(&grtex->mipmap);
+	if (!mipmap->downloaded)
+		HWD.pfnSetTexture(mipmap);
+	HWR_SetCurrentTexture(mipmap);
 
 	// The system-memory data can be purged now.
-	Z_ChangeTag(grtex->mipmap.data, PU_HWRCACHE_UNLOCKED);
+	Z_ChangeTag(mipmap->data, PU_HWRCACHE_UNLOCKED);
+}
+
+GLMapTexture_t *HWR_GetTexture(INT32 tex)
+{
+	if (tex < 0 || tex >= (signed)gl_numtextures)
+	{
+#ifdef PARANOIA
+		I_Error("HWR_GetTexture: Invalid texture ID %d", tex);
+#else
+		tex = 0;
+#endif
+	}
+
+	GLMapTexture_t *grtex = &gl_textures[tex];
+
+	GetMapTexture(tex, grtex, &grtex->mipmap);
 
 	return grtex;
 }
 
-static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
+static void HWR_CacheRawFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
 {
 	size_t size = W_LumpLength(flatlumpnum);
 	UINT16 pflatsize = R_GetFlatSize(size);
 
 	// setup the texture info
 	grMipmap->format = GL_TEXFMT_P_8;
-	grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
+	grMipmap->flags = TF_WRAPXY;
 
 	grMipmap->width = pflatsize;
 	grMipmap->height = pflatsize;
@@ -817,7 +802,7 @@ void HWR_GetRawFlat(lumpnum_t flatlumpnum)
 	patch = HWR_GetCachedGLPatch(flatlumpnum);
 	grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap;
 	if (!grmip->downloaded && !grmip->data)
-		HWR_CacheFlat(grmip, flatlumpnum);
+		HWR_CacheRawFlat(grmip, flatlumpnum);
 
 	// If hardware does not have the texture, then call pfnSetTexture to upload it
 	if (!grmip->downloaded)
@@ -828,7 +813,16 @@ void HWR_GetRawFlat(lumpnum_t flatlumpnum)
 	Z_ChangeTag(grmip->data, PU_HWRCACHE_UNLOCKED);
 }
 
-void HWR_GetLevelFlat(levelflat_t *levelflat)
+static void MakeLevelFlatMipmap(GLMipmap_t *grMipmap, INT32 texturenum, UINT16 flags)
+{
+	grMipmap->format = GL_TEXFMT_P_8;
+	grMipmap->flags = flags;
+
+	grMipmap->width  = (UINT16)textures[texturenum]->width;
+	grMipmap->height = (UINT16)textures[texturenum]->height;
+}
+
+void HWR_GetLevelFlat(levelflat_t *levelflat, boolean chromakeyed)
 {
 	if (levelflat->type == LEVELFLAT_NONE || levelflat->texture_id < 0)
 	{
@@ -839,24 +833,50 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
 	INT32 texturenum = texturetranslation[levelflat->texture_id];
 
 	GLMapTexture_t *grtex = &gl_flats[texturenum];
+
 	GLMipmap_t *grMipmap = &grtex->mipmap;
+	GLMipmap_t *originalMipmap = grMipmap;
+
+	if (!originalMipmap->downloaded)
+		MakeLevelFlatMipmap(originalMipmap, texturenum, TF_WRAPXY);
 
-	if (!grMipmap->data && !grMipmap->downloaded)
+	if (!originalMipmap->data)
 	{
-		grMipmap->format = GL_TEXFMT_P_8;
-		grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
+		size_t size = originalMipmap->width * originalMipmap->height;
+		memcpy(Z_Malloc(size, PU_HWRCACHE, &originalMipmap->data), R_GetFlatForTexture(texturenum), size);
+	}
+
+	// If chroma-keyed, create or use a different mipmap for the variant
+	if (chromakeyed)
+	{
+		if (!originalMipmap->data)
+		{
+			HWR_SetCurrentTexture(NULL);
+			return;
+		}
+
+		// Allocate it if it wasn't already
+		if (!originalMipmap->nextcolormap)
+		{
+			GLMipmap_t *newMipmap = calloc(1, sizeof (*grMipmap));
+			if (newMipmap == NULL)
+				I_Error("%s: Out of memory", "HWR_GetLevelFlat");
+			MakeLevelFlatMipmap(newMipmap, texturenum, TF_WRAPXY | TF_CHROMAKEYED);
+			originalMipmap->nextcolormap = newMipmap;
+		}
 
-		grMipmap->width  = (UINT16)textures[texturenum]->width;
-		grMipmap->height = (UINT16)textures[texturenum]->height;
+		// Upload and bind the variant texture instead of the original one
+		grMipmap = originalMipmap->nextcolormap;
 
-		size_t size = grMipmap->width * grMipmap->height;
-		memcpy(Z_Malloc(size, PU_HWRCACHE, &grMipmap->data), R_GetFlatForTexture(texturenum), size);
+		// Use the original texture's pixel data
+		// It can just be a pointer to it, since the r_opengl backend deals with the pixels
+		// that are supposed to be transparent.
+		grMipmap->data = originalMipmap->data;
 	}
 
 	if (!grMipmap->downloaded)
-		HWD.pfnSetTexture(&grtex->mipmap);
-
-	HWR_SetCurrentTexture(&grtex->mipmap);
+		HWD.pfnSetTexture(grMipmap);
+	HWR_SetCurrentTexture(grMipmap);
 
 	Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED);
 }
diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h
index 2d55eef2d8fd72271fef9c529d4be862318f93da..7d06ceb60b86d8ef3fff3d30a21ce29213d6c600 100644
--- a/src/hardware/hw_defs.h
+++ b/src/hardware/hw_defs.h
@@ -246,7 +246,7 @@ enum ETextureFlags
 	TF_WRAPX       = 0x00000001,        // wrap around X
 	TF_WRAPY       = 0x00000002,        // wrap around Y
 	TF_WRAPXY      = TF_WRAPY|TF_WRAPX, // very common so use alias is more easy
-	TF_CHROMAKEYED = 0x00000010,
+	TF_CHROMAKEYED = 0x00000010,        // Used only for flats with pixels that have palette index 255
 	TF_TRANSPARENT = 0x00000040,        // texture with some alpha == 0
 };
 
diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h
index e96ea6c7832e2dda5bb03c73b67981d35f1459e4..807c7098946b5589ce7d3394f864d6dccb484194 100644
--- a/src/hardware/hw_glob.h
+++ b/src/hardware/hw_glob.h
@@ -121,7 +121,7 @@ void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap);
 void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
 
 GLMapTexture_t *HWR_GetTexture(INT32 tex);
-void HWR_GetLevelFlat(levelflat_t *levelflat);
+void HWR_GetLevelFlat(levelflat_t *levelflat, boolean chromakeyed);
 void HWR_GetRawFlat(lumpnum_t flatlumpnum);
 
 void HWR_FreeTexture(patch_t *patch);
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index f5270f4e9e1381891e15d557652db63c14d03c39..bd8f316178dad3e48835e921c5cf7db0af734660 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -59,7 +59,7 @@ static void HWR_ProjectSprite(mobj_t *thing);
 static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
 static void HWR_ProjectBoundingBox(mobj_t *thing);
 
-void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap);
+void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, boolean chromakeyed, extracolormap_t *planecolormap);
 void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
                              INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap);
 
@@ -2252,7 +2252,7 @@ static void HWR_AddPolyObjectPlanes(void)
 			}
 			else
 			{
-				HWR_GetLevelFlat(&levelflats[polyobjsector->floorpic]);
+				HWR_GetLevelFlat(&levelflats[polyobjsector->floorpic], false);
 				HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude,
 										(light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->floorpic],
 										polyobjsector, 255, (light == -1 ? gl_frontsector->extra_colormap : *gl_frontsector->lightlist[light].extra_colormap));
@@ -2275,7 +2275,7 @@ static void HWR_AddPolyObjectPlanes(void)
 			}
 			else
 			{
-				HWR_GetLevelFlat(&levelflats[polyobjsector->ceilingpic]);
+				HWR_GetLevelFlat(&levelflats[polyobjsector->ceilingpic], false);
 				HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude,
 				                          (light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->ceilingpic],
 				                          polyobjsector, 255, (light == -1 ? gl_frontsector->extra_colormap : *gl_frontsector->lightlist[light].extra_colormap));
@@ -2405,7 +2405,7 @@ static void HWR_Subsector(size_t num)
 		{
 			if (sub->validcount != validcount)
 			{
-				HWR_GetLevelFlat(&levelflats[gl_frontsector->floorpic]);
+				HWR_GetLevelFlat(&levelflats[gl_frontsector->floorpic], false);
 				HWR_RenderPlane(sub, &extrasubsectors[num], false,
 					// Hack to make things continue to work around slopes.
 					locFloorHeight == cullFloorHeight ? locFloorHeight : gl_frontsector->floorheight,
@@ -2421,7 +2421,7 @@ static void HWR_Subsector(size_t num)
 		{
 			if (sub->validcount != validcount)
 			{
-				HWR_GetLevelFlat(&levelflats[gl_frontsector->ceilingpic]);
+				HWR_GetLevelFlat(&levelflats[gl_frontsector->ceilingpic], false);
 				HWR_RenderPlane(sub, &extrasubsectors[num], true,
 					// Hack to make things continue to work around slopes.
 					locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gl_frontsector->ceilingheight,
@@ -2479,7 +2479,7 @@ static void HWR_Subsector(size_t num)
 					                       *rover->bottomheight,
 					                       *gl_frontsector->lightlist[light].lightlevel,
 					                       alpha, rover->master->frontsector, PF_Fog|PF_NoTexture,
-										   true, rover->master->frontsector->extra_colormap);
+										   true, false, rover->master->frontsector->extra_colormap);
 				}
 				else if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) // SoM: Flags are more efficient
 				{
@@ -2492,11 +2492,11 @@ static void HWR_Subsector(size_t num)
 					                       *gl_frontsector->lightlist[light].lightlevel,
 					                       max(0, min(rover->alpha, 255)), rover->master->frontsector,
 					                       HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent),
-					                       false, *gl_frontsector->lightlist[light].extra_colormap);
+					                       false, rover->fofflags & FOF_SPLAT, *gl_frontsector->lightlist[light].extra_colormap);
 				}
 				else
 				{
-					HWR_GetLevelFlat(&levelflats[*rover->bottompic]);
+					HWR_GetLevelFlat(&levelflats[*rover->bottompic], rover->fofflags & FOF_SPLAT);
 					light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false);
 					HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic],
 					                rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap);
@@ -2524,7 +2524,7 @@ static void HWR_Subsector(size_t num)
 					                       *rover->topheight,
 					                       *gl_frontsector->lightlist[light].lightlevel,
 					                       alpha, rover->master->frontsector, PF_Fog|PF_NoTexture,
-										   true, rover->master->frontsector->extra_colormap);
+										   true, false, rover->master->frontsector->extra_colormap);
 				}
 				else if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend)
 				{
@@ -2537,11 +2537,11 @@ static void HWR_Subsector(size_t num)
 					                        *gl_frontsector->lightlist[light].lightlevel,
 					                        max(0, min(rover->alpha, 255)), rover->master->frontsector,
 					                        HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent),
-					                        false, *gl_frontsector->lightlist[light].extra_colormap);
+					                        false, rover->fofflags & FOF_SPLAT, *gl_frontsector->lightlist[light].extra_colormap);
 				}
 				else
 				{
-					HWR_GetLevelFlat(&levelflats[*rover->toppic]);
+					HWR_GetLevelFlat(&levelflats[*rover->toppic], rover->fofflags & FOF_SPLAT);
 					light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false);
 					HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic],
 					                  rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap);
@@ -3835,6 +3835,7 @@ typedef struct
 	sector_t *FOFSector;
 	FBITFIELD blend;
 	boolean fogplane;
+	boolean chromakeyed;
 	extracolormap_t *planecolormap;
 	INT32 drawcount;
 } planeinfo_t;
@@ -3876,7 +3877,7 @@ static INT32 drawcount = 0;
 #define MAX_TRANSPARENTFLOOR 512
 
 // This will likely turn into a copy of HWR_Add3DWater and replace it.
-void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap)
+void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, boolean chromakeyed, extracolormap_t *planecolormap)
 {
 	static size_t allocedplanes = 0;
 
@@ -3899,6 +3900,7 @@ void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boo
 	planeinfo[numplanes].FOFSector = FOFSector;
 	planeinfo[numplanes].blend = blend;
 	planeinfo[numplanes].fogplane = fogplane;
+	planeinfo[numplanes].chromakeyed = chromakeyed;
 	planeinfo[numplanes].planecolormap = planecolormap;
 	planeinfo[numplanes].drawcount = drawcount++;
 
@@ -4065,7 +4067,7 @@ static void HWR_CreateDrawNodes(void)
 			gl_frontsector = NULL;
 
 			if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture))
-				HWR_GetLevelFlat(sortnode[sortindex[i]].plane->levelflat);
+				HWR_GetLevelFlat(sortnode[sortindex[i]].plane->levelflat, sortnode[sortindex[i]].plane->chromakeyed);
 			HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel,
 				sortnode[sortindex[i]].plane->levelflat, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->planecolormap);
 		}
@@ -4074,9 +4076,11 @@ static void HWR_CreateDrawNodes(void)
 			// We aren't traversing the BSP tree, so make gl_frontsector null to avoid crashes.
 			gl_frontsector = NULL;
 
+			polyobj_t *po = sortnode[sortindex[i]].polyplane->polysector;
+
 			if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture))
-				HWR_GetLevelFlat(sortnode[sortindex[i]].polyplane->levelflat);
-			HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel,
+				HWR_GetLevelFlat(sortnode[sortindex[i]].polyplane->levelflat, po->flags & POF_SPLAT);
+			HWR_RenderPolyObjectPlane(po, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel,
 				sortnode[sortindex[i]].polyplane->levelflat, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap);
 		}
 		else if (sortnode[sortindex[i]].wall)
@@ -5555,7 +5559,7 @@ static void HWR_TogglePaletteRendering(void)
 			// The textures will still be converted to RGBA by r_opengl.
 			// This however makes hw_cache use paletted blending for composite textures!
 			// (patchformat is not touched)
-			textureformat = GL_TEXFMT_P_8;
+			textureformat = GL_TEXFMT_AP_88;
 
 			HWR_SetMapPalette();
 			HWR_SetPalette(pLocalPalette);