[Open Assets] SRB2 with some OpenGL fixes

This content may be freely modified and/or maintained by anyone.
Status
Not open for further replies.

Sryder

'That brit'
Kart Krew™️
This is something that I have been working on for a few months on and off now. I know it may seem a little late with 2.1 this close to being out, but better late than never right?

It aims to sort out the majority of the issues with how OpenGL draws things. Some of these changes were taken from CB where the issue was fixed there. A changelog of everything that has changed (as far as I can remember anyway) is below. If you see anything I missed from here tell me so I can add it.

The r_opengl.dll included is optional, all it does is alter the lighting on MD2 models. If you don't use MD2 models there is no need for it. If you do use it be sure to backup the original one first, I have included the vanilla one too in case however.

This executable is compatible with vanilla SRB2, you can join netgames with vanilla with this and vice versa.

  • Fixed Lighting
  • Fog Blocks drawn as translucent polygons like in CB
  • Fixed sky drawing in instances where there was REDWALL or HOM
  • Translucent walls no longer get lighting from other places
  • Translucent FOF's with an opacity of 255 render
  • Holes in flats that should have them
  • Colourmaps have their fading colours
  • Sprite shadows aren't broken anymore
  • Midtextures are aligned correctly in the cases where they weren't
  • Repeating midtextures work
  • Sector Flat Alignment rotation works
  • The screen transition has had a small fix
  • Heatwave effect, it is only an altered underwater effect however
  • Multiple Character MD2's from CB with item boxes and end signs also using MD2's
  • MD2's that are replacing sprites with only a single rotation (e.g. monitors) rotate to face the screen
  • MD2's lighted correctly
  • MD2's use correct animations when the sprite is using FULLBRIGHT or translucency
  • With the r_opengl.dll included MD2's are lit from above rather than behind
  • New console command "gr_softwarefog" attempts to emulate lighting from software. Unfortunately it usually goes too dark so it is disabled by default. values are "Off", "On", and "Lightplanes"

  • Translucency sorting issues with sprites, MD2s, walls, and planes
  • Performance Issues
  • Issues with "Nearest_Mipmapped" filter, default has been changed to "Nearest"
  • Things and geometry drawn behind the sky
  • Single patch textures with holes in them are drawn higher if there's empty space in the texture in software, the same is not done in OpenGL (See Boinciel's Sonic Schoolhouse)
  • Sprites when scaled don't align correctly
  • The ERZ2 miniboss sinks into the ceiling after it activates, I do not know why
  • Weather is still inactive, I couldn't figure out what was causing the issues with it.

I hope you can enjoy this while you still can.
 

Attachments

  • MD2Light.png
    MD2Light.png
    182.2 KB · Views: 2,909
  • SoftwareFog.png
    SoftwareFog.png
    227.9 KB · Views: 2,295
  • FogBlockColourmaps.png
    FogBlockColourmaps.png
    203.3 KB · Views: 2,203
  • MidtextureTranslucentFOFs.jpg
    MidtextureTranslucentFOFs.jpg
    171.8 KB · Views: 1,984
  • Fog.jpg
    Fog.jpg
    88.2 KB · Views: 2,073
  • SRB2OpenGL.zip
    1.2 MB · Views: 5,289
  • SRB2v2.0.7OpenGLSource.zip
    6.2 MB · Views: 2,468
Last edited:
Oh wow, consider me impressed! This fixes most of the major problems with OpenGL mode and makes the game entirely playable without issues when using that renderer as a result.

I would have liked to see polyobject flat rendering implemented at last, but beggars can't be choosers.

Regardless, I'm hoping that the release of 2.1 won't break this too much. But there will probably be a few issues cropping up after 2.1 comes out.

OpenGL supported kthxbye
 
Finally, a true Godsend for the 2.0.7 vanilla SRB2's final days before 2.1. Question: Will the MD2 models work like they did in CB?
 
Finally, a true Godsend for the 2.0.7 vanilla SRB2's final days before 2.1. Question: Will the MD2 models work like they did in CB?

Yes, they're setup the same way for characters with "<character name> <MD2 name> <scale> <offset>" in the md2.dat. Other objects use the same system as before.
 
This is truly amazing.

I've rarely, if ever touched OpenGL due to how buggy it all was (and the fact my Vista doesn't exactly have the best graphics card out there). Everything that was mostly broken about it was patched up and I feel like I could actually use OpenGL more than once or twice! Like Whackjood, I really hope to see all of this fancy stuff brought into 2.1 in some form or another.

alsojasper.md2pl0x *ban*
 
2.0.7 diff?

Code:
diff --git a/src/f_wipe.c b/src/f_wipe.c
index 8bab793..2f665d6 100644
--- a/src/f_wipe.c
+++ b/src/f_wipe.c
@@ -82,13 +82,6 @@ static INT32 F_DoWipe(INT32 width, INT32 height, tic_t ticks)
 
 	while (ticks--)
 	{
-		// slowdown
-		if (slowdown++)
-		{
-			slowdown = 0;
-			return false;
-		}
-
 #ifdef SHUFFLE
 		if(rendermode != render_soft)
 		{
@@ -98,6 +91,14 @@ static INT32 F_DoWipe(INT32 width, INT32 height, tic_t ticks)
 			continue;
 		}
 #endif
+
+		// slowdown
+		if (slowdown++)
+		{
+			slowdown = 0;
+			return false;
+		}
+
 		w = wipe_scr;
 		e = wipe_scr_end;
 
diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c
index 0ca7c8b..3ef35c5 100644
--- a/src/hardware/hw_cache.c
+++ b/src/hardware/hw_cache.c
@@ -582,7 +582,7 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
 	grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64;
 	grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
 	grMipmap->grInfo.format = GR_TEXFMT_P_8;
-	grMipmap->flags = TF_WRAPXY;
+	grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
 
 	size = W_LumpLength(flatlumpnum);
 
diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h
index 56419ff..faf65b4 100644
--- a/src/hardware/hw_glob.h
+++ b/src/hardware/hw_glob.h
@@ -73,7 +73,6 @@ typedef struct gr_vissprite_s
 	lumpnum_t patchlumpnum;
 	boolean flip;
 	UINT8 translucency;       //alpha level 0-255
-	UINT8 sectorlight;        // ...
 	mobj_t *mobj;
 	boolean precip; // Tails 08-25-2002
 	boolean vflip;
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 9ac52d9..22207a0 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -41,6 +41,9 @@
 #include "../i_system.h"
 #endif
 
+#include "hw_md2.h"
+#include "../m_random.h"
+
 #define R_FAKEFLOORS
 //#define HWPRECIP
 #define SORTING
@@ -64,7 +67,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
 
 #ifdef SORTING
 void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight,
-                             INT32 lightlevel, INT32 alpha, sector_t *FOFSector);
+                             INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap);
 #else
 static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight,
                            INT32 lightlevel, INT32 alpha, sector_t *FOFSector);
@@ -109,13 +112,13 @@ consvar_t cv_grfov = {"gr_fov", "90", CV_FLOAT|CV_CALL, grfov_cons_t, CV_grFov_O
 consvar_t cv_grfogdensity = {"gr_fogdensity", "25", CV_CALL|CV_NOINIT, CV_Unsigned,
                              CV_FogDensity_ONChange, 0, NULL, NULL, 0, 0, NULL};
 #else
-consvar_t cv_grfogdensity = {"gr_fogdensity", "300", 0, CV_Unsigned,
+consvar_t cv_grfogdensity = {"gr_fogdensity", "150", 0, CV_Unsigned,
                              CV_FogDensity_ONChange, 0, NULL, NULL, 0, 0, NULL};
 #endif
 
 // Unfortunately, this can no longer be saved...
 #ifdef SHUFFLE
-consvar_t cv_grfiltermode = {"gr_filtermode", "Nearest_Mipmap", CV_CALL, grfiltermode_cons_t,
+consvar_t cv_grfiltermode = {"gr_filtermode", "Nearest", CV_CALL, grfiltermode_cons_t,
                              CV_filtermode_ONChange, 0, NULL, NULL, 0, 0, NULL};
 #else
 consvar_t cv_grfiltermode = {"gr_filtermode", "Bilinear", CV_CALL, grfiltermode_cons_t,
@@ -380,9 +383,9 @@ static float gr_fovlud;
 static UINT8 lightleveltonumlut[256];
 
 // added to SRB2's sector lightlevel to make things a bit brighter (sprites/walls/planes)
-FUNCMATH static UINT8 LightLevelToLum(INT32 l)
+FUNCMATH UINT8 LightLevelToLum(INT32 l)
 {
-#ifdef HARDWAREFIX
+/*#ifdef HARDWAREFIX
 	if (!cv_grfog.value)
 	{
 		if(l > 255)
@@ -391,7 +394,7 @@ FUNCMATH static UINT8 LightLevelToLum(INT32 l)
 			l = 0;
 		return lightleveltonumlut[l];
 	}
-#endif
+#endif*/
 	return (UINT8)(255*gld_CalcLightLevel(l));
 /*
 	l = lightleveltonumlut[l];
@@ -416,54 +419,113 @@ static inline void InitLumLut(void)
 
 #ifdef HARDWAREFIX
 //#define FOGFACTOR 300 //was 600 >> Covered by cv_grfogdensity
-#define NORMALFOG 0x19000000
-#define CALCFOGALPHA(x,y) (UINT8)(((float)(x)/((0x19 - (y))/12.0f+1.0f)))
-#define CALCLIGHT(x,y) ((float)(x)/((0xFF - (y))/127.0f+1.0f))
-static UINT32 HWR_Lighting(INT32 light, UINT32 color)
+#define NORMALFOG 0x00000000
+#define FADEFOG 0x19000000
+#define CALCFOGDENSITY(x) ((float)((5220.0f*(1.0f/((x)/41.0f+1.0f)))-(5220.0f*(1.0f/(255.0f/41.0f+1.0f))))) // Approximate fog calculation based off of software walls
+#define CALCFOGDENSITYFLOOR(x) ((float)((40227.0f*(1.0f/((x)/11.0f+1.0f)))-(40227.0f*(1.0f/(255.0f/11.0f+1.0f))))) // Approximate fog calculation based off of software floors
+#define CALCLIGHT(x,y) ((float)(x)*((y)/255.0f))
+UINT32 HWR_Lighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogblockpoly, boolean plane)
 {
-	RGBA_t realcolor, surfcolor;
+	RGBA_t realcolor, fogcolor, surfcolor;
+	INT32 alpha, fogalpha;
 
 	realcolor.rgba = color;
+	fogcolor.rgba = fadecolor;
 
-	if(cv_grfog.value)
+	alpha = (realcolor.s.alpha*255)/25;
+	fogalpha = (fogcolor.s.alpha*255)/25;
+
+	if (cv_grfog.value && cv_grsoftwarefog.value) // Only do this when fog is on, software fog mode is on, and the poly is not from a fog block
 	{
-		surfcolor.s.red = (UINT8)(0xFF-(realcolor.s.green+realcolor.s.blue)/2);
-		surfcolor.s.green = (UINT8)(0xFF-(realcolor.s.red+realcolor.s.blue)/2);
-		surfcolor.s.blue = (UINT8)(0xFF-(realcolor.s.red+realcolor.s.green)/2);
-		surfcolor.s.alpha = 0xFF;
+		// Modulate the colors by alpha.
+		realcolor.s.red = (UINT8)(CALCLIGHT(alpha,realcolor.s.red));
+		realcolor.s.green = (UINT8)(CALCLIGHT(alpha,realcolor.s.green));
+		realcolor.s.blue = (UINT8)(CALCLIGHT(alpha,realcolor.s.blue));
 
-		if(light == 0xFF && color == NORMALFOG)
-		{
-			light = 0xFE;
-			color = realcolor.rgba = 0x19FFFFFF;
-		}
+		// Set the surface colors and further modulate the colors by light.
+		surfcolor.s.red = (UINT8)(CALCLIGHT((0xFF-alpha),255)+CALCLIGHT(realcolor.s.red,255));
+		surfcolor.s.green = (UINT8)(CALCLIGHT((0xFF-alpha),255)+CALCLIGHT(realcolor.s.green,255));
+		surfcolor.s.blue = (UINT8)(CALCLIGHT((0xFF-alpha),255)+CALCLIGHT(realcolor.s.blue,255));
+		surfcolor.s.alpha = 0xFF;
 
 		// Modulate the colors by alpha.
-		realcolor.s.red = CALCFOGALPHA(realcolor.s.red,realcolor.s.alpha);
-		realcolor.s.green = CALCFOGALPHA(realcolor.s.green,realcolor.s.alpha);
-		realcolor.s.blue = CALCFOGALPHA(realcolor.s.blue,realcolor.s.alpha);
-
-		// Set the fog options.
-		light = CALCFOGALPHA(light,realcolor.s.alpha);
-		HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, (INT32)(cv_grfogdensity.value-(cv_grfogdensity.value*(float)light/255.0f)));
-		HWD.pfnSetSpecialState(HWD_SET_FOG_COLOR, (realcolor.s.red*0x10000)+(realcolor.s.green*0x100)+realcolor.s.blue);
-		HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 1);
+		fogcolor.s.red = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.red));
+		fogcolor.s.green = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.green));
+		fogcolor.s.blue = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.blue));
 	}
 	else
-	{ // No fog? Sucks for j00.
+	{
+		// Modulate the colors by alpha.
+		realcolor.s.red = (UINT8)(CALCLIGHT(alpha,realcolor.s.red));
+		realcolor.s.green = (UINT8)(CALCLIGHT(alpha,realcolor.s.green));
+		realcolor.s.blue = (UINT8)(CALCLIGHT(alpha,realcolor.s.blue));
+
+		// Set the surface colors and further modulate the colors by light.
+		surfcolor.s.red = (UINT8)(CALCLIGHT((0xFF-alpha),light)+CALCLIGHT(realcolor.s.red,light));
+		surfcolor.s.green = (UINT8)(CALCLIGHT((0xFF-alpha),light)+CALCLIGHT(realcolor.s.green,light));
+		surfcolor.s.blue = (UINT8)(CALCLIGHT((0xFF-alpha),light)+CALCLIGHT(realcolor.s.blue,light));
+
 		// Modulate the colors by alpha.
-		realcolor.s.red = CALCFOGALPHA(realcolor.s.red,realcolor.s.alpha);
-		realcolor.s.green = CALCFOGALPHA(realcolor.s.green,realcolor.s.alpha);
-		realcolor.s.blue = CALCFOGALPHA(realcolor.s.blue,realcolor.s.alpha);
+		fogcolor.s.red = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.red));
+		fogcolor.s.green = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.green));
+		fogcolor.s.blue = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.blue));
 
 		// Set the surface colors and further modulate the colors by light.
-		surfcolor.s.red = (UINT8)CALCLIGHT(0xFF-(realcolor.s.green+realcolor.s.blue)/2,light);
-		surfcolor.s.green = (UINT8)CALCLIGHT(0xFF-(realcolor.s.red+realcolor.s.blue)/2,light);
-		surfcolor.s.blue = (UINT8)CALCLIGHT(0xFF-(realcolor.s.red+realcolor.s.green)/2,light);
+		surfcolor.s.red = surfcolor.s.red+((UINT8)(CALCLIGHT((0xFF-fogalpha),(255-light))+CALCLIGHT(fogcolor.s.red,(255-light))));
+		surfcolor.s.green = surfcolor.s.green+((UINT8)(CALCLIGHT((0xFF-fogalpha),(255-light))+CALCLIGHT(fogcolor.s.green,(255-light))));
+		surfcolor.s.blue = surfcolor.s.blue+((UINT8)(CALCLIGHT((0xFF-fogalpha),(255-light))+CALCLIGHT(fogcolor.s.blue,(255-light))));
 		surfcolor.s.alpha = 0xFF;
 	}
+
+	if(cv_grfog.value)
+	{
+		if (cv_grsoftwarefog.value)
+		{
+			fogcolor.s.red = (UINT8)((CALCLIGHT(fogcolor.s.red,(255-light)))+(CALCLIGHT(realcolor.s.red,light)));
+			fogcolor.s.green = (UINT8)((CALCLIGHT(fogcolor.s.green,(255-light)))+(CALCLIGHT(realcolor.s.green,light)));
+			fogcolor.s.blue = (UINT8)((CALCLIGHT(fogcolor.s.blue,(255-light)))+(CALCLIGHT(realcolor.s.blue,light)));
+
+			// Set the fog options.
+			if (cv_grsoftwarefog.value == 1 && plane) // With floors, software draws them way darker for their distance
+				HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, (INT32)(CALCFOGDENSITYFLOOR(light)));
+			else // everything else is drawn like walls
+				HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, (INT32)(CALCFOGDENSITY(light)));
+		}
+		else
+		{
+			fogcolor.s.red = (UINT8)((CALCLIGHT(fogcolor.s.red,(255-light)))+(CALCLIGHT(realcolor.s.red,light)));
+			fogcolor.s.green = (UINT8)((CALCLIGHT(fogcolor.s.green,(255-light)))+(CALCLIGHT(realcolor.s.green,light)));
+			fogcolor.s.blue = (UINT8)((CALCLIGHT(fogcolor.s.blue,(255-light)))+(CALCLIGHT(realcolor.s.blue,light)));
+
+			fogalpha = (UINT8)((CALCLIGHT(fogalpha,(255-light)))+(CALCLIGHT(alpha,light)));
+
+			// Set the fog options.
+			light = (UINT8)(CALCLIGHT(light,(255-fogalpha)));
+			HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, (INT32)(cv_grfogdensity.value-(cv_grfogdensity.value*(float)light/255.0f)));
+		}
+
+		HWD.pfnSetSpecialState(HWD_SET_FOG_COLOR, (fogcolor.s.red*0x10000)+(fogcolor.s.green*0x100)+fogcolor.s.blue);
+		HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 1);
+	}
 	return surfcolor.rgba;
 }
+
+static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color, UINT32 fadecolor) // Let's see if this can work
+{
+	RGBA_t realcolor, fogcolor, surfcolor;
+	INT32 alpha, fogalpha;
+
+	realcolor.rgba = color;
+	fogcolor.rgba = fadecolor;
+
+	alpha = (realcolor.s.alpha*255)/25;
+	fogalpha = (fogcolor.s.alpha*255)/25;
+
+	// Fog blocks seem to get slightly more opaque with more opaque colourmap opacity, and much more opaque with darker brightness
+	surfcolor.s.alpha = (UINT8)(CALCLIGHT(light, ((0xFF-light)+alpha)/2)+CALCLIGHT(0xFF-light, ((light)+fogalpha)/2));
+
+	return surfcolor.s.alpha;
+}
 #endif
 
 // ==========================================================================
@@ -480,7 +542,7 @@ static FOutVector  planeVerts[MAXPLANEVERTICES];
 // HWR_RenderPlane  : Render a floor or ceiling convex polygon
 // -----------------+
 static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fixedheight,
-                           FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector)
+                           FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap)
 {
 	polyvertex_t *  pv;
 	float           height; //constant y for all points on the convex flat polygon
@@ -492,6 +554,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi
 	INT32 flatflag;
 	size_t len;
 	float scrollx = 0.0f, scrolly = 0.0f;
+	angle_t angle = 0;
 	FSurfaceInfo    Surf;
 
 	// no convex poly were generated for this subsector
@@ -559,11 +622,13 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi
 		{
 			scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize;
 			scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize;
+			angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT;
 		}
 		else // it's a ceiling
 		{
 			scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize;
 			scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize;
+			angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT;
 		}
 	}
 	else if (gr_frontsector)
@@ -572,19 +637,55 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi
 		{
 			scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize;
 			scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize;
+			angle = gr_frontsector->floorpic_angle>>ANGLETOFINESHIFT;
 		}
 		else // it's a ceiling
 		{
 			scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize;
 			scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize;
+			angle = gr_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT;
 		}
 	}
 
+	fixed_t tempxsow, tempytow;
+
+	if (angle) // Only needs to be done if there's an altered angle
+	{
+		// This needs to be done so that it scrolls in a different direction after rotation like software
+		tempxsow = FLOAT_TO_FIXED(scrollx);
+		tempytow = FLOAT_TO_FIXED(scrolly);
+		scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
+		scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
+
+		// This needs to be done so everything aligns after rotation
+		// It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does
+		tempxsow = FLOAT_TO_FIXED(flatxref);
+		tempytow = FLOAT_TO_FIXED(flatyref);
+		flatxref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
+		flatyref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
+	}
+
 	for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++)
 	{
 		// Hurdler: add scrolling texture on floor/ceiling
 		v3d->sow = (float)((pv->x / fflatsize) - flatxref + scrollx);
 		v3d->tow = (float)(flatyref - (pv->y / fflatsize) + scrolly);
+
+		//v3d->sow = (float)(pv->x / fflatsize);
+		//v3d->tow = (float)(pv->y / fflatsize);
+
+		// Need to rotate before translate
+		if (angle) // Only needs to be done if there's an altered angle
+		{
+			tempxsow = FLOAT_TO_FIXED(v3d->sow);
+			tempytow = FLOAT_TO_FIXED(v3d->tow);
+			v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
+			v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle))));
+		}
+
+		//v3d->sow = (float)(v3d->sow - flatxref + scrollx);
+		//v3d->tow = (float)(flatyref - v3d->tow + scrolly);
+
 		v3d->x = pv->x;
 		v3d->y = height;
 		v3d->z = pv->y;
@@ -620,7 +721,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi
 	Surf.FlatColor.s.blue = LightLevelToLum(lightlevel); //  Don't take from the frontsector, or the game will crash
 #endif
 
-	// colormap test
+/*	// colormap test
 	if (gr_frontsector)
 	{
 		sector_t *psector = gr_frontsector;
@@ -640,9 +741,9 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi
 		}
 		if (psector->extra_colormap)
 #ifdef HARDWAREFIX
-			Surf.FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel),psector->extra_colormap->rgba);
+			Surf.FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel),psector->extra_colormap->rgba,psector->extra_colormap->fadergba, false, true);
 		else
-			Surf.FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel),NORMALFOG);
+			Surf.FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel),NORMALFOG,FADEFOG, false, true);
 #else
 		{
 			RGBA_t temp;
@@ -659,14 +760,25 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi
 	}
 #ifdef HARDWAREFIX
 	else
-		Surf.FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel),NORMALFOG);
-#endif
+		Surf.FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel),NORMALFOG,FADEFOG, false, true);
+#endif*/
+
+	if (planecolormap)
+		if (fogplane)
+			Surf.FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel), planecolormap->rgba, planecolormap->fadergba, true, false);
+		else
+			Surf.FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel), planecolormap->rgba, planecolormap->fadergba, false, true);
+	else
+		if (fogplane)
+			Surf.FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel), NORMALFOG, FADEFOG, true, false);
+		else
+			Surf.FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel), NORMALFOG, FADEFOG, false, true);
 
 	if (PolyFlags & PF_Translucent)
 	{
-		Surf.FlatColor.s.alpha = (UINT8)(PolyFlags>>24);
+		Surf.FlatColor.s.alpha = alpha;
 		HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts,
-		                   PF_Translucent|PF_Modulated|PF_Occlude|PF_Clip);
+		                   PolyFlags|PF_Modulated|PF_Occlude|PF_Clip);
 	}
 	else
 	{
@@ -838,7 +950,7 @@ FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf)
 //         clipped so that only a visible portion of the wall seg is drawn.
 // floorheight, ceilingheight : depend on wall upper/lower/middle, comes from the sectors.
 
-static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo * pSurf, INT32 texnum, FBITFIELD blend);
+static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo * pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap);
 
 // -----------------+
 // HWR_ProjectWall  :
@@ -852,7 +964,7 @@ static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo * pSurf,
 */
 static void HWR_ProjectWall(wallVert3D   * wallVerts,
                                     FSurfaceInfo * pSurf,
-                                    FBITFIELD blendmode)
+                                    FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap)
 {
 	FOutVector  trVerts[4];
 	FOutVector  *wv;
@@ -889,6 +1001,15 @@ static void HWR_ProjectWall(wallVert3D   * wallVerts,
 	wv->y   = wallVerts->y;
 	wv->z   = wallVerts->z;
 
+	if (wallcolormap)
+	{
+		pSurf->FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel), wallcolormap->rgba, wallcolormap->fadergba, false, false);
+	}
+	else
+	{
+		pSurf->FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel), NORMALFOG, FADEFOG, false, false);
+	}
+
 	HWD.pfnDrawPolygon(pSurf, trVerts, 4, blendmode|PF_Modulated|PF_Occlude|PF_Clip);
 
 #ifdef WALLSPLATS
@@ -967,11 +1088,35 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 //		if (!list[i].caster)
 //			continue;
 
+		solid = false;
+
 		if (list[i].caster)
-			solid = list[i].caster->flags & (cutflag&~FF_TRANSLUCENT);
+		{
+			if (sector->lightlist[i].caster->flags & FF_SOLID && !(cutflag & FF_EXTRA))
+				solid = true;
+			else if (sector->lightlist[i].caster->flags & FF_CUTEXTRA && cutflag & FF_EXTRA)
+			{
+				if (sector->lightlist[i].caster->flags & FF_EXTRA)
+				{
+					if (sector->lightlist[i].caster->flags == cutflag) // Only merge with your own types
+						solid = true;
+				}
+				else
+					solid = true;
+			}
+			else
+				solid = false;
+		}
 		else
 			solid = false;
 
+		if (cutflag == FF_CUTSOLIDS) // These are regular walls sent in from StoreWallRange, they shouldn't be cut from this
+			solid = false;
+
+		if (cutflag & FF_SOLID) // these weren't being cut before anyway, although they probably should be in the right conditions
+			solid = false;
+
+
 		height = FIXED_TO_FLOAT(list[i].height);
 		if (solid)
 			bheight = FIXED_TO_FLOAT(*list[i].caster->bottomheight);
@@ -983,6 +1128,9 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 			continue;
 		}
 
+		FUINT lightnum;
+		extracolormap_t *colormap;
+
 		//Found a break;
 		bot = height;
 
@@ -990,8 +1138,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 			bot = realbot;
 
 		{
-			FUINT lightnum;
-			sector_t *psector;
+
 
 #ifndef HARDWAREFIX
 			lightnum = LightLevelToLum(*list[i-1].lightlevel);
@@ -1001,15 +1148,19 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 #endif
 
 			// colormap test
-			psector =  list[i-1].caster ? &sectors[list[i-1].caster->secnum] : gr_frontsector;
 #ifdef HARDWAREFIX
-			lightnum = LightLevelToLum(psector->lightlevel);
+			if (list[i-1].caster)
+			{
+				lightnum = *list[i-1].lightlevel;
+				colormap = list[i-1].extra_colormap;
+			}
+			else
+			{
+				lightnum = sector->lightlevel;
+				colormap = sector->extra_colormap;
+			}
 #endif
-			if (psector->extra_colormap)
 #ifdef HARDWAREFIX
-				Surf->FlatColor.rgba = HWR_Lighting(lightnum,psector->extra_colormap->rgba);
-			else
-				Surf->FlatColor.rgba = HWR_Lighting(lightnum,NORMALFOG);
 			Surf->FlatColor.s.alpha = alpha;
 #else
 			{
@@ -1039,11 +1190,11 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 
 		glTex = HWR_GetTexture(texnum);
 		if (cutflag & FF_TRANSLUCENT)
-			HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent);
+			HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap);
 		else if (glTex->mipmap.flags & TF_TRANSPARENT)
-			HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Environment);
+			HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Environment, false, lightnum, colormap);
 		else
-			HWR_ProjectWall(wallVerts, Surf, PF_Masked);
+			HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap);
 
 		if (solid)
 			top = bheight;
@@ -1051,14 +1202,14 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 			top = height;
 	}
 
+	FUINT lightnum;
+	extracolormap_t *colormap;
+
 	bot = realbot;
 	if (top <= realbot)
 		return;
 
 	{
-		FUINT   lightnum;
-		sector_t    *psector;
-
 #ifndef HARDWAREFIX
 		lightnum = LightLevelToLum(*list[i-1].lightlevel);
 		// store Surface->FlatColor to modulate wall texture
@@ -1066,15 +1217,19 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 			= (UINT8)lightnum;
 #endif
 
-		psector =  list[i-1].caster ? &sectors[list[i-1].caster->secnum] : gr_frontsector;
 #ifdef HARDWAREFIX
-		lightnum = LightLevelToLum(psector->lightlevel);
+		if (list[i-1].caster)
+		{
+			lightnum = *list[i-1].lightlevel;
+			colormap = list[i-1].extra_colormap;
+		}
+		else
+		{
+			lightnum = sector->lightlevel;
+			colormap = sector->extra_colormap;
+		}
 #endif
-		if (psector->extra_colormap)
 #ifdef HARDWAREFIX
-			Surf->FlatColor.rgba = HWR_Lighting(lightnum,psector->extra_colormap->rgba);
-		else
-			Surf->FlatColor.rgba = HWR_Lighting(lightnum,NORMALFOG);
 		Surf->FlatColor.s.alpha = alpha;
 #else
 		{
@@ -1100,11 +1255,168 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 
 	glTex = HWR_GetTexture(texnum);
 	if (cutflag & FF_TRANSLUCENT)
-		HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent);
+		HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap);
 	else if (glTex->mipmap.flags & TF_TRANSPARENT)
-		HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Environment);
+		HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Environment, false, lightnum, colormap);
 	else
-		HWR_ProjectWall(wallVerts, Surf, PF_Masked);
+		HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap);
+}
+
+
+//
+// HWR_SplitFog
+// Exclusively for fog
+//
+static void HWR_SplitFog(sector_t *sector, wallVert3D *wallVerts, FSurfaceInfo* Surf, INT32 cutflag, FUINT lightnum, extracolormap_t *colormap)
+{
+	/* SoM: split up and light walls according to the
+	 lightlist. This may also include leaving out parts
+	 of the wall that can't be seen */
+	float realtop, realbot, top, bot;
+	float pegt, pegb, pegmul;
+	float height = 0.0f, bheight = 0.0f;
+	INT32   solid, i;
+	lightlist_t *  list = sector->lightlist;
+#ifdef HARDWAREFIX
+	const UINT8 alpha = Surf->FlatColor.s.alpha;
+#endif
+
+	realtop = top = wallVerts[2].y;
+	realbot = bot = wallVerts[0].y;
+	pegt = wallVerts[2].t;
+	pegb = wallVerts[0].t;
+	pegmul = (pegb - pegt) / (top - bot);
+
+	for (i = 1; i < sector->numlights; i++)
+	{
+		if (top < realbot)
+			return;
+
+	//Hurdler: fix a crashing bug, but is it correct?
+//		if (!list[i].caster)
+//			continue;
+
+		solid = false;
+
+		if (list[i].caster)
+		{
+			if (sector->lightlist[i].caster->flags & FF_SOLID && !(cutflag & FF_EXTRA))
+				solid = true;
+			else if (sector->lightlist[i].caster->flags & FF_CUTEXTRA && cutflag & FF_EXTRA)
+			{
+				if (sector->lightlist[i].caster->flags & FF_EXTRA)
+				{
+					if (sector->lightlist[i].caster->flags == cutflag)
+						solid = true;
+				}
+				else
+					solid = true;
+			}
+			else
+				solid = false;
+		}
+		else
+			solid = false;
+
+		height = FIXED_TO_FLOAT(list[i].height);
+
+		if (solid)
+			bheight = FIXED_TO_FLOAT(*list[i].caster->bottomheight);
+
+		if (height >= top)
+		{
+			if (solid && top > bheight)
+				top = bheight;
+			continue;
+		}
+
+		//Found a break;
+		bot = height;
+
+		if (bot < realbot)
+			bot = realbot;
+
+		{
+
+
+#ifndef HARDWAREFIX
+			lightnum = LightLevelToLum(*list[i-1].lightlevel);
+			// store Surface->FlatColor to modulate wall texture
+			Surf->FlatColor.s.red = Surf->FlatColor.s.green = Surf->FlatColor.s.blue =
+				(UINT8)lightnum;
+#endif
+
+#ifdef HARDWAREFIX
+			Surf->FlatColor.s.alpha = alpha;
+#else
+			{
+				RGBA_t temp;
+				INT32 alpha;
+
+				temp.rgba = psector->extra_colormap->rgba;
+				alpha = (INT32)((26 - temp.s.alpha)*lightnum);
+
+				Surf->FlatColor.s.red =
+					(UINT8)((alpha + temp.s.alpha*temp.s.red)/26);
+				Surf->FlatColor.s.blue =
+					(UINT8)((alpha + temp.s.alpha*temp.s.blue)/26);
+				Surf->FlatColor.s.green =
+					(UINT8)((alpha + temp.s.alpha*temp.s.green)/26);
+				Surf->FlatColor.s.alpha = 0xff;
+			}
+#endif
+		}
+
+		wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul);
+		wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul);
+
+		// set top/bottom coords
+		wallVerts[2].y = wallVerts[3].y = top;
+		wallVerts[0].y = wallVerts[1].y = bot;
+
+		if (!solid) // Don't draw it if there's more fog behind it
+			HWR_AddTransparentWall(wallVerts, Surf, 0, PF_Translucent|PF_NoTexture, true, lightnum, colormap);
+
+		top = height;
+	}
+
+	bot = realbot;
+	if (top <= realbot)
+		return;
+
+	{
+#ifndef HARDWAREFIX
+		lightnum = LightLevelToLum(*list[i-1].lightlevel);
+		// store Surface->FlatColor to modulate wall texture
+		Surf->FlatColor.s.red = Surf->FlatColor.s.green = Surf->FlatColor.s.blue
+			= (UINT8)lightnum;
+#endif
+
+#ifdef HARDWAREFIX
+		Surf->FlatColor.s.alpha = alpha;
+#else
+		{
+			RGBA_t  temp;
+			INT32     alpha;
+
+			temp.rgba = psector->extra_colormap->rgba;
+			alpha = (INT32)((26 - temp.s.alpha)*lightnum);
+			Surf->FlatColor.s.red = (UINT8)((alpha + temp.s.alpha*temp.s.red)/26);
+			Surf->FlatColor.s.blue = (UINT8)((alpha + temp.s.alpha*temp.s.blue)/26);
+			Surf->FlatColor.s.green = (UINT8)((alpha + temp.s.alpha*temp.s.green)/26);
+			Surf->FlatColor.s.alpha = 0xFF;
+		}
+#endif
+	}
+
+	wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul);
+	wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul);
+
+	// set top/bottom coords
+	wallVerts[2].y = wallVerts[3].y = top;
+	wallVerts[0].y = wallVerts[1].y = bot;
+
+	HWR_AddTransparentWall(wallVerts, Surf, 0, PF_Translucent|PF_NoTexture, true, lightnum, colormap);
 }
 
 
@@ -1129,6 +1441,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 	fixed_t h, l; // 3D sides and 2s middle textures
 
 	FUINT lightnum = 0; // shut up compiler
+	extracolormap_t *colormap;
 	FSurfaceInfo Surf;
 
 	if (startfrac > endfrac)
@@ -1184,7 +1497,8 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 	}
 
 #ifdef HARDWAREFIX
-	lightnum = LightLevelToLum(gr_frontsector->lightlevel);
+	lightnum = gr_frontsector->lightlevel;
+	colormap = gr_frontsector->extra_colormap;
 #else
 	//  use different light tables
 	//  for horizontal / vertical / diagonal
@@ -1211,20 +1525,8 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 
 	if (gr_frontsector)
 	{
-		sector_t *sector = gr_frontsector;
-
-		// colormap test
-		if (sector->ffloors)
-		{
-			ffloor_t *caster = sector->lightlist[R_GetPlaneLight(sector, sector->floorheight, false)].caster;
-			sector = caster ? &sectors[caster->secnum] : sector;
-		}
-		if (sector->extra_colormap)
-#ifdef HARDWAREFIX
-			Surf.FlatColor.rgba = HWR_Lighting(lightnum,sector->extra_colormap->rgba);
-		else
-			Surf.FlatColor.rgba = HWR_Lighting(lightnum,NORMALFOG);
-#else
+		Surf.FlatColor.s.alpha = 255;
+#ifndef HARDWAREFIX
 		{
 			RGBA_t temp;
 			INT32 alpha;
@@ -1241,10 +1543,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 		}
 #endif
 	}
-#ifdef HARDWAREFIX
-	else
-		Surf.FlatColor.rgba = HWR_Lighting(lightnum,NORMALFOG);
-#endif
 
 	if (gr_backsector)
 	{
@@ -1261,6 +1559,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 		}
 
 		// hack to allow height changes in outdoor areas
+		// This is what gets rid of the upper textures if there should be sky
 		if (gr_frontsector->ceilingpic == skyflatnum &&
 			gr_backsector->ceilingpic  == skyflatnum)
 		{
@@ -1301,9 +1600,9 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			if (gr_frontsector->numlights)
 				HWR_SplitWall(gr_frontsector, wallVerts, texturetranslation[gr_sidedef->toptexture], &Surf, FF_CUTSOLIDS);
 			else if (grTex->mipmap.flags & TF_TRANSPARENT)
-				HWR_AddTransparentWall(wallVerts, &Surf, texturetranslation[gr_sidedef->toptexture], PF_Environment);
+				HWR_AddTransparentWall(wallVerts, &Surf, texturetranslation[gr_sidedef->toptexture], PF_Environment, false, lightnum, colormap);
 			else
-				HWR_ProjectWall(wallVerts, &Surf, PF_Masked);
+				HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
 		}
 
 		// check BOTTOM TEXTURE
@@ -1340,42 +1639,49 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			if (gr_frontsector->numlights)
 				HWR_SplitWall(gr_frontsector, wallVerts, texturetranslation[gr_sidedef->bottomtexture], &Surf, FF_CUTSOLIDS);
 			else if (grTex->mipmap.flags & TF_TRANSPARENT)
-				HWR_AddTransparentWall(wallVerts, &Surf, texturetranslation[gr_sidedef->bottomtexture], PF_Environment);
+				HWR_AddTransparentWall(wallVerts, &Surf, texturetranslation[gr_sidedef->bottomtexture], PF_Environment, false, lightnum, colormap);
 			else
-				HWR_ProjectWall(wallVerts, &Surf, PF_Masked);
+				HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
 		}
 		gr_midtexture = texturetranslation[gr_sidedef->midtexture];
 		if (gr_midtexture)
 		{
 			FBITFIELD blendmode;
-			fixed_t  popentop, popenbottom, polytop, polybottom;
-			fixed_t fvisiblefloor, fvisibleceiling, bvisiblefloor, bvisibleceiling;
-			boolean heightsecd = false;
+			sector_t *front, *back;
+			fixed_t  popentop, popenbottom, polytop, polybottom, lowcut, highcut;
 			fixed_t     texturevpeg = 0;
+			INT32 repeats;
 
-			if (gr_frontsector->heightsec != -1)
-			{
-				fvisiblefloor = sectors[gr_frontsector->heightsec].floorheight;
-				fvisibleceiling = sectors[gr_frontsector->heightsec].ceilingheight;
-				heightsecd = true;
-			}
+			if (gr_linedef->frontsector->heightsec != -1)
+				front = &sectors[gr_linedef->frontsector->heightsec];
 			else
-			{
-				fvisiblefloor = gr_frontsector->floorheight;
-				fvisibleceiling = gr_frontsector->ceilingheight;
-			}
+				front = gr_linedef->frontsector;
 
-			if (gr_backsector->heightsec != -1)
-			{
-				bvisiblefloor = sectors[gr_backsector->heightsec].floorheight;
-				bvisibleceiling = sectors[gr_backsector->heightsec].ceilingheight;
-				heightsecd = true;
-			}
+			if (gr_linedef->backsector->heightsec != -1)
+				back = &sectors[gr_linedef->backsector->heightsec];
 			else
+				back = gr_linedef->backsector;
+
+			if (gr_sidedef->repeatcnt)
+				repeats = 1 + gr_sidedef->repeatcnt;
+			else if (gr_linedef->flags & ML_EFFECT5)
 			{
-				bvisiblefloor = gr_backsector->floorheight;
-				bvisibleceiling = gr_backsector->ceilingheight;
+				fixed_t high, low;
+
+				if (front->ceilingheight > back->ceilingheight)
+					high = back->ceilingheight;
+				else
+					high = front->ceilingheight;
+
+				if (front->floorheight > back->floorheight)
+					low = front->floorheight;
+				else
+					low = back->floorheight;
+
+				repeats = (high - low)/textureheight[gr_sidedef->midtexture];
 			}
+			else
+				repeats = 1;
 
 			// SoM: a little note: This code re-arranging will
 			// fix the bug in Nimrod map02. popentop and popenbottom
@@ -1384,36 +1690,58 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			// heights of the polygon, and h & l, are the final (clipped)
 			// poly coords.
 
-			popentop = worldtop < worldhigh ? worldtop : worldhigh;
-			popenbottom = worldbottom > worldlow ? worldbottom : worldlow;
+#ifdef POLYOBJECTS
+			// NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to,
+			// you must use the linedef's backsector to be correct
+			// From CB
+			if (gr_curline->polyseg)
+			{
+				popentop = back->ceilingheight;
+				popenbottom = back->floorheight;
+			}
+#endif
+			else
+			{
+				popentop = front->ceilingheight < back->ceilingheight ? front->ceilingheight : back->ceilingheight;
+				popenbottom = front->floorheight > back->floorheight ? front->floorheight : back->floorheight;
+			}
 
 			if (gr_linedef->flags & ML_DONTPEGBOTTOM)
 			{
 				polybottom = popenbottom + gr_sidedef->rowoffset;
-				polytop = polybottom + textureheight[gr_midtexture];
+				polytop = polybottom + textureheight[gr_midtexture]*repeats;
 			}
 			else
 			{
 				polytop = popentop + gr_sidedef->rowoffset;
-				polybottom = polytop - textureheight[gr_midtexture];
+				polybottom = polytop - textureheight[gr_midtexture]*repeats;
 			}
-			if ((fvisibleceiling == bvisibleceiling)
-			    /*|| (gr_linedef->flags & ML_DONTDRAW)*/)
-				h = polytop;
-			else
-				h = polytop < popentop ? polytop : popentop;
 
-			if ((fvisiblefloor == bvisiblefloor)
-			    /*|| (gr_linedef->flags & ML_DONTDRAW)*/)
-				l = polybottom;
+			// CB
+#ifdef POLYOBJECTS
+			// NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to,
+			// you must use the linedef's backsector to be correct
+			if (gr_curline->polyseg)
+			{
+				lowcut = polybottom;
+				highcut = polytop;
+			}
+#endif
 			else
-				l = polybottom > popenbottom ? polybottom : popenbottom;
+			{
+				// The cut-off values of a linedef can always be constant, since every line has an absoulute front and or back sector
+				lowcut = front->floorheight > back->floorheight ? front->floorheight : back->floorheight;
+				highcut = front->ceilingheight < back->ceilingheight ? front->ceilingheight : back->ceilingheight;
+			}
+
+			h = polytop > highcut ? highcut : polytop;
+			l = polybottom < lowcut ? lowcut : polybottom;
 
 			if (drawtextured)
 			{
 				// PEGGING
 				if (gr_linedef->flags & ML_DONTPEGBOTTOM)
-					texturevpeg = textureheight[gr_sidedef->midtexture] - h + polybottom;
+					texturevpeg = textureheight[gr_sidedef->midtexture]*repeats - h + polybottom;
 				else
 					texturevpeg = polytop - h;
 
@@ -1428,8 +1756,8 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			// set top/bottom coords
 			// Take the texture peg into account, rather than changing the offsets past
 			// where the polygon might not be.
-			wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h - texturevpeg);
-			wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l - texturevpeg);
+			wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h);
+			wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l);
 
 			// set alpha for transparent walls (new boom and legacy linedef types)
 			// ooops ! this do not work at all because render order we should render it in backtofront order
@@ -1486,14 +1814,12 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			if (grTex->mipmap.flags & TF_TRANSPARENT)
 				blendmode = PF_Environment;
 
-			blendmode |= PF_RemoveYWrap;
-
 			if (gr_frontsector->numlights)
 				HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTSOLIDS);
 			else if (!(blendmode & PF_Masked))
-				HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, blendmode);
+				HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, blendmode, false, lightnum, colormap);
 			else
-				HWR_ProjectWall(wallVerts, &Surf, blendmode);
+				HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap);
 
 			// If there is a colormap change, remove it.
 /*			if (!(Surf.FlatColor.s.red + Surf.FlatColor.s.green + Surf.FlatColor.s.blue == Surf.FlatColor.s.red/3)
@@ -1536,9 +1862,9 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			else
 			{
 				if (grTex->mipmap.flags & TF_TRANSPARENT)
-					HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, PF_Environment);
+					HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, PF_Environment, false, lightnum, colormap);
 				else
-					HWR_ProjectWall(wallVerts, &Surf, PF_Masked);
+					HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
 			}
 		}
 	}
@@ -1549,6 +1875,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 	if (gr_frontsector && gr_backsector && gr_frontsector->tag != gr_backsector->tag && (gr_backsector->ffloors || gr_frontsector->ffloors))
 	{
 		ffloor_t * rover;
+		ffloor_t * r2;
 		fixed_t    highcut = 0, lowcut = 0;
 
 		highcut = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight;
@@ -1563,7 +1890,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
 					continue;
 
-
 				h = *rover->topheight;
 				l = *rover->bottomheight;
 				if (h > highcut)
@@ -1576,7 +1902,14 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h);
 				wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l);
 
-				if (drawtextured)
+				if (rover->flags & FF_FOG)
+				{
+					wallVerts[3].t = wallVerts[2].t = 0;
+					wallVerts[0].t = wallVerts[1].t = 0;
+					wallVerts[0].s = wallVerts[3].s = 0;
+					wallVerts[2].s = wallVerts[1].s = 0;
+				}
+				else if (drawtextured)
 				{
 					grTex = HWR_GetTexture(texturetranslation[sides[rover->master->sidenum[0]].midtexture]);
 
@@ -1585,14 +1918,39 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 					wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
 					wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
 				}
-				if (!(rover->flags & FF_FOG))
+
+				if (rover->flags & FF_FOG)
+				{
+					FBITFIELD blendmode;
+
+					blendmode = PF_Translucent|PF_NoTexture;
+
+					lightnum = rover->master->frontsector->lightlevel;
+					colormap = rover->master->frontsector->extra_colormap;
+
+					if (rover->master->frontsector->extra_colormap)
+					{
+
+						Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,rover->master->frontsector->extra_colormap->rgba,rover->master->frontsector->extra_colormap->fadergba);
+					}
+					else
+					{
+						Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG,FADEFOG);
+					}
+
+					if (gr_frontsector->numlights)
+						HWR_SplitFog(gr_frontsector, wallVerts, &Surf, rover->flags, lightnum, colormap);
+					else
+						HWR_AddTransparentWall(wallVerts, &Surf, 0, blendmode, true, lightnum, colormap);
+				}
+				else
 				{
 					FBITFIELD blendmode = PF_Masked;
 
 					if (rover->flags & FF_TRANSLUCENT)
 					{
 						blendmode = PF_Translucent;
-						Surf.FlatColor.s.alpha = (UINT8)rover->alpha;
+						Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1;
 					}
 					else if (grTex->mipmap.flags & TF_TRANSPARENT)
 					{
@@ -1600,18 +1958,19 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 					}
 
 					if (gr_frontsector->numlights)
-						HWR_SplitWall(gr_frontsector, wallVerts, texturetranslation[sides[rover->master->sidenum[0]].midtexture], &Surf, (rover->flags & FF_EXTRA ? FF_CUTEXTRA : FF_CUTSOLIDS)|(rover->flags & FF_TRANSLUCENT ? FF_TRANSLUCENT : 0));
+						HWR_SplitWall(gr_frontsector, wallVerts, texturetranslation[sides[rover->master->sidenum[0]].midtexture], &Surf, rover->flags);
 					else
 					{
 						if (blendmode != PF_Masked)
-							HWR_AddTransparentWall(wallVerts, &Surf, texturetranslation[sides[rover->master->sidenum[0]].midtexture], blendmode);
+							HWR_AddTransparentWall(wallVerts, &Surf, texturetranslation[sides[rover->master->sidenum[0]].midtexture], blendmode, false, lightnum, colormap);
 						else
-							HWR_ProjectWall(wallVerts, &Surf, PF_Masked);
+							HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
 					}
 				}
 			}
 		}
-		else if (gr_frontsector->ffloors)
+
+		if (gr_frontsector->ffloors) // Putting this seperate should allow 2 FOF sectors to be connected without too many errors? I think?
 		{
 			for (rover = gr_frontsector->ffloors; rover; rover = rover->next)
 			{
@@ -1632,7 +1991,14 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h);
 				wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l);
 
-				if (drawtextured)
+				if (rover->flags & FF_FOG)
+				{
+					wallVerts[3].t = wallVerts[2].t = 0;
+					wallVerts[0].t = wallVerts[1].t = 0;
+					wallVerts[0].s = wallVerts[3].s = 0;
+					wallVerts[2].s = wallVerts[1].s = 0;
+				}
+				else if (drawtextured)
 				{
 					grTex = HWR_GetTexture(texturetranslation[sides[rover->master->sidenum[0]].midtexture]);
 
@@ -1641,14 +2007,38 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 					wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
 					wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
 				}
-				if (!(rover->flags & FF_FOG))
+
+				if (rover->flags & FF_FOG)
+				{
+					FBITFIELD blendmode;
+
+					blendmode = PF_Translucent|PF_NoTexture;
+
+					lightnum = rover->master->frontsector->lightlevel;
+					colormap = rover->master->frontsector->extra_colormap;
+
+					if (rover->master->frontsector->extra_colormap)
+					{
+						Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,rover->master->frontsector->extra_colormap->rgba,rover->master->frontsector->extra_colormap->fadergba);
+					}
+					else
+					{
+						Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG,FADEFOG);
+					}
+
+					if (gr_backsector->numlights)
+						HWR_SplitFog(gr_backsector, wallVerts, &Surf, rover->flags, lightnum, colormap);
+					else
+						HWR_AddTransparentWall(wallVerts, &Surf, 0, blendmode, true, lightnum, colormap);
+				}
+				else
 				{
 					FBITFIELD blendmode = PF_Masked;
 
 					if (rover->flags & FF_TRANSLUCENT)
 					{
 						blendmode = PF_Translucent;
-						Surf.FlatColor.s.alpha = (UINT8)rover->alpha;
+						Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1;
 					}
 					else if (grTex->mipmap.flags & TF_TRANSPARENT)
 					{
@@ -1656,13 +2046,13 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 					}
 
 					if (gr_backsector->numlights)
-						HWR_SplitWall(gr_backsector, wallVerts, texturetranslation[sides[rover->master->sidenum[0]].midtexture], &Surf, (rover->flags & FF_EXTRA ? FF_CUTEXTRA : FF_CUTSOLIDS)|(rover->flags & FF_TRANSLUCENT ? FF_TRANSLUCENT : 0));
+						HWR_SplitWall(gr_backsector, wallVerts, texturetranslation[sides[rover->master->sidenum[0]].midtexture], &Surf, rover->flags);
 					else
 					{
 						if (blendmode != PF_Masked)
-							HWR_AddTransparentWall(wallVerts, &Surf, texturetranslation[sides[rover->master->sidenum[0]].midtexture], blendmode);
+							HWR_AddTransparentWall(wallVerts, &Surf, texturetranslation[sides[rover->master->sidenum[0]].midtexture], blendmode, false, lightnum, colormap);
 						else
-							HWR_ProjectWall(wallVerts, &Surf, PF_Masked);
+							HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
 					}
 				}
 			}
@@ -2256,8 +2646,10 @@ static void HWR_Subsector(size_t num)
 	INT32 floorlightlevel;
 	INT32 ceilinglightlevel;
 	INT32 locFloorHeight, locCeilingHeight;
-	INT32 light;
+	INT32 light = 0;
 	fixed_t wh;
+	extracolormap_t *floorcolormap;
+	extracolormap_t *ceilingcolormap;
 
 #ifdef PARANOIA //no risk while developing, enough debugging nights!
 	if (num >= addsubsector)
@@ -2296,6 +2688,8 @@ static void HWR_Subsector(size_t num)
 								&ceilinglightlevel, false);
 	//FIXME: Use floorlightlevel and ceilinglightlevel insted of lightlevel.
 
+	floorcolormap = ceilingcolormap = gr_frontsector->extra_colormap;
+
 	// ------------------------------------------------------------------------
 	// sector lighting, DISABLED because it's done in HWR_StoreWallRange
 	// ------------------------------------------------------------------------
@@ -2343,10 +2737,19 @@ static void HWR_Subsector(size_t num)
 			sub->sector->moved = gr_frontsector->moved = false;
 		}
 
-		floorlightlevel = *gr_frontsector->lightlist[R_GetPlaneLight(gr_frontsector, locFloorHeight, false)].lightlevel;
-		ceilinglightlevel = *gr_frontsector->lightlist[R_GetPlaneLight(gr_frontsector, locCeilingHeight, false)].lightlevel;
+		light = R_GetPlaneLight(gr_frontsector, locFloorHeight, false);
+		if (gr_frontsector->floorlightsec == -1)
+			floorlightlevel = *gr_frontsector->lightlist[light].lightlevel;
+		floorcolormap = gr_frontsector->lightlist[light].extra_colormap;
+
+		light = R_GetPlaneLight(gr_frontsector, locCeilingHeight, false);
+		if (gr_frontsector->ceilinglightsec == -1)
+			ceilinglightlevel = *gr_frontsector->lightlist[light].lightlevel;
+		ceilingcolormap = gr_frontsector->lightlist[light].extra_colormap;
 	}
 
+	sub->sector->extra_colormap = gr_frontsector->extra_colormap;
+
 	// render floor ?
 #ifdef DOPLANES
 	// yeah, easy backface cull! :)
@@ -2357,7 +2760,7 @@ static void HWR_Subsector(size_t num)
 			if (sub->validcount != validcount)
 			{
 				HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum);
-				HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], locFloorHeight, PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL);
+				HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], locFloorHeight, PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, false, floorcolormap);
 			}
 		}
 		else
@@ -2365,7 +2768,6 @@ static void HWR_Subsector(size_t num)
 #ifdef POLYSKY
 			HWR_RenderSkyPlane(&extrasubsectors[num], locFloorHeight);
 #endif
-			drawsky = true;
 		}
 	}
 
@@ -2376,7 +2778,7 @@ static void HWR_Subsector(size_t num)
 			if (sub->validcount != validcount)
 			{
 				HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum);
-				HWR_RenderPlane(NULL, &extrasubsectors[num], locCeilingHeight, PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL);
+				HWR_RenderPlane(NULL, &extrasubsectors[num], locCeilingHeight, PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, false, ceilingcolormap);
 			}
 		}
 		else
@@ -2384,10 +2786,17 @@ static void HWR_Subsector(size_t num)
 #ifdef POLYSKY
 			HWR_RenderSkyPlane(&extrasubsectors[num], locCeilingHeight);
 #endif
-			drawsky = true;
 		}
 	}
 
+#ifndef POLYSKY
+	// Moved here because before, when above the ceiling and the floor does not have the sky flat, it doesn't draw the sky
+	if (gr_frontsector->ceilingpic == skyflatnum || gr_frontsector->floorpic == skyflatnum)
+	{
+		drawsky = true;
+	}
+#endif
+
 #ifdef R_FAKEFLOORS
 	if (gr_frontsector->ffloors)
 	{
@@ -2407,9 +2816,27 @@ static void HWR_Subsector(size_t num)
 			if (*rover->bottomheight <= gr_frontsector->ceilingheight &&
 			    *rover->bottomheight >= gr_frontsector->floorheight &&
 			    ((dup_viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) ||
-			     (dup_viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES))))
+			     (dup_viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
 			{
-				if (rover->flags & (FF_TRANSLUCENT|FF_FOG)) // SoM: Flags are more efficient
+				if (rover->flags & FF_FOG)
+				{
+					UINT8 alpha;
+
+					light = R_GetPlaneLight(gr_frontsector, *rover->bottomheight, dup_viewz < *rover->bottomheight ? true : false);
+
+					if (rover->master->frontsector->extra_colormap)
+						alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba, rover->master->frontsector->extra_colormap->fadergba);
+					else
+						alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG, FADEFOG);
+
+					HWR_AddTransparentFloor(0,
+					                       &extrasubsectors[num],
+					                       *rover->bottomheight,
+					                       *gr_frontsector->lightlist[light].lightlevel,
+					                       alpha, rover->master->frontsector, PF_Translucent|PF_NoTexture,
+										   true, rover->master->frontsector->extra_colormap);
+				}
+				else if (rover->flags & FF_TRANSLUCENT) // SoM: Flags are more efficient
 				{
 					light = R_GetPlaneLight(gr_frontsector, *rover->bottomheight, dup_viewz < *rover->bottomheight ? true : false);
 #ifndef SORTING
@@ -2423,7 +2850,8 @@ static void HWR_Subsector(size_t num)
 					                       &extrasubsectors[num],
 					                       *rover->bottomheight,
 					                       *gr_frontsector->lightlist[light].lightlevel,
-					                       rover->alpha, rover->master->frontsector);
+					                       rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent,
+										   false, gr_frontsector->lightlist[light].extra_colormap);
 #endif
 				}
 				else
@@ -2431,15 +2859,33 @@ static void HWR_Subsector(size_t num)
 					HWR_GetFlat(levelflats[*rover->bottompic].lumpnum);
 					light = R_GetPlaneLight(gr_frontsector, *rover->bottomheight, dup_viewz < *rover->bottomheight ? true : false);
 					HWR_RenderPlane(NULL, &extrasubsectors[num], *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum,
-					                rover->master->frontsector);
+					                rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap);
 				}
 			}
 			if (*rover->topheight >= gr_frontsector->floorheight &&
 			    *rover->topheight <= gr_frontsector->ceilingheight &&
 			    ((dup_viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) ||
-			     (dup_viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES))))
+			     (dup_viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
 			{
-				if (rover->flags & (FF_TRANSLUCENT|FF_FOG))
+				if (rover->flags & FF_FOG)
+				{
+					byte alpha;
+
+					light = R_GetPlaneLight(gr_frontsector, *rover->topheight, dup_viewz < *rover->topheight ? true : false);
+
+					if (rover->master->frontsector->extra_colormap)
+						alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba, rover->master->frontsector->extra_colormap->fadergba);
+					else
+						alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG, FADEFOG);
+
+					HWR_AddTransparentFloor(0,
+					                       &extrasubsectors[num],
+					                       *rover->topheight,
+					                       *gr_frontsector->lightlist[light].lightlevel,
+					                       alpha, rover->master->frontsector, PF_Translucent|PF_NoTexture,
+										   true, rover->master->frontsector->extra_colormap);
+				}
+				else if (rover->flags & FF_TRANSLUCENT)
 				{
 					light = R_GetPlaneLight(gr_frontsector, *rover->topheight, dup_viewz < *rover->topheight ? true : false);
 #ifndef SORTING
@@ -2453,7 +2899,8 @@ static void HWR_Subsector(size_t num)
 					                        &extrasubsectors[num],
 					                        *rover->topheight,
 					                        *gr_frontsector->lightlist[light].lightlevel,
-					                        rover->alpha, rover->master->frontsector);
+					                        rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent,
+											false, gr_frontsector->lightlist[light].extra_colormap);
 #endif
 
 				}
@@ -2462,7 +2909,7 @@ static void HWR_Subsector(size_t num)
 					HWR_GetFlat(levelflats[*rover->toppic].lumpnum);
 					light = R_GetPlaneLight(gr_frontsector, *rover->topheight, dup_viewz < *rover->topheight ? true : false);
 					HWR_RenderPlane(NULL, &extrasubsectors[num], *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum,
-					                  rover->master->frontsector);
+					                  rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap);
 				}
 			}
 		}
@@ -2535,7 +2982,7 @@ static void HWR_Subsector(size_t num)
 			HWR_RenderPlane(gr_frontsector,
 				&extrasubsectors[num], wh, PF_Translucent,
 				gr_frontsector->lightlevel, doomwaterflat,
-				NULL);
+				NULL, 255, false, gr_frontsector->lightlist[light].extra_colormap);
 		}
 	}
 	// -------------------- WATER IN DEV. TEST ------------------------
@@ -2920,41 +3367,6 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
 	//Hurdler: 25/04/2000: now support colormap in hardware mode
 	HWR_GetMappedPatch(gpatch, spr->colormap);
 
-	// sprite lighting by modulating the RGB components
-	/// \todo coloured
-#ifndef HARDWAREFIX
-	Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = spr->sectorlight;
-#endif
-
-	// colormap test
-	{
-		sector_t *sector = spr->mobj->subsector->sector;
-
-		if (sector->ffloors)
-		{
-			ffloor_t *caster = sector->lightlist[R_GetPlaneLight(sector, spr->mobj->z, false)].caster;
-			sector = caster ? &sectors[caster->secnum] : sector;
-		}
-		if (sector->extra_colormap)
-#ifdef HARDWAREFIX
-			Surf.FlatColor.rgba = HWR_Lighting(LightLevelToLum(sector->lightlevel),sector->extra_colormap->rgba);
-		else
-			Surf.FlatColor.rgba = HWR_Lighting(LightLevelToLum(sector->lightlevel),NORMALFOG);
-#else
-		{
-			RGBA_t temp;
-			INT32 alpha;
-
-			temp.rgba = sector->extra_colormap->rgba;
-			alpha = (26 - temp.s.alpha)*spr->sectorlight;
-			Surf.FlatColor.s.red = (UINT8)((alpha + temp.s.alpha*temp.s.red)/26);
-			Surf.FlatColor.s.blue = (UINT8)((alpha + temp.s.alpha*temp.s.blue)/26);
-			Surf.FlatColor.s.green = (UINT8)((alpha + temp.s.alpha*temp.s.green)/26);
-			Surf.FlatColor.s.alpha = 0xff;
-		}
-#endif
-	}
-
 	// Draw shadow BEFORE SPRITE.
 	if (cv_shadow.value // Shadows enabled
 		&& !(spr->mobj->flags & MF_SCENERY && spr->mobj->flags & MF_SPAWNCEILING && spr->mobj->flags & MF_NOGRAVITY) // Ceiling scenery have no shadow.
@@ -3042,6 +3454,25 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
 			swallVerts[2].z = swallVerts[3].z = spr->tz + gpatch->height - (gpatch->height-gpatch->topoffset);
 		}
 
+		// Huh setting the Y higher? Also moving this before to stop the alterations affecting it after scaling.
+		if (spr->mobj && spr->mobj->scale != 100)
+		{
+			const float radius = (spr->x2-spr->x1)/2;
+			const float scale = (float)(100-spr->mobj->scale);
+			if(spr->mobj->flags & MF_HIRES)
+			{
+				swallVerts[0].x = swallVerts[3].x += FLOATSCALE(radius,scale)/2;
+				swallVerts[2].x = swallVerts[1].x -= FLOATSCALE(radius,scale)/2;
+				swallVerts[2].z = swallVerts[3].z -= FLOATSCALE(gpatch->height,scale);
+			}
+			else
+			{
+				swallVerts[0].x = swallVerts[3].x += FLOATSCALE(radius,scale);
+				swallVerts[2].x = swallVerts[1].x -= FLOATSCALE(radius,scale);
+				swallVerts[2].z = swallVerts[3].z -= FLOATSCALE(gpatch->height,scale);
+			}
+		}
+
 		// transform
 		wv = swallVerts;
 
@@ -3081,27 +3512,41 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
 		else
 			swallVerts[0].tow = swallVerts[1].tow = gpatch->max_t;
 
-#if 0
-		Surf.FlatColor.s.red = 0x00;
-		Surf.FlatColor.s.blue = 0x00;
-		Surf.FlatColor.s.green = 0x00;
-#endif
+		sSurf.FlatColor.s.red = 0x00;
+		sSurf.FlatColor.s.blue = 0x00;
+		sSurf.FlatColor.s.green = 0x00;
 
 		if (spr->mobj->frame & FF_TRANSMASK || spr->mobj->flags2 & MF2_SHADOW)
 		{
 #ifdef HARDWAREFIX
 			sector_t *sector = spr->mobj->subsector->sector;
+			UINT8 lightlevel = LightLevelToLum(sector->lightlevel);
+			extracolormap_t *colormap = sector->extra_colormap;
+
+			if (sector->numlights)
+			{
+				INT32 light = R_GetPlaneLight(sector, spr->mobj->floorz, false);
+
+				if (!(spr->mobj->frame & FF_FULLBRIGHT))
+					lightlevel = LightLevelToLum(*sector->lightlist[light].lightlevel);
+				else
+					lightlevel = LightLevelToLum(255);
 
-			if (sector->ffloors)
+				if (sector->lightlist[light].extra_colormap)
+					colormap = sector->lightlist[light].extra_colormap;
+			}
+			else
 			{
-				ffloor_t *caster = sector->lightlist[R_GetPlaneLight(sector, spr->mobj->z, false)].caster;
-				sector = caster ? &sectors[caster->secnum] : sector;
+				lightlevel = LightLevelToLum(sector->lightlevel);
+
+				if (sector->extra_colormap)
+					colormap = sector->extra_colormap;
 			}
 
-			if (sector->extra_colormap)
-				Surf.FlatColor.rgba = HWR_Lighting(spr->sectorlight/2,sector->extra_colormap->rgba);
+			if (colormap)
+				sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, colormap->rgba, colormap->fadergba, false, true);
 			else
-				Surf.FlatColor.rgba = HWR_Lighting(spr->sectorlight/2,NORMALFOG);
+				sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, NORMALFOG, FADEFOG, false, true);
 #else
 			// sprite lighting by modulating the RGB components
 			sSurf.FlatColor.s.red = sSurf.FlatColor.s.green = sSurf.FlatColor.s.blue = (UINT8)(spr->sectorlight/2);
@@ -3115,31 +3560,10 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
 #endif
 
 		/// \todo do the test earlier
-		if (!cv_grmd2.value || (md2_models[spr->mobj->sprite].scale < 0.0f))
+		if (!cv_grmd2.value || (md2_models[spr->mobj->sprite].scale < 0.0f) || (md2_models[spr->mobj->sprite].notfound = true) || (md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) || (md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound = true))
 		{
 			if (0x80 > floorheight/4)
 			{
-				if(spr->mobj && spr->mobj->scale != 100)
-				{
-					const float radius = (spr->x2-spr->x1)/2;
-					const float scale = (float)(100-spr->mobj->scale);
-					if(spr->mobj->flags & MF_HIRES)
-					{
-						wallVerts[0].x = wallVerts[3].x += FLOATSCALE(radius,scale)/2;
-						wallVerts[2].x = wallVerts[1].x -= FLOATSCALE(radius,scale)/2;
-						wallVerts[0].y = wallVerts[1].y += FLOATSCALE(abs(gpatch->topoffset-gpatch->height),scale/2);
-						wallVerts[2].y = wallVerts[3].y += FLOATSCALE(abs(gpatch->topoffset-gpatch->height),scale/2);
-						wallVerts[2].y = wallVerts[3].y -= FLOATSCALE(gpatch->height,scale);
-					}
-					else
-					{
-						wallVerts[0].x = wallVerts[3].x += FLOATSCALE(radius,scale);
-						wallVerts[2].x = wallVerts[1].x -= FLOATSCALE(radius,scale);
-						wallVerts[0].y = wallVerts[1].y += FLOATSCALE(abs(gpatch->topoffset-gpatch->height),scale);
-						wallVerts[2].y = wallVerts[3].y += FLOATSCALE(abs(gpatch->topoffset-gpatch->height),scale);
-						wallVerts[2].y = wallVerts[3].y -= FLOATSCALE(gpatch->height,scale);
-					}
-				}
 				sSurf.FlatColor.s.alpha = (UINT8)(0x80 - floorheight/4);
 				HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated|PF_Clip);
 			}
@@ -3148,6 +3572,88 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
 
 noshadow:
 
+	// This needs to be AFTER the shadows so that the regular sprites aren't drawn completely black.
+	// sprite lighting by modulating the RGB components
+	/// \todo coloured
+#ifndef HARDWAREFIX
+	Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = spr->sectorlight;
+#endif
+
+	// colormap test
+	{
+#ifdef HARDWAREFIX
+		sector_t *sector = spr->mobj->subsector->sector;
+		UINT8 lightlevel = LightLevelToLum(sector->lightlevel);
+		extracolormap_t *colormap = sector->extra_colormap;
+
+		if (sector->numlights)
+		{
+			INT32 light = R_GetPlaneLight(sector, spr->mobj->z, false);
+
+			if ((sector->lightlist[light].height > (spr->mobj->z + spr->mobj->height)) && !(sector->lightlist[light].flags & FF_NOSHADE))
+			{
+				if (!(spr->mobj->frame & FF_FULLBRIGHT))
+					lightlevel = LightLevelToLum(*sector->lightlist[light].lightlevel);
+				else
+					lightlevel = LightLevelToLum(255);
+
+				if (sector->lightlist[light].extra_colormap)
+					colormap = sector->lightlist[light].extra_colormap;
+			}
+			else // If we can't use the light at its bottom, we'll use the light at its top
+			{
+				light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false);
+
+				if (!(spr->mobj->frame & FF_FULLBRIGHT))
+					lightlevel = LightLevelToLum(*sector->lightlist[light].lightlevel);
+				else
+					lightlevel = LightLevelToLum(255);
+
+				if (sector->lightlist[light].extra_colormap)
+					colormap = sector->lightlist[light].extra_colormap;
+			}
+		}
+		else
+		{
+			if (!(spr->mobj->frame & FF_FULLBRIGHT))
+				lightlevel = LightLevelToLum(sector->lightlevel);
+			else
+				lightlevel = LightLevelToLum(255);
+
+			if (sector->extra_colormap)
+				colormap = sector->extra_colormap;
+		}
+
+		if (spr->mobj->frame & FF_FULLBRIGHT)
+			lightlevel = LightLevelToLum(255);
+
+		if (colormap)
+			Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false);
+		else
+			Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false);
+#else
+
+		sector_t *sector = spr->mobj->subsector->sector;
+
+		if (sector->ffloors)
+		{
+			ffloor_t *caster = sector->lightlist[R_GetPlaneLight(sector, spr->mobj->z, false)].caster;
+			sector = caster ? &sectors[caster->secnum] : sector;
+		}
+		{
+			RGBA_t temp;
+			INT32 alpha;
+
+			temp.rgba = sector->extra_colormap->rgba;
+			alpha = (26 - temp.s.alpha)*spr->sectorlight;
+			Surf.FlatColor.s.red = (UINT8)((alpha + temp.s.alpha*temp.s.red)/26);
+			Surf.FlatColor.s.blue = (UINT8)((alpha + temp.s.alpha*temp.s.blue)/26);
+			Surf.FlatColor.s.green = (UINT8)((alpha + temp.s.alpha*temp.s.green)/26);
+			Surf.FlatColor.s.alpha = 0xff;
+		}
+#endif
+	}
+
 	/// \todo do the test earlier
 	if (!cv_grmd2.value || (md2_models[spr->mobj->sprite].scale < 0.0f))
 	{
@@ -3185,6 +3691,12 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
 	GLPatch_t *gpatch; // sprite patch converted to hardware
 	FSurfaceInfo Surf;
 
+	if (!spr->mobj)
+		return;
+
+	if (!spr->mobj->subsector)
+		return;
+
 	// cache sprite graphics
 	gpatch = W_CachePatchNum(spr->patchlumpnum, PU_CACHE);
 
@@ -3231,12 +3743,41 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
 	//Hurdler: 25/04/2000: now support colormap in hardware mode
 	HWR_GetMappedPatch(gpatch, spr->colormap);
 
+	sector_t *sector = spr->mobj->subsector->sector;
+
+	if (sector->ffloors)
+	{
+		ffloor_t *caster = sector->lightlist[R_GetPlaneLight(sector, spr->mobj->z, false)].caster;
+		sector = caster ? &sectors[caster->secnum] : sector;
+	}
+
+
 	// sprite lighting by modulating the RGB components
-	Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = spr->sectorlight;
+	if (sector->extra_colormap)
+#ifdef HARDWAREFIX
+			Surf.FlatColor.rgba = HWR_Lighting(spr->sectorlight,sector->extra_colormap->rgba,sector->extra_colormap->fadergba, false, false);
+		else
+			Surf.FlatColor.rgba = HWR_Lighting(spr->sectorlight,NORMALFOG,FADEFOG, false, false);
+#endif
 
-	blend = HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
+	if (spr->mobj->flags2 & MF2_SHADOW)
+	{
+		Surf.FlatColor.s.alpha = 0x40;
+		blend = PF_Translucent;
+	}
+	else if (spr->mobj->frame & FF_TRANSMASK)
+		blend = HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
+	else
+	{
+		// BP: i agree that is little better in environement but it don't
+		//     work properly under glide nor with fogcolor to ffffff :(
+		// Hurdler: PF_Environement would be cool, but we need to fix
+		//          the issue with the fog before
+		Surf.FlatColor.s.alpha = 0xFF;
+		blend = PF_Translucent|PF_Occlude;
+	}
 
-	HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip|PF_Occlude);
+	HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip);
 }
 #endif
 
@@ -3305,12 +3846,15 @@ typedef struct
 #ifndef SORTING
 	fixed_t       fixedheight;
 #endif
+	boolean fogwall;
+	INT32 lightlevel;
+	extracolormap_t *wallcolormap; // Doing the lighting in HWR_RenderWall now for correct fog after sorting
 } wallinfo_t;
 
 static wallinfo_t *wallinfo = NULL;
 static size_t numwalls = 0; // a list of transparent walls to be drawn
 
-static void HWR_RenderWall(wallVert3D   *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend);
+static void HWR_RenderWall(wallVert3D   *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap);
 
 #define MAX_TRANSPARENTWALL 256
 
@@ -3322,6 +3866,9 @@ typedef struct
 	lumpnum_t lumpnum;
 	INT32 alpha;
 	sector_t *FOFSector;
+	FBITFIELD blend;
+	boolean fogplane;
+	extracolormap_t *planecolormap;
 	INT32 drawcount;
 } planeinfo_t;
 
@@ -3350,7 +3897,7 @@ static INT32 drawcount = 0;
 
 // This will likely turn into a copy of HWR_Add3DWater and replace it.
 void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub,
-	fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector)
+	fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap)
 {
 	if (!(numplanes % MAX_TRANSPARENTFLOOR))
 	{
@@ -3364,6 +3911,9 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub,
 	planeinfo[numplanes].xsub = xsub;
 	planeinfo[numplanes].alpha = alpha;
 	planeinfo[numplanes].FOFSector = FOFSector;
+	planeinfo[numplanes].blend = blend;
+	planeinfo[numplanes].fogplane = fogplane;
+	planeinfo[numplanes].planecolormap = planecolormap;
 	planeinfo[numplanes].drawcount = drawcount++;
 	numplanes++;
 }
@@ -3475,19 +4025,20 @@ static void HWR_CreateDrawNodes(void)
 	{
 		if (sortnode[sortindex[i]].plane)
 		{
-			FBITFIELD PolyFlags = PF_Translucent | (sortnode[sortindex[i]].plane->alpha<<24);
-
 			// We aren't traversing the BSP tree, so make gr_frontsector null to avoid crashes.
 			gr_frontsector = NULL;
 
-			HWR_GetFlat(sortnode[sortindex[i]].plane->lumpnum);
-			HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->fixedheight, PolyFlags, sortnode[sortindex[i]].plane->lightlevel,
-				sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->FOFSector);
+			if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture))
+				HWR_GetFlat(sortnode[sortindex[i]].plane->lumpnum);
+			HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel,
+				sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap);
 		}
 		else if (sortnode[sortindex[i]].wall)
 		{
-			HWR_GetTexture(sortnode[sortindex[i]].wall->texnum);
-			HWR_RenderWall(sortnode[sortindex[i]].wall->wallVerts, &sortnode[sortindex[i]].wall->Surf, sortnode[sortindex[i]].wall->blend);
+			if (!(sortnode[sortindex[i]].wall->blend & PF_NoTexture))
+				HWR_GetTexture(sortnode[sortindex[i]].wall->texnum);
+			HWR_RenderWall(sortnode[sortindex[i]].wall->wallVerts, &sortnode[sortindex[i]].wall->Surf, sortnode[sortindex[i]].wall->blend, sortnode[sortindex[i]].wall->fogwall,
+				sortnode[sortindex[i]].wall->lightlevel, sortnode[sortindex[i]].wall->wallcolormap);
 		}
 	}
 
@@ -3517,11 +4068,17 @@ static void HWR_DrawSprites(void)
 		     spr = spr->next)
 		{
 #ifdef HWPRECIP
-			if (spr->precip == true)
+			if (spr->precip)
 				HWR_DrawPrecipitationSprite(spr);
 			else
 #endif
-				HWR_DrawSprite(spr);
+				if (spr->mobj->skin)
+				{
+					if (!cv_grmd2.value || (cv_grmd2.value && md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound == true))
+						HWR_DrawSprite(spr);
+				}
+				else if (!cv_grmd2.value || (cv_grmd2.value && md2_models[spr->mobj->sprite].notfound == true))
+					HWR_DrawSprite(spr);
 		}
 	}
 }
@@ -3540,7 +4097,20 @@ static void HWR_DrawMD2S(void)
 			spr != &gr_vsprsortedhead;
 			spr = spr->next)
 		{
-			HWR_DrawMD2(spr);
+#ifdef HWPRECIP
+			if (!spr->precip)
+			{
+#endif
+				if (spr->mobj && spr->mobj->skin)
+				{
+					if ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound == false) && (md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale > 0.0f))
+						HWR_DrawMD2(spr);
+				}
+				else if (md2_models[spr->mobj->sprite].notfound == false && md2_models[spr->mobj->sprite].scale > 0.0f)
+					HWR_DrawMD2(spr);
+#ifdef HWPRECIP
+			}
+#endif
 		}
 	}
 }
@@ -3582,7 +4152,7 @@ static void HWR_AddSprites(sector_t *sec)
 			if (!thing)
 				continue;
 
-			if ((thing->flags2 & MF2_DONTDRAW) == 0)
+			if (!(thing->flags2 & MF2_DONTDRAW))
 			{
 				adx = abs(players[displayplayer].mo->x - thing->x);
 				ady = abs(players[displayplayer].mo->y - thing->y);
@@ -3614,11 +4184,11 @@ static void HWR_AddSprites(sector_t *sec)
 			if (!thing)
 				continue;
 
-			if ((thing->flags2 & MF2_DONTDRAW) == 0)
+			if (!(thing->flags2 & MF2_DONTDRAW))
 				HWR_ProjectSprite(thing);
 
 			if (cv_objectplace.value
-			&& (thing->flags2 & MF2_DONTDRAW) == 0)
+			&& (!thing->flags2 & MF2_DONTDRAW))
 				objectsdrawn++;
 
 			if (!thing->snext)
@@ -3816,30 +4386,6 @@ static void HWR_ProjectSprite(mobj_t *thing)
 	//CONS_Printf("------------------\nH: sprite  : %d\nH: frame   : %x\nH: type    : %d\nH: sname   : %s\n\n",
 	//            thing->sprite, thing->frame, thing->type, sprnames[thing->sprite]);
 
-	if (thing->state && (thing->state->frame & FF_FULLBRIGHT))
-		/// \todo disable also the fog
-		vis->sectorlight = 0xff;
-	else
-	{
-		sector_t *sector;
-		if (thing->subsector)
-			sector = thing->subsector->sector;
-		else
-			sector = R_PointInSubsector(thing->x, thing->y)->sector;
-
-		if (sector)
-		{
-			if (sector->ffloors)
-			{
-				ffloor_t *caster = sector->lightlist[R_GetPlaneLight(sector, thing->z+thing->height/2, false)].caster;
-				sector = caster ? &sectors[caster->secnum] : sector;
-			}
-			vis->sectorlight = LightLevelToLum(sector->lightlevel & 0xff);
-		}
-		else
-			vis->sectorlight = sectorlight;
-	}
-
 	if (thing->eflags & MFE_VERTICALFLIP)
 		vis->vflip = true;
 	else
@@ -4108,6 +4654,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
 	//------------------------------------------------------------------------
 	HWR_ClearView();
 
+	/* // I don't think this is ever used.
 	if (cv_grfog.value)
 	{
 		camera_t *camview;
@@ -4167,6 +4714,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
 	}
 	else
 		HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); // Turn it off
+		*/
 
 	if (drawsky)
 		HWR_DrawSkyBackground(player);
@@ -4253,6 +4801,10 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
 	}
 #endif
 
+	// put it off for menus etc
+	if (cv_grfog.value)
+		HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0);
+
 #ifdef SHUFFLE
 	HWR_DoPostProcessor();
 #endif
@@ -4260,9 +4812,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
 	NetUpdate();
 
 	//------------------------------------------------------------------------
-	// put it off for menus etc
-	if (cv_grfog.value)
-		HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0);
+
 
 	// added by Hurdler for correct splitscreen
 	// moved here by hurdler so it works with the new near clipping plane
@@ -4530,13 +5080,13 @@ static void HWR_Render3DWater(void)
 
 		HWR_GetFlat(planeinfo[i].lumpnum);
 		HWR_RenderPlane(NULL, planeinfo[i].xsub, planeinfo[i].fixedheight, PolyFlags, planeinfo[i].lightlevel, planeinfo[i].lumpnum,
-			planeinfo[i].FOFSector);
+			planeinfo[i].FOFSector, planeinfo[i].alpha, planeinfo[i].fogplane, planeinfo[i].planecolormap);
 	}
 	numfloors = 0;
 }
 #endif
 
-static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, FBITFIELD blend)
+static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap)
 {
 	if (!(numwalls % MAX_TRANSPARENTWALL))
 	{
@@ -4551,6 +5101,9 @@ static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, I
 #ifdef SORTING
 	wallinfo[numwalls].drawcount = drawcount++;
 #endif
+	wallinfo[numwalls].fogwall = fogwall;
+	wallinfo[numwalls].lightlevel = lightlevel;
+	wallinfo[numwalls].wallcolormap = wallcolormap;
 	numwalls++;
 }
 #ifndef SORTING
@@ -4580,12 +5133,12 @@ static void HWR_RenderTransparentWalls(void)
 	for (i = 0; i < numwalls; i++)
 	{
 		HWR_GetTexture(wallinfo[i].texnum);
-		HWR_RenderWall(wallinfo[i].wallVerts, &wallinfo[i].Surf, wallinfo[i].blend);
+		HWR_RenderWall(wallinfo[i].wallVerts, &wallinfo[i].Surf, wallinfo[i].blend, wallinfo[i].wall->fogwall, wallinfo[i].wall->lightlevel, wallinfo[i].wall->wallcolormap);
 	}
 	numwalls = 0;
 }
 #endif
-static void HWR_RenderWall(wallVert3D   *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend)
+static void HWR_RenderWall(wallVert3D   *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap)
 {
 	FOutVector  trVerts[4];
 	UINT8       i;
@@ -4606,6 +5159,26 @@ static void HWR_RenderWall(wallVert3D   *wallVerts, FSurfaceInfo *pSurf, FBITFIE
 		wv->z = wallVerts->z;
 	}
 
+	UINT8 alpha = pSurf->FlatColor.s.alpha; // retain the alpha
+
+	// Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting
+	if (wallcolormap)
+	{
+		if (fogwall)
+			pSurf->FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel), wallcolormap->rgba, wallcolormap->fadergba, true, false);
+		else
+			pSurf->FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel), wallcolormap->rgba, wallcolormap->fadergba, false, false);
+	}
+	else
+	{
+		if (fogwall)
+			pSurf->FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel), NORMALFOG, FADEFOG, true, false);
+		else
+			pSurf->FlatColor.rgba = HWR_Lighting(LightLevelToLum(lightlevel), NORMALFOG, FADEFOG, false, false);
+	}
+
+	pSurf->FlatColor.s.alpha = alpha; // put the alpha back after lighting
+
 	if (blend & PF_Environment)
 		HWD.pfnDrawPolygon(pSurf, trVerts, 4, blend|PF_Modulated|PF_Clip|PF_Occlude); // PF_Occlude must be used for solid objects
 	else
@@ -4634,18 +5207,29 @@ void HWR_DoPostProcessor(void)
 	if(gamestate != GS_INTERMISSION)
 		HWD.pfnMakeScreenTexture();
 
-	// Drunken vision! WooOOooo~
-	if (postimgtype == postimg_water)
+	if (postimgtype == postimg_water || postimgtype == postimg_heat)
 	{
 		// 10 by 10 grid. 2 coordinates (xy)
 		float v[SCREENVERTS][SCREENVERTS][2];
 		static double disStart = 0;
 		UINT8 x, y;
+		INT32 WAVELENGTH;
+		INT32 AMPLITUDE;
+		INT32 FREQUENCY;
 
 		// Modifies the wave.
-		const INT32 WAVELENGTH = 20; // Lower is longer
-		const INT32 AMPLITUDE = 20; // Lower is bigger
-		const INT32 FREQUENCY = 16; // Lower is faster
+		if (postimgtype == postimg_water)
+		{
+			WAVELENGTH = 20; // Lower is longer
+			AMPLITUDE = 20; // Lower is bigger
+			FREQUENCY = 16; // Lower is faster
+		}
+		else
+		{
+			WAVELENGTH = 10; // Lower is longer
+			AMPLITUDE = 30; // Lower is bigger
+			FREQUENCY = 4; // Lower is faster
+		}
 
 		for (x = 0; x < SCREENVERTS; x++)
 		{
@@ -4743,7 +5327,7 @@ void HWR_DrawIntermissionBG(void)
 
 void HWR_DoScreenWipe(void)
 {
-	HWRWipeCounter -= 0.07f;
+	HWRWipeCounter -= 0.035f;
 /*
 	if(cv_debug)
 		CONS_Printf("In HWR_DoScreenWipe(). Alpha =%f\n", HWRWipeCounter);
diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h
index 55e90e3..e6077b2 100644
--- a/src/hardware/hw_main.h
+++ b/src/hardware/hw_main.h
@@ -69,6 +69,10 @@ void HWR_PrepFadeToBlack(void);
 void HWR_DrawIntermissionBG(void);
 #endif
 
+// This stuff is put here so MD2's can use them
+UINT32 HWR_Lighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogblockpoly, boolean plane);
+FUNCMATH UINT8 LightLevelToLum(INT32 l);
+
 extern CV_PossibleValue_t granisotropicmode_cons_t[];
 
 extern consvar_t cv_grrenderquality;
@@ -77,6 +81,7 @@ extern consvar_t cv_grmd2;
 extern consvar_t cv_grfog;
 extern consvar_t cv_grfogcolor;
 extern consvar_t cv_grfogdensity;
+extern consvar_t cv_grsoftwarefog;
 extern consvar_t cv_grgammared;
 extern consvar_t cv_grgammagreen;
 extern consvar_t cv_grgammablue;
diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index 69a5393..10956a5 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -34,6 +34,9 @@
 #include "../m_misc.h"
 #include "../w_wad.h"
 #include "../z_zone.h"
+#include "../r_things.h"
+
+#include "hw_main.h"
 
 #ifdef HAVE_PNG
 
@@ -227,6 +230,7 @@ float avertexnormals[NUMVERTEXNORMALS][3] = {
 };
 
 md2_t md2_models[NUMSPRITES];
+md2_t md2_playermodels[MAXSKINS];
 
 /*
  * free model
@@ -878,16 +882,27 @@ static void md2_loadTexture(md2_t *model)
 void HWR_InitMD2(void)
 {
 	size_t i;
+	INT32 s;
 	FILE *f;
-	char name[5], filename[32];
+	char name[18], filename[32];
 	float scale, offset;
 
 	CONS_Printf("InitMD2()...\n");
+	for (s = 0; s < MAXSKINS; s++)
+	{
+		md2_playermodels[s].scale = -1.0f;
+		md2_playermodels[s].model = NULL;
+		md2_playermodels[s].grpatch = NULL;
+		md2_playermodels[s].skin = -1;
+		md2_playermodels[s].notfound = true;
+	}
 	for (i = 0; i < NUMSPRITES; i++)
 	{
 		md2_models[i].scale = -1.0f;
 		md2_models[i].model = NULL;
 		md2_models[i].grpatch = NULL;
+		md2_models[i].skin = -1;
+		md2_models[i].notfound = true;
 	}
 	// read the md2.dat file
 
@@ -897,26 +912,142 @@ void HWR_InitMD2(void)
 		CONS_Printf("Error while loading md2.dat\n");
 		return;
 	}
-	while (fscanf(f, "%4s %31s %f %f", name, filename, &scale, &offset) == 4)
+
+	md2_t *md2;
+
+	while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4)
 	{
 		for (i = 0; i < NUMSPRITES; i++)
 		{
-			if (strcmp(name, sprnames[i]) == 0)
+			if (stricmp(name, sprnames[i]) == 0)
 			{
+				if (stricmp(name, "PLAY") == 0)
+					continue;
+
 				//CONS_Printf("  Found: %s %s %f %f\n", name, filename, scale, offset);
 				md2_models[i].scale = scale;
 				md2_models[i].offset = offset;
+				md2_models[i].notfound = false;
 				strcpy(md2_models[i].filename, filename);
+				md2 = &md2_models[i];
 				break;
 			}
+			if (i == NUMSPRITES)
+			{
+				CONS_Printf("MD2 for sprite %s not found\n", name);
+				md2_models[i].notfound = true;
+			}
+		}
+
+		for (s = 0; s < MAXSKINS; s++)
+		{
+			if (stricmp(name, skins[s].name) == 0)
+			{
+				//CONS_Printf("  Found: %s %s %f %f\n", name, filename, scale, offset);
+				md2_playermodels[s].skin = s;
+				md2_playermodels[s].scale = scale;
+				md2_playermodels[s].offset = offset;
+				md2_playermodels[s].notfound = false;
+				strcpy(md2_playermodels[s].filename, filename);
+				md2 = &md2_playermodels[s];
+				break;
+			}
+			if (s == MAXSKINS-1)
+			{
+				CONS_Printf("MD2 for player skin %s not found\n", name);
+				md2_playermodels[s].notfound = true;
+			}
+		}
+
+	}
+	fclose(f);
+}
+
+
+void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup
+{
+	FILE *f;
+	char name[18], filename[32];
+	float scale, offset;
+
+	CONS_Printf("AddPlayerMD2()...\n");
+
+	// read the md2.dat file
+
+	f = fopen("md2.dat", "rt");
+	if (!f)
+	{
+		CONS_Printf("Error while loading md2.dat\n");
+		return;
+	}
+
+	// Check for any MD2s that match the names of player skins!
+	while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4)
+	{
+		if (stricmp(name, skins[skin].name) == 0)
+		{
+			md2_playermodels[skin].skin = skin;
+			md2_playermodels[skin].scale = scale;
+			md2_playermodels[skin].offset = offset;
+			md2_playermodels[skin].notfound = false;
+			strcpy(md2_playermodels[skin].filename, filename);
+			break;
+		}
+		if (skin == MAXSKINS-1)
+		{
+			CONS_Printf("MD2 for player skin %s not found\n", name);
+			md2_playermodels[skin].notfound = true;
 		}
-		if (i == NUMSPRITES)
-			CONS_Printf("    Not found: %s\n", name);
 	}
+
 	fclose(f);
+
 }
 
+void HWR_AddSpriteMD2(int spritenum) // For MD2s that were added after startup
+{
+	FILE *f;
+	// name[18] is used to check for names in the md2.dat file that match with sprites or player skins
+	// sprite names are always 4 characters long, and names is for player skins can be up to 19 characters long
+	char name[18], filename[32];
+	float scale, offset;
+
+	// Read the md2.dat file
+
+	f = fopen("md2.dat", "rt");
+
+	if (!f)
+	{
+		CONS_Printf("Error while loading md2.dat\n");
+		return;
+	}
 
+	// Check for any MD2s that match the names of player skins!
+	while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4)
+	{
+		{
+			if (stricmp(name, sprnames[spritenum]) == 0)
+			{
+				if (stricmp(name, "PLAY") == 0) // Handled already NEWMD2: Per sprite, per-skin check
+					continue;
+
+				md2_models[spritenum].scale = scale;
+				md2_models[spritenum].offset = offset;
+				md2_models[spritenum].notfound = false;
+				strcpy(md2_models[spritenum].filename, filename);
+				break;
+			}
+
+			if (spritenum == NUMSPRITES-1)
+			{
+				CONS_Printf("MD2 for sprite %s not found\n", name);
+				md2_models[spritenum].notfound = true;
+			}
+		}
+	}
+
+	fclose(f);
+}
 
 // -----------------+
 // HWR_DrawMD2      : Draw MD2
@@ -937,6 +1068,8 @@ void HWR_InitMD2(void)
 	res?
 	run?
 	*/
+#define NORMALFOG 0x00000000
+#define FADEFOG 0x19000000
 void HWR_DrawMD2(gr_vissprite_t *spr)
 {
 	GLPatch_t *gpatch; // sprite patch converted to hardware
@@ -959,37 +1092,62 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
 	//12/12/99: Hurdler: same comment as above (for md2)
 	HWR_GetMappedPatch(gpatch, spr->colormap);
 
-	// model lighting by modulating the RGB components
-	/// \todo Handled colored lighting
-	Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = spr->sectorlight;
 	// MD2 colormap fix
 	// colormap test
 	{
 		sector_t *sector = spr->mobj->subsector->sector;
+		UINT8 lightlevel = LightLevelToLum(sector->lightlevel);
+		extracolormap_t *colormap = sector->extra_colormap;
 
-		if (sector->ffloors)
+		if (sector->numlights)
 		{
-			ffloor_t *caster;
+			INT32 light = R_GetPlaneLight(sector, spr->mobj->z, false);
+
+			if (sector->lightlist[light].height > (spr->mobj->z + spr->mobj->height))
+			{
+				if (!(spr->mobj->frame & FF_FULLBRIGHT))
+					lightlevel = LightLevelToLum(*sector->lightlist[light].lightlevel);
+				else
+					lightlevel = LightLevelToLum(255);
+
+				if (sector->lightlist[light].extra_colormap)
+					colormap = sector->lightlist[light].extra_colormap;
+			}
+			else // If we can't use the light at its bottom, we'll use the light at its top
+			{
+				light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false);
+
+				if (!(spr->mobj->frame & FF_FULLBRIGHT))
+					lightlevel = LightLevelToLum(*sector->lightlist[light].lightlevel);
+				else
+					lightlevel = LightLevelToLum(255);
 
-			caster = sector->lightlist[R_GetPlaneLight(sector, spr->mobj->z+spr->mobj->height, false)].caster;
-			sector = caster ? &sectors[caster->secnum] : sector;
+				if (sector->lightlist[light].extra_colormap)
+					colormap = sector->lightlist[light].extra_colormap;
+			}
 		}
-		if (sector->extra_colormap)
+		else
 		{
-			RGBA_t temp;
-			INT32 alpha;
-
-			temp.rgba = sector->extra_colormap->rgba;
-			alpha = (26 - temp.s.alpha)*spr->sectorlight;
-			Surf.FlatColor.s.red = (UINT8)((alpha + temp.s.alpha*temp.s.red)/26);
-			Surf.FlatColor.s.blue = (UINT8)((alpha + temp.s.alpha*temp.s.blue)/26);
-			Surf.FlatColor.s.green = (UINT8)((alpha + temp.s.alpha*temp.s.green)/26);
-			Surf.FlatColor.s.alpha = 0xff;
+			if (!(spr->mobj->frame & FF_FULLBRIGHT))
+				lightlevel = LightLevelToLum(sector->lightlevel);
+			else
+				lightlevel = LightLevelToLum(255);
+
+			if (sector->extra_colormap)
+				colormap = sector->extra_colormap;
 		}
+
+		if (spr->mobj->frame & FF_FULLBRIGHT)
+			lightlevel = LightLevelToLum(255);
+
+		if (colormap)
+			Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false);
+		else
+			Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false);
 	}
 
 	// Look at HWR_ProjetctSprite for more
-	if (cv_grmd2.value && (md2_models[spr->mobj->sprite].scale > 0) && !spr->precip)
+	if (cv_grmd2.value && ((md2_models[spr->mobj->sprite].scale > 0.0f) || (md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale > 0.0f)) && !spr->precip)
 	{
 		FBITFIELD blend = 0;
 		GLPatch_t *oldgpatch = gpatch;
@@ -999,6 +1157,9 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
 		md2_frame_t *curr, *next = NULL;
 		const UINT8 flip = (UINT8)((spr->mobj->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP);
 
+		spritedef_t *sprdef;
+		spriteframe_t *sprframe;
+
 		if (spr->mobj->flags2 & MF2_SHADOW)
 		{
 			Surf.FlatColor.s.alpha = 0x40;
@@ -1017,7 +1178,14 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
 
 		// 1. load model+texture if not already loaded
 		// 2. draw model with correct position, rotation,...
-		md2 = &md2_models[spr->mobj->sprite];
+		if (spr->mobj->skin)
+		{
+			md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins];
+			md2->skin = (skin_t*)spr->mobj->skin-skins;
+		}
+		else
+			md2 = &md2_models[spr->mobj->sprite];
+
 		if (!md2->model)
 		{
 			//CONS_Printf("Loading MD2... (%s)", sprnames[spr->mobj->sprite]);
@@ -1044,14 +1212,16 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
 			HWD.pfnSetTexture(&oldgpatch->mipmap);
 
 		//FIXME: this is not yet correct
-		frame = spr->mobj->frame % md2->model->header.numFrames;
+		frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->header.numFrames;
 		buff = md2->model->glCommandBuffer;
 		curr = &md2->model->frames[frame];
 		if (cv_grmd2.value == 1
 		    && spr->mobj->state->nextstate != S_DISS
-		    && spr->mobj->state->nextstate != S_NULL)
+		    && spr->mobj->state->nextstate != S_NULL
+			&& !(spr->mobj->player && (spr->mobj->state->nextstate == S_PLAY_TAP1 || spr->mobj->state->nextstate == S_PLAY_TAP2) && spr->mobj->state == &states[S_PLAY_STND])
+			)
 		{
-			const INT32 nextframe = states[spr->mobj->state->nextstate].frame % md2->model->header.numFrames;
+			const INT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames;
 			next = &md2->model->frames[nextframe];
 		}
 
@@ -1064,10 +1234,23 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
 		else
 			p.z = FIXED_TO_FLOAT(spr->mobj->z);
 
+		if (spr->mobj->skin)
+			sprdef = &((skin_t *)spr->mobj->skin)->spritedef;
+		else
+			sprdef = &sprites[spr->mobj->sprite];
+
+		sprframe = &sprdef->spriteframes[spr->mobj->frame & FF_FRAMEMASK];
+
+		if (sprframe->rotate)
 		{
 			const fixed_t anglef = AngleFixed(spr->mobj->angle);
 			p.angley = FIXED_TO_FLOAT(anglef);
 		}
+		else
+		{
+			const fixed_t anglef = AngleFixed((R_PointToAngle(spr->mobj->x, spr->mobj->y))-ANGLE_180);
+			p.angley = FIXED_TO_FLOAT(anglef);
+		}
 		p.anglex = 0.0f;
 
 		color[0] = Surf.FlatColor.s.red;
@@ -1075,7 +1258,16 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
 		color[2] = Surf.FlatColor.s.blue;
 		color[3] = Surf.FlatColor.s.alpha;
 
-		HWD.pfnDrawMD2i(buff, curr, durs, tics, next, &p, md2->scale, flip, color);
+		// SRB2CBTODO: MD2 scaling support
+		float finalscale = md2->scale;
+
+		if (spr->mobj->scale != 100)
+		{
+			float normscale = md2->scale;
+			finalscale = (float)(normscale*(((float)spr->mobj->scale)/100.0f));
+		}
+
+		HWD.pfnDrawMD2i(buff, curr, durs, tics, next, &p, finalscale, flip, color);
 
 	}
 }
diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h
index 030e1d2..9ab870c 100644
--- a/src/hardware/hw_md2.h
+++ b/src/hardware/hw_md2.h
@@ -120,11 +120,16 @@ typedef struct
 	float       offset;
 	md2_model_t *model;
 	void        *grpatch;
+	boolean	notfound;
+	long skin;
 } md2_t;
 
 extern md2_t md2_models[NUMSPRITES];
+extern md2_t md2_playermodels[MAXSKINS];
 
 void HWR_InitMD2(void);
 void HWR_DrawMD2(gr_vissprite_t *spr);
+void HWR_AddPlayerMD2(int skin);
+void HWR_AddSpriteMD2(int spritenum);
 
 #endif // _HW_MD2_H_
diff --git a/src/hardware/hw_trick.c b/src/hardware/hw_trick.c
index d8ab519..b7cabe7 100644
--- a/src/hardware/hw_trick.c
+++ b/src/hardware/hw_trick.c
@@ -924,7 +924,7 @@ void HWR_CorrectSWTricks(void)
 					if (sdr->toptexture == 0)
 					{
 						if (sdr->midtexture == 0)
-							sdr->toptexture = R_TextureNumForName("REDWALL", (UINT16)(sdr-sides)); // Tails
+							sdr->toptexture = 0; // Tails // When this was REDWALL it was causing issues in the sky sometimes
 						else
 							sdr->toptexture = sdr->midtexture;
 					}
@@ -935,7 +935,7 @@ void HWR_CorrectSWTricks(void)
 					if (sdl->toptexture == 0)
 					{
 						if (sdl->midtexture == 0)
-							sdl->toptexture = R_TextureNumForName("REDWALL", (UINT16)(sdl-sides)); // Tails
+							sdl->toptexture = 0; // Tails // When this was REDWALL it was causing issues in the sky sometimes
 						else
 							sdl->toptexture = sdl->midtexture;
 					}
diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c
index 0e9de26..dea4c20 100644
--- a/src/hardware/r_opengl/r_opengl.c
+++ b/src/hardware/r_opengl/r_opengl.c
@@ -273,6 +273,8 @@ typedef void (APIENTRY * PFNglLightModelfv) (GLenum pname, GLfloat *params);
 static PFNglLightModelfv pglLightModelfv;
 typedef void (APIENTRY * PFNglMaterialfv) (GLint face, GLenum pname, GLfloat *params);
 static PFNglMaterialfv pglMaterialfv;
+typedef void (APIENTRY * PFNglLightfv) (GLenum light, GLenum pname, GLfloat *params);
+static PFNglLightfv pglLightfv;
 
 /* Raster functions */
 typedef void (APIENTRY  * PFNglReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
@@ -382,6 +384,7 @@ boolean SetupGLfunc(void)
 	pglShadeModel = GetGLFunc("glShadeModel");
 	pglLightModelfv = GetGLFunc("glLightModelfv");
 	pglMaterialfv = GetGLFunc("glMaterialfv");
+	pglLightfv = GetGLFunc("glLightfv");
 
 	pglReadPixels = GetGLFunc("glReadPixels");
 
@@ -459,6 +462,7 @@ void SetStates(void)
 	FUINT Data[8*8];
 	INT32 i;
 	float LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
+	GLfloat LightPos[] = {0.0f, 1.0f, 0.0f, 0.0f};
 
 	DBG_Printf("SetStates()\n");
 
@@ -517,6 +521,7 @@ void SetStates(void)
 	// Lighting for models
 	pglLightModelfv(GL_LIGHT_MODEL_AMBIENT, LightDiffuse);
 	pglEnable (GL_LIGHT0);
+	pglLightfv(GL_LIGHT0, GL_POSITION, LightPos);
 
 	// bp : when no t&l :)
 	pglLoadIdentity();
diff --git a/src/m_menu.c b/src/m_menu.c
index f973efc..af7a3f0 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -8170,6 +8170,7 @@ static menuitem_t OGL_FogMenu[] =
 	{IT_STRING|IT_CVAR,       NULL, "Fog",         &cv_grfog,         0},
 	{IT_STRING|IT_KEYHANDLER, NULL, "Fog color",   M_HandleFogColor, 10},
 	{IT_STRING|IT_CVAR,       NULL, "Fog density", &cv_grfogdensity, 20},
+	{IT_STRING|IT_CVAR,       NULL, "Software Fog",&cv_grsoftwarefog,30},
 };
 
 static menuitem_t OGL_ColorMenu[] =
diff --git a/src/p_setup.c b/src/p_setup.c
index 22b3326..24a1d09 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1179,23 +1179,72 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum)
 				else
 				{
 					// for now, full support of toptexture only
-					if (msd->toptexture[0] == '#')
+					if ((msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6])
+						|| (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6]))
 					{
-						char *col = msd->toptexture;
+						char *col;
 
 						sec->midmap = R_CreateColormap(msd->toptexture, msd->midtexture,
 							msd->bottomtexture);
 						sd->toptexture = sd->bottomtexture = 0;
-#define HEX2INT(x) (x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
-#define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : 0)
+
 						sec->extra_colormap = &extra_colormaps[sec->midmap];
-						sec->extra_colormap->rgba =
-							(HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0) +
-							(HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8) +
-							(HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16) +
-							(ALPHA2INT(col[7]) << 24);
+
+						if (msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6])
+						{
+							col = msd->toptexture;
+
+#define HEX2INT(x) (x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
+#define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0)
+							if (msd->toptexture[7])
+							{
+								sec->extra_colormap->rgba =
+									(HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0) +
+									(HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8) +
+									(HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16) +
+									(ALPHA2INT(col[7]) << 24);
+							}
+							else
+							{
+								sec->extra_colormap->rgba =
+									(HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0) +
+									(HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8) +
+									(HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16) +
+									(25 << 24);
+							}
+						}
+						else
+						{
+							sec->extra_colormap->rgba = 0;
+						}
+
+						if (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6])
+						{
+							col = msd->bottomtexture;
+
+							if (msd->bottomtexture[7])
+							{
+								sec->extra_colormap->fadergba =
+									(HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0) +
+									(HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8) +
+									(HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16) +
+									(ALPHA2INT(col[7]) << 24);
+							}
+							else
+							{
+								sec->extra_colormap->fadergba =
+									(HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0) +
+									(HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8) +
+									(HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16) +
+									(25 << 24);
+							}
 #undef ALPHA2INT
 #undef HEX2INT
+						}
+						else
+						{
+							sec->extra_colormap->fadergba = 0x19000000;
+						}
 					}
 					else
 					{
diff --git a/src/r_defs.h b/src/r_defs.h
index 7d288b4..27b0415 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -65,6 +65,7 @@ typedef struct
 
 	// rgba is used in hw mode for colored sector lighting
 	INT32 rgba; // similar to maskcolor in sw mode
+	INT32 fadergba; // The colour the colourmaps fade to
 
 	lighttable_t *colormap;
 } extracolormap_t;
diff --git a/src/r_main.c b/src/r_main.c
index 42a1804..143ee93 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -966,6 +966,7 @@ void R_RegisterEngineStuff(void)
 	CV_RegisterVar(&cv_grfovchange);
 	CV_RegisterVar(&cv_grfog);
 	CV_RegisterVar(&cv_grfogcolor);
+	CV_RegisterVar(&cv_grsoftwarefog);
 #endif
 
 #ifdef HWRENDER
diff --git a/src/r_things.c b/src/r_things.c
index e75d22e..0d5d678 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -32,6 +32,7 @@
 #include "r_plane.h"
 #include "p_tick.h"
 #include "p_local.h"
+#include "hardware\hw_md2.h"
 
 #ifdef PC_DOS
 #include <stdio.h> // for snprintf
@@ -411,6 +412,8 @@ void R_AddSpriteDefs(UINT16 wadnum)
 
 		if (R_AddSingleSpriteDef(spritename, &sprites[i], wadnum, start, end))
 		{
+			if (rendermode == render_opengl)
+				HWR_AddSpriteMD2(i);
 			// if a new sprite was added (not just replaced)
 			addsprites++;
 			if (devparm)
@@ -2850,6 +2853,9 @@ next_token:
 		ST_LoadFaceGraphics(skins[numskins].faceprefix, skins[numskins].superprefix, numskins);
 		ST_LoadFaceNameGraphics(skins[numskins].nameprefix, numskins);
 
+		if (rendermode == render_opengl)
+			HWR_AddPlayerMD2(numskins);
+
 		numskins++;
 	}
 	return;
diff --git a/src/v_video.c b/src/v_video.c
index 764dea2..002aa05 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -58,11 +58,13 @@ static void CV_Gammaxxx_ONChange(void);
 // but they won't do anything.
 static CV_PossibleValue_t grrenderquality_cons_t[] = {{1, "Speed"}, {2, "Quality"}, {3, "Full Quality"}, {0, NULL}};
 static CV_PossibleValue_t grgamma_cons_t[] = {{1, "MIN"}, {255, "MAX"}, {0, NULL}};
+static CV_PossibleValue_t grsoftwarefog_cons_t[4] = {{0, "Off"}, {1, "On"}, {2, "LightPlanes"}, {0, NULL}};
 
 consvar_t cv_grrenderquality = {"gr_renderdetail", "Quality", CV_SAVE, grrenderquality_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_grfovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_grfog = {"gr_fog", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_grfogcolor = {"gr_fogcolor", "AAAAAA", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_grsoftwarefog = {"gr_softwarefog", "Off", CV_SAVE, grsoftwarefog_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_grgammared = {"gr_gammared", "127", CV_SAVE|CV_CALL, grgamma_cons_t,
                            CV_Gammaxxx_ONChange, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_grgammagreen = {"gr_gammagreen", "127", CV_SAVE|CV_CALL, grgamma_cons_t,
 
Last edited:
a fixup

A few notes:
  • test with -DNOHW to make sure your code works for systems that does not have 3D support
  • the var type "byte" only exist in Win32 land, use UINT8 in it place
  • use / not \ for paths, also Win32 only
Code:
diff --git a/src/f_wipe.c b/src/f_wipe.c
index 2f665d6..ff344e8 100644
--- a/src/f_wipe.c
+++ b/src/f_wipe.c
@@ -82,7 +82,7 @@ static INT32 F_DoWipe(INT32 width, INT32 height, tic_t ticks)
 
        while (ticks--)
        {
-#ifdef SHUFFLE
+#if defined (SHUFFLE) && defined (HWRENDER)
                if(rendermode != render_soft)
                {
 
@@ -130,7 +130,7 @@ void F_WipeStartScreen(void)
 #ifndef NOWIPE
        if(rendermode != render_soft)
        {
-#ifdef SHUFFLE
+#if defined (SHUFFLE) && defined (HWRENDER)
                HWR_StartScreenWipe();
 #endif
                return;
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 22207a0..b76992d 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -2869,7 +2869,7 @@ static void HWR_Subsector(size_t num)
                        {
                                if (rover->flags & FF_FOG)
                                {
-                                       byte alpha;
+                                       UINT8 alpha;
 
                                        light = R_GetPlaneLight(gr_frontsector, *rover->topheight, dup_viewz < *rover->topheight ? true : false);
 
diff --git a/src/r_things.c b/src/r_things.c
index 0d5d678..173c8a9 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -32,7 +32,9 @@
 #include "r_plane.h"
 #include "p_tick.h"
 #include "p_local.h"
-#include "hardware\hw_md2.h"
+#ifdef HWRENDER
+#include "hardware/hw_md2.h"
+#endif
 
 #ifdef PC_DOS
 #include <stdio.h> // for snprintf
@@ -412,8 +414,10 @@ void R_AddSpriteDefs(UINT16 wadnum)
 
                if (R_AddSingleSpriteDef(spritename, &sprites[i], wadnum, start, end))
                {
+#ifdef HWRENDER
                        if (rendermode == render_opengl)
                                HWR_AddSpriteMD2(i);
+#endif
                        // if a new sprite was added (not just replaced)
                        addsprites++;
                        if (devparm)
@@ -2853,8 +2857,10 @@ next_token:
                ST_LoadFaceGraphics(skins[numskins].faceprefix, skins[numskins].superprefix, numskins);
                ST_LoadFaceNameGraphics(skins[numskins].nameprefix, numskins);
 
+#ifdef HWRENDER
                if (rendermode == render_opengl)
                        HWR_AddPlayerMD2(numskins);
+#endif
 
A few notes:
  • test with -DNOHW to make sure your code works for systems that does not have 3D support
  • the var type "byte" only exist in Win32 land, use UINT8 in it place
  • use / not \ for paths, also Win32 only
Code:
diff --git a/src/f_wipe.c b/src/f_wipe.c
index 2f665d6..ff344e8 100644
--- a/src/f_wipe.c
+++ b/src/f_wipe.c
@@ -82,7 +82,7 @@ static INT32 F_DoWipe(INT32 width, INT32 height, tic_t ticks)
 
        while (ticks--)
        {
-#ifdef SHUFFLE
+#if defined (SHUFFLE) && defined (HWRENDER)
                if(rendermode != render_soft)
                {
 
@@ -130,7 +130,7 @@ void F_WipeStartScreen(void)
 #ifndef NOWIPE
        if(rendermode != render_soft)
        {
-#ifdef SHUFFLE
+#if defined (SHUFFLE) && defined (HWRENDER)
                HWR_StartScreenWipe();
 #endif
                return;
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 22207a0..b76992d 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -2869,7 +2869,7 @@ static void HWR_Subsector(size_t num)
                        {
                                if (rover->flags & FF_FOG)
                                {
-                                       byte alpha;
+                                       UINT8 alpha;
 
                                        light = R_GetPlaneLight(gr_frontsector, *rover->topheight, dup_viewz < *rover->topheight ? true : false);
 
diff --git a/src/r_things.c b/src/r_things.c
index 0d5d678..173c8a9 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -32,7 +32,9 @@
 #include "r_plane.h"
 #include "p_tick.h"
 #include "p_local.h"
-#include "hardware\hw_md2.h"
+#ifdef HWRENDER
+#include "hardware/hw_md2.h"
+#endif
 
 #ifdef PC_DOS
 #include <stdio.h> // for snprintf
@@ -412,8 +414,10 @@ void R_AddSpriteDefs(UINT16 wadnum)
 
                if (R_AddSingleSpriteDef(spritename, &sprites[i], wadnum, start, end))
                {
+#ifdef HWRENDER
                        if (rendermode == render_opengl)
                                HWR_AddSpriteMD2(i);
+#endif
                        // if a new sprite was added (not just replaced)
                        addsprites++;
                        if (devparm)
@@ -2853,8 +2857,10 @@ next_token:
                ST_LoadFaceGraphics(skins[numskins].faceprefix, skins[numskins].superprefix, numskins);
                ST_LoadFaceNameGraphics(skins[numskins].nameprefix, numskins);
 
+#ifdef HWRENDER
                if (rendermode == render_opengl)
                        HWR_AddPlayerMD2(numskins);
+#endif

Oops, I knew I'd have done SOMETHING wrong. I've applied the changes you pointed out and re-uploaded the executable and source code. Thanks.
 
After using this, r_opengl.dll has decided not to load on SRB2Net or SRB2CB. It just gives me a loadlibrary error or something about r_opengl.dll not being found, then it says opengl failed to initialize. Reinstalling didn't help, and using the vanilla dll OR the dll included here OR the vanilla dll backup included in here makes no difference. How do I fix this?
 
After using this, r_opengl.dll has decided not to load on SRB2Net or SRB2CB. It just gives me a loadlibrary error or something about r_opengl.dll not being found, then it says opengl failed to initialize. Reinstalling didn't help, and using the vanilla dll OR the dll included here OR the vanilla dll backup included in here makes no difference. How do I fix this?

This is an issue I've known about in OpenGL for a long time, I don't know what causes it or why. But for some reason closing Steam if I have it running seems to get it working again. It could possibly be related with another program, so try that.
 
This is an issue I've known about in OpenGL for a long time, I don't know what causes it or why. But for some reason closing Steam if I have it running seems to get it working again. It could possibly be related with another program, so try that.
I'm having the same issue as Sonic Fan, and I don't even have Steam, could someone please help with this?

EDIT: Nevermind, I found out it works with the SRB2Start launcher.
 
Last edited:
Status
Not open for further replies.

Who is viewing this thread (Total: 0, Members: 0, Guests: 0)

Back
Top