diff --git a/src/common/textures/hw_material.h b/src/common/textures/hw_material.h
index a280ac6fb..9e9428759 100644
--- a/src/common/textures/hw_material.h
+++ b/src/common/textures/hw_material.h
@@ -125,14 +125,6 @@ public:
 		return mTopOffset;
 	}
 
-	// Get right/bottom UV coordinates for patch drawing
-	float GetUL() const { return 0; }
-	float GetVT() const { return 0; }
-	float GetUR() const { return 1; }
-	float GetVB() const { return 1; }
-	float GetU(float upix) const { return upix/(float)mWidth; }
-	float GetV(float vpix) const { return vpix/(float)mHeight; }
-
 	static FMaterial *ValidateTexture(FTexture * tex, bool expand, bool create = true);
 	static FMaterial *ValidateTexture(FTextureID no, bool expand, bool trans, bool create = true);
 	const TArray<FTexture*> &GetLayerArray() const
diff --git a/src/common/textures/skyboxtexture.h b/src/common/textures/skyboxtexture.h
index 1c7a6ad2b..14ada8b4a 100644
--- a/src/common/textures/skyboxtexture.h
+++ b/src/common/textures/skyboxtexture.h
@@ -1,31 +1,3 @@
 #pragma once
 
 #include "textures.h"
-//-----------------------------------------------------------------------------
-//
-// This is not a real texture but will be added to the texture manager
-// so that it can be handled like any other sky.
-//
-//-----------------------------------------------------------------------------
-
-class FSkyBox : public FImageTexture
-{
-public:
-
-	FTexture *previous;
-	FTexture * faces[6];
-	bool fliptop;
-
-	FSkyBox(const char *name);
-	void SetSize();
-
-	bool Is3Face() const
-	{
-		return faces[5] == nullptr;
-	}
-
-	bool IsFlipped() const
-	{
-		return fliptop;
-	}
-};
diff --git a/src/common/textures/textures.h b/src/common/textures/textures.h
index a88bed179..f288214cc 100644
--- a/src/common/textures/textures.h
+++ b/src/common/textures/textures.h
@@ -623,6 +623,35 @@ struct FTexCoordInfo
 	void GetFromTexture(FGameTexture* tex, float x, float y, bool forceworldpanning);
 };
 
+//-----------------------------------------------------------------------------
+//
+// Todo: Get rid of this
+// The faces can easily be stored in the material layer array
+//
+//-----------------------------------------------------------------------------
+
+class FSkyBox : public FImageTexture
+{
+public:
+
+	FTexture* previous;
+	FTexture* faces[6];
+	bool fliptop;
+
+	FSkyBox(const char* name);
+	void SetSize();
+
+	bool Is3Face() const
+	{
+		return faces[5] == nullptr;
+	}
+
+	bool IsFlipped() const
+	{
+		return fliptop;
+	}
+};
+
 // Refactoring helper to allow piece by piece adjustment of the API
 class FGameTexture
 {
@@ -714,12 +743,18 @@ public:
 	void SetSpriteRect() { wrapped.SetSpriteRect(); }
 	const SpritePositioningInfo& GetSpritePositioning(int which) { /* todo: keep two sets of positioning infd*/ if (wrapped.mTrimResult == -1) wrapped.SetupSpriteData(); return wrapped.spi; }
 	int GetAreas(FloatRect** pAreas) const { return wrapped.GetAreas(pAreas); }
+	PalEntry GetSkyCapColor(bool bottom) { return wrapped.GetSkyCapColor(bottom); }
 
 	bool GetTranslucency()
 	{
 		return wrapped.GetTranslucency();
 	}
 
+	FGameTexture *GetSkyFace(int num)
+	{
+		return reinterpret_cast<FGameTexture*>(isSkybox() ? static_cast<FSkyBox*>(&wrapped)->faces[num] : nullptr);
+	}
+
 };
 
 
diff --git a/src/rendering/hwrenderer/scene/hw_decal.cpp b/src/rendering/hwrenderer/scene/hw_decal.cpp
index d112d5aee..e92a6c80e 100644
--- a/src/rendering/hwrenderer/scene/hw_decal.cpp
+++ b/src/rendering/hwrenderer/scene/hw_decal.cpp
@@ -47,8 +47,6 @@
 
 void HWDecal::DrawDecal(HWDrawInfo *di, FRenderState &state)
 {
-	auto tex = gltexture;
-
 	// calculate dynamic light effect.
 	if (di->Level->HasDynamicLights && !di->isFullbrightScene() && gl_light_sprites)
 	{
@@ -68,7 +66,7 @@ void HWDecal::DrawDecal(HWDrawInfo *di, FRenderState &state)
 
 	state.SetTextureMode(decal->RenderStyle);
 	state.SetRenderStyle(decal->RenderStyle);
-	state.SetMaterial(tex, CLAMP_XY, decal->Translation, -1);
+	state.SetMaterial(texture, false, CLAMP_XY, decal->Translation, -1);
 
 
 	// If srcalpha is one it looks better with a higher alpha threshold
@@ -313,8 +311,6 @@ void HWWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &nor
 	float vx = (glseg.x2 - glseg.x1) / linelength;
 	float vy = (glseg.y2 - glseg.y1) / linelength;
 	
-	FMaterial* tex = FMaterial::ValidateTexture(texture->GetTexture(), false);
-
 	DecalVertex dv[4];
 	enum
 	{
@@ -330,11 +326,12 @@ void HWWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &nor
 	
 	dv[UL].z = dv[UR].z = zpos;
 	dv[LL].z = dv[LR].z = dv[UL].z - decalheight;
-	dv[UL].v = dv[UR].v = tex->GetVT();
+	dv[UL].v = dv[UR].v = 0.f;
 	
-	dv[UL].u = dv[LL].u = tex->GetU(lefttex / decal->ScaleX);
-	dv[LR].u = dv[UR].u = tex->GetU(righttex / decal->ScaleX);
-	dv[LL].v = dv[LR].v = tex->GetVB();
+	float decalscale = float(decal->ScaleX * texture->GetDisplayWidth());
+	dv[UL].u = dv[LL].u = lefttex / decalscale;
+	dv[LR].u = dv[UR].u = righttex / decalscale;
+	dv[LL].v = dv[LR].v = 1.f;
 	
 	// now clip to the top plane
 	float vzt = (ztop[UL] - ztop[LL]) / linelength;
@@ -377,17 +374,15 @@ void HWWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &nor
 	
 	if (flipx)
 	{
-		float ur = tex->GetUR();
-		for (i = 0; i < 4; i++) dv[i].u = ur - dv[i].u;
+		for (i = 0; i < 4; i++) dv[i].u = 1.f - dv[i].u;
 	}
 	if (flipy)
 	{
-		float vb = tex->GetVB();
-		for (i = 0; i < 4; i++) dv[i].v = vb - dv[i].v;
+		for (i = 0; i < 4; i++) dv[i].v = 1.f - dv[i].v;
 	}
 
 	HWDecal *gldecal = di->AddDecal(type == RENDERWALL_MIRRORSURFACE);
-	gldecal->gltexture = tex;
+	gldecal->texture = texture;
 	gldecal->decal = decal;
 
 	if (decal->RenderFlags & RF_FULLBRIGHT)
diff --git a/src/rendering/hwrenderer/scene/hw_drawstructs.h b/src/rendering/hwrenderer/scene/hw_drawstructs.h
index 347f96aad..e8a244562 100644
--- a/src/rendering/hwrenderer/scene/hw_drawstructs.h
+++ b/src/rendering/hwrenderer/scene/hw_drawstructs.h
@@ -401,7 +401,7 @@ struct DecalVertex
 
 struct HWDecal
 {
-	FMaterial *gltexture;
+	FGameTexture *texture;
 	TArray<lightlist_t> *lightlist;
 	DBaseDecal *decal;
 	DecalVertex dv[4];
diff --git a/src/rendering/hwrenderer/scene/hw_portal.h b/src/rendering/hwrenderer/scene/hw_portal.h
index 63a2f5518..10fd90d7d 100644
--- a/src/rendering/hwrenderer/scene/hw_portal.h
+++ b/src/rendering/hwrenderer/scene/hw_portal.h
@@ -13,7 +13,7 @@ struct HWSkyInfo
 {
 	float x_offset[2];
 	float y_offset;		// doubleskies don't have a y-offset
-	FMaterial * texture[2];
+	FGameTexture * texture[2];
 	FTextureID skytexno1;
 	bool mirrored;
 	bool doublesky;
@@ -358,8 +358,8 @@ struct HWSkyPortal : public HWPortal
 	friend struct HWEEHorizonPortal;
 
 	void RenderRow(HWDrawInfo *di, FRenderState &state, EDrawType prim, int row, bool apply = true);
-	void RenderBox(HWDrawInfo *di, FRenderState &state, FTextureID texno, FMaterial * gltex, float x_offset, bool sky2);
-	void RenderDome(HWDrawInfo *di, FRenderState &state, FMaterial * tex, float x_offset, float y_offset, bool mirror, int mode);
+	void RenderBox(HWDrawInfo *di, FRenderState &state, FTextureID texno, FGameTexture * gltex, float x_offset, bool sky2);
+	void RenderDome(HWDrawInfo *di, FRenderState &state, FGameTexture * tex, float x_offset, float y_offset, bool mirror, int mode);
 
 protected:
 	virtual void DrawContents(HWDrawInfo *di, FRenderState &state);
diff --git a/src/rendering/hwrenderer/scene/hw_sky.cpp b/src/rendering/hwrenderer/scene/hw_sky.cpp
index ce48d9437..af2328bbc 100644
--- a/src/rendering/hwrenderer/scene/hw_sky.cpp
+++ b/src/rendering/hwrenderer/scene/hw_sky.cpp
@@ -63,7 +63,7 @@ void HWSkyInfo::init(HWDrawInfo *di, int sky1, PalEntry FadeColor)
 		FTextureID texno = s->GetTexture(pos);
 		auto tex = TexMan.GetGameTexture(texno, true);
 		if (!tex || !tex->isValid()) goto normalsky;
-		texture[0] = FMaterial::ValidateTexture(tex->GetTexture(), false);
+		texture[0] = tex;
 		skytexno1 = texno;
 		x_offset[0] = s->GetTextureXOffset(pos) * (360.f/65536.f);
 		y_offset = s->GetTextureYOffset(pos);
@@ -76,7 +76,7 @@ void HWSkyInfo::init(HWDrawInfo *di, int sky1, PalEntry FadeColor)
 		{
 			auto tex1 = TexMan.GetGameTexture(di->Level->skytexture1, true);
 			if (tex1) tex1 = tex1->GetFrontSkyLayer();
-			texture[1] = FMaterial::ValidateTexture(tex1->GetTexture(), false);
+			texture[1] = tex1;
 			x_offset[1] = di->Level->hw_sky1pos;
 			doublesky = true;
 		}
@@ -84,14 +84,14 @@ void HWSkyInfo::init(HWDrawInfo *di, int sky1, PalEntry FadeColor)
 		if ((di->Level->flags&LEVEL_SWAPSKIES || (sky1 == PL_SKYFLAT) || (di->Level->flags&LEVEL_DOUBLESKY)) &&
 			di->Level->skytexture2 != di->Level->skytexture1)	// If both skies are equal use the scroll offset of the first!
 		{
-			texture[0] = FMaterial::ValidateTexture(di->Level->skytexture2, false, true);
+			texture[0] = TexMan.GetGameTexture(di->Level->skytexture2, true);
 			skytexno1 = di->Level->skytexture2;
 			sky2 = true;
 			x_offset[0] = di->Level->hw_sky2pos;
 		}
 		else if (!doublesky)
 		{
-			texture[0] = FMaterial::ValidateTexture(di->Level->skytexture1, false, true);
+			texture[0] = TexMan.GetGameTexture(di->Level->skytexture1, true);
 			skytexno1 = di->Level->skytexture1;
 			x_offset[0] = di->Level->hw_sky1pos;
 		}
diff --git a/src/rendering/hwrenderer/scene/hw_skydome.cpp b/src/rendering/hwrenderer/scene/hw_skydome.cpp
index 968b79fbb..58f25f532 100644
--- a/src/rendering/hwrenderer/scene/hw_skydome.cpp
+++ b/src/rendering/hwrenderer/scene/hw_skydome.cpp
@@ -282,17 +282,17 @@ void FSkyVertexBuffer::CreateDome()
 //
 //-----------------------------------------------------------------------------
 
-void FSkyVertexBuffer::SetupMatrices(HWDrawInfo *di, FMaterial *tex, float x_offset, float y_offset, bool mirror, int mode, VSMatrix &modelMatrix, VSMatrix &textureMatrix)
+void FSkyVertexBuffer::SetupMatrices(HWDrawInfo *di, FGameTexture *tex, float x_offset, float y_offset, bool mirror, int mode, VSMatrix &modelMatrix, VSMatrix &textureMatrix)
 {
-	int texw = tex->TextureWidth();
-	int texh = tex->TextureHeight();
+	int texw = tex->GetDisplayWidth();
+	int texh = tex->GetDisplayHeight();
 
 	modelMatrix.loadIdentity();
 	modelMatrix.rotate(-180.0f + x_offset, 0.f, 1.f, 0.f);
 
 	float xscale = texw < 1024.f ? floor(1024.f / float(texw)) : 1.f;
 	float yscale = 1.f;
-	auto texskyoffset = tex->Source()->GetSkyOffset() + skyoffset;
+	auto texskyoffset = tex->GetSkyOffset() + skyoffset;
 	if (texh <= 128 && (di->Level->flags & LEVEL_FORCETILEDSKY))
 	{
 		modelMatrix.translate(0.f, (-40 + texskyoffset)*skyoffsetfactor, 0.f);
diff --git a/src/rendering/hwrenderer/scene/hw_skydome.h b/src/rendering/hwrenderer/scene/hw_skydome.h
index 4084ef96f..e4865f330 100644
--- a/src/rendering/hwrenderer/scene/hw_skydome.h
+++ b/src/rendering/hwrenderer/scene/hw_skydome.h
@@ -4,7 +4,7 @@
 #include "matrix.h"
 #include "hwrenderer/data/buffers.h"
 
-class FMaterial;
+class FGameTexture;
 class FRenderState;
 class IVertexBuffer;
 struct HWSkyPortal;
@@ -70,7 +70,7 @@ public:
 
 	FSkyVertexBuffer();
 	~FSkyVertexBuffer();
-	void SetupMatrices(HWDrawInfo *di, FMaterial *tex, float x_offset, float y_offset, bool mirror, int mode, VSMatrix &modelmatrix, VSMatrix &textureMatrix);
+	void SetupMatrices(HWDrawInfo *di, FGameTexture *tex, float x_offset, float y_offset, bool mirror, int mode, VSMatrix &modelmatrix, VSMatrix &textureMatrix);
 	std::pair<IVertexBuffer *, IIndexBuffer *> GetBufferObjects() const
 	{
 		return std::make_pair(mVertexBuffer, nullptr);
diff --git a/src/rendering/hwrenderer/scene/hw_skyportal.cpp b/src/rendering/hwrenderer/scene/hw_skyportal.cpp
index d4c4f11a7..e1eb942d8 100644
--- a/src/rendering/hwrenderer/scene/hw_skyportal.cpp
+++ b/src/rendering/hwrenderer/scene/hw_skyportal.cpp
@@ -50,11 +50,11 @@ void HWSkyPortal::RenderRow(HWDrawInfo *di, FRenderState &state, EDrawType prim,
 //
 //-----------------------------------------------------------------------------
 
-void HWSkyPortal::RenderDome(HWDrawInfo *di, FRenderState &state, FMaterial * tex, float x_offset, float y_offset, bool mirror, int mode)
+void HWSkyPortal::RenderDome(HWDrawInfo *di, FRenderState &state, FGameTexture * tex, float x_offset, float y_offset, bool mirror, int mode)
 {
 	if (tex)
 	{
-		state.SetMaterial(tex, CLAMP_NONE, 0, -1);
+		state.SetMaterial(tex, false, CLAMP_NONE, 0, -1);
 		state.EnableModelMatrix(true);
 		state.EnableTextureMatrix(true);
 
@@ -66,13 +66,12 @@ void HWSkyPortal::RenderDome(HWDrawInfo *di, FRenderState &state, FMaterial * te
 	// The caps only get drawn for the main layer but not for the overlay.
 	if (mode == FSkyVertexBuffer::SKYMODE_MAINLAYER && tex != NULL)
 	{
-		auto base = tex->Source();
-		PalEntry pe = base->GetSkyCapColor(false);
+		PalEntry pe = tex->GetSkyCapColor(false);
 		state.SetObjectColor(pe);
 		state.EnableTexture(false);
 		RenderRow(di, state, DT_TriangleFan, 0);
 
-		pe = base->GetSkyCapColor(true);
+		pe = tex->GetSkyCapColor(true);
 		state.SetObjectColor(pe);
 		RenderRow(di, state, DT_TriangleFan, rc);
 		state.EnableTexture(true);
@@ -95,9 +94,9 @@ void HWSkyPortal::RenderDome(HWDrawInfo *di, FRenderState &state, FMaterial * te
 //
 //-----------------------------------------------------------------------------
 
-void HWSkyPortal::RenderBox(HWDrawInfo *di, FRenderState &state, FTextureID texno, FMaterial * gltex, float x_offset, bool sky2)
+void HWSkyPortal::RenderBox(HWDrawInfo *di, FRenderState &state, FTextureID texno, FGameTexture * gltex, float x_offset, bool sky2)
 {
-	FSkyBox * sb = static_cast<FSkyBox*>(gltex->Source());
+	FSkyBox * sb = static_cast<FSkyBox*>(gltex->GetTexture());
 	int faces;
 	FMaterial * tex;
 
@@ -182,7 +181,7 @@ void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state)
 	di->SetupView(state, 0, 0, 0, !!(mState->MirrorFlag & 1), !!(mState->PlaneMirrorFlag & 1));
 
 	state.SetVertexBuffer(vertexBuffer);
-	if (origin->texture[0] && origin->texture[0]->Source()->isSkybox())
+	if (origin->texture[0] && origin->texture[0]->isSkybox())
 	{
 		RenderBox(di, state, origin->skytexno1, origin->texture[0], origin->x_offset[0], origin->sky2);
 	}