From 5c16a91fd63ddfe1af0c3d8a723cc36828d2e8ec Mon Sep 17 00:00:00 2001
From: Ronald Kinard <furyhunter600@gmail.com>
Date: Wed, 1 Apr 2015 20:48:54 -0500
Subject: [PATCH] Render most flats and sides with texture arrays.

This breaks stencil buffer clipping, transparent flats, the whole
nine yards.

Unfortunately, this is about as far as I will be taking this
approach to cleaning up OpenGL. It's unfortunate, but this
renderer is basically unsalvagable. I will have to rewrite it
completely from scratch to get what I want out of this.
---
 src/hardware/hw_defs.h           |  6 +++
 src/hardware/hw_draw.c           | 20 ++++-----
 src/hardware/hw_drv.h            |  2 +-
 src/hardware/hw_light.c          |  8 ++--
 src/hardware/hw_main.c           | 76 +++++++++++++++++++++++---------
 src/hardware/hw_vertarray.c      | 36 ++++++++++++---
 src/hardware/hw_vertbuckets.c    |  8 +++-
 src/hardware/hw_vertbuckets.h    |  1 +
 src/hardware/r_opengl/r_opengl.c | 17 +++++--
 src/win32/win_dll.c              |  2 +-
 10 files changed, 128 insertions(+), 48 deletions(-)

diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h
index 70d776d9e9..302e750162 100644
--- a/src/hardware/hw_defs.h
+++ b/src/hardware/hw_defs.h
@@ -159,6 +159,12 @@ enum EPolyFlags
 	PF_Debug            = 0x80000000    // print debug message in driver :)
 };
 
+enum EPolygonPrimitive
+{
+	PP_TriangleFan = 0,
+	PP_Triangles
+};
+
 
 enum ESurfFlags
 {
diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c
index e6a26e6058..f1e82aa5cb 100644
--- a/src/hardware/hw_draw.c
+++ b/src/hardware/hw_draw.c
@@ -132,7 +132,7 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option)
 		flags |= PF_ForceWrapY;
 
 	// clip it since it is used for bunny scroll in doom I
-	HWD.pfnDrawPolygon(NULL, v, 4, flags);
+	HWD.pfnDrawPolygon(NULL, v, 4, flags, PP_TriangleFan);
 }
 
 void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, const UINT8 *colormap)
@@ -229,10 +229,10 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
 		else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value];
 		else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel];
 		flags |= PF_Modulated;
-		HWD.pfnDrawPolygon(&Surf, v, 4, flags);
+		HWD.pfnDrawPolygon(&Surf, v, 4, flags, PP_TriangleFan);
 	}
 	else
-		HWD.pfnDrawPolygon(NULL, v, 4, flags);
+		HWD.pfnDrawPolygon(NULL, v, 4, flags, PP_TriangleFan);
 }
 
 void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h)
@@ -305,10 +305,10 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
 		else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value];
 		else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel];
 		flags |= PF_Modulated;
-		HWD.pfnDrawPolygon(&Surf, v, 4, flags);
+		HWD.pfnDrawPolygon(&Surf, v, 4, flags, PP_TriangleFan);
 	}
 	else
-		HWD.pfnDrawPolygon(NULL, v, 4, flags);
+		HWD.pfnDrawPolygon(NULL, v, 4, flags, PP_TriangleFan);
 }
 
 void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
@@ -343,7 +343,7 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
 	// But then, the question is: why not 0 instead of PF_Masked ?
 	// or maybe PF_Environment ??? (like what I said above)
 	// BP: PF_Environment don't change anything ! and 0 is undifined
-	HWD.pfnDrawPolygon(NULL, v, 4, BLENDMODE | PF_NoDepthTest | PF_Clip | PF_NoZClip);
+	HWD.pfnDrawPolygon(NULL, v, 4, BLENDMODE | PF_NoDepthTest | PF_Clip | PF_NoZClip, PP_TriangleFan);
 }
 
 // ==========================================================================
@@ -419,7 +419,7 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum
 	// BTW, I see we put 0 for PFs, and If I'm right, that
 	// means we take the previous PFs as default
 	// how can we be sure they are ok?
-	HWD.pfnDrawPolygon(NULL, v, 4, PF_NoDepthTest); //PF_Translucent);
+	HWD.pfnDrawPolygon(NULL, v, 4, PF_NoDepthTest, PP_TriangleFan); //PF_Translucent);
 }
 
 
@@ -452,7 +452,7 @@ void HWR_FadeScreenMenuBack(UINT32 color, INT32 height)
 
 	Surf.FlatColor.rgba = UINT2RGBA(color);
 	Surf.FlatColor.s.alpha = (UINT8)((0xff/2) * ((float)height / vid.height)); //calum: varies console alpha
-	HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
+	HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest, PP_TriangleFan);
 }
 
 // Draw the console background with translucency support
@@ -479,7 +479,7 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height)
 	Surf.FlatColor.rgba = UINT2RGBA(color);
 	Surf.FlatColor.s.alpha = 0x80;
 
-	HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
+	HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest, PP_TriangleFan);
 }
 
 
@@ -678,7 +678,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
 	Surf.FlatColor = V_GetColor(color);
 
 	HWD.pfnDrawPolygon(&Surf, v, 4,
-		PF_Modulated|PF_NoTexture|PF_NoDepthTest);
+		PF_Modulated|PF_NoTexture|PF_NoDepthTest, PP_TriangleFan);
 }
 
 #ifdef HAVE_PNG
diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h
index 188aeff981..cb75c21a5e 100644
--- a/src/hardware/hw_drv.h
+++ b/src/hardware/hw_drv.h
@@ -53,7 +53,7 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal, RGBA_t *pgamma);
 #endif
 EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl);
 EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color);
-EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags);
+EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int PrimitiveType);
 EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags);
 EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor);
 EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo);
diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c
index fb369387f4..70c03ed397 100644
--- a/src/hardware/hw_light.c
+++ b/src/hardware/hw_light.c
@@ -768,7 +768,7 @@ void HWR_WallLighting(FOutVector *wlVerts)
 		if (dynlights->mo[j]->state->nextstate == S_NULL)
 			Surf.FlatColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha);
 
-		HWD.pfnDrawPolygon (&Surf, wlVerts, 4, LIGHTMAPFLAGS);
+		HWD.pfnDrawPolygon (&Surf, wlVerts, 4, LIGHTMAPFLAGS, PP_TriangleFan);
 
 	} // end for (j = 0; j < dynlights->nb; j++)
 }
@@ -831,7 +831,7 @@ void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts)
 		if ((dynlights->mo[j]->state->nextstate == S_NULL))
 			Surf.FlatColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha);
 
-		HWD.pfnDrawPolygon (&Surf, clVerts, nrClipVerts, LIGHTMAPFLAGS);
+		HWD.pfnDrawPolygon (&Surf, clVerts, nrClipVerts, LIGHTMAPFLAGS, PP_TriangleFan);
 
 	} // end for (j = 0; j < dynlights->nb; j++)
 }
@@ -928,7 +928,7 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gr_vissprite_t *spr)
 
 		HWR_GetPic(coronalumpnum);  /// \todo use different coronas
 
-		HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_Corona | PF_NoDepthTest);
+		HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_Corona | PF_NoDepthTest, PP_TriangleFan);
 	}
 }
 #endif
@@ -1008,7 +1008,7 @@ void HWR_DrawCoronas(void)
 		light[3].y = cy+size*1.33f;
 		light[3].sow = 0.0f;   light[3].tow = 1.0f;
 
-		HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_NoDepthTest | PF_Corona);
+		HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_NoDepthTest | PF_Corona, PP_TriangleFan);
 	}
 }
 #endif
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 549b4ac2a9..00668daf9d 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -24,6 +24,7 @@
 #include "hw_glob.h"
 #include "hw_light.h"
 #include "hw_drv.h"
+#include "hw_vertbuckets.h"
 
 #include "../i_video.h" // for rendermode == render_glide
 #include "../v_video.h"
@@ -758,7 +759,8 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi
 	else
 		PolyFlags |= PF_Masked|PF_Modulated|PF_Clip;
 
-	HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags);
+	//HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags);
+    HWR_InsertVertexArray(HWR_GetVertexArrayForFlat(lumpnum), nrPlaneVerts, planeVerts);
 
 #ifdef ALAM_LIGHTING
 	// add here code for dynamic lighting on planes
@@ -807,7 +809,7 @@ static void HWR_RenderSkyPlane(extrasubsector_t *xsub, fixed_t fixedheight)
 	}
 
 	HWD.pfnDrawPolygon(NULL, planeVerts, nrPlaneVerts,
-	 PF_Clip|PF_Invisible|PF_NoTexture|PF_Occlude);
+	 PF_Clip|PF_Invisible|PF_NoTexture|PF_Occlude, PP_TriangleFan);
 }
 #endif //polysky
 
@@ -897,7 +899,7 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
 				break;
 		}
 
-		HWD.pfnDrawPolygon(&pSurf2, trVerts, 4, i|PF_Modulated|PF_Clip|PF_Decal);
+		HWD.pfnDrawPolygon(&pSurf2, trVerts, 4, i|PF_Modulated|PF_Clip|PF_Decal, PP_TriangleFan);
 	}
 }
 #endif
@@ -942,7 +944,7 @@ static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo * pSurf,
 */
 static void HWR_ProjectWall(wallVert3D   * wallVerts,
                                     FSurfaceInfo * pSurf,
-                                    FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap)
+                                    FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap, int texnum)
 {
 	FOutVector  trVerts[4];
 	FOutVector  *wv;
@@ -988,7 +990,14 @@ static void HWR_ProjectWall(wallVert3D   * wallVerts,
 		pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false);
 	}
 
-	HWD.pfnDrawPolygon(pSurf, trVerts, 4, blendmode|PF_Modulated|PF_Occlude|PF_Clip);
+    if (texnum == -1)
+    {
+        //HWD.pfnDrawPolygon(pSurf, trVerts, 4, blendmode|PF_Modulated|PF_Occlude|PF_Clip, PP_TriangleFan);
+    }
+    else
+    {
+        HWR_InsertVertexArray(HWR_GetVertexArrayForTexture(texnum), 4, trVerts);   
+    }
 
 #ifdef WALLSPLATS
 	if (gr_curline->linedef->splats && cv_splats.value)
@@ -1144,7 +1153,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 		else if (glTex->mipmap.flags & TF_TRANSPARENT)
 			HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Environment, false, lightnum, colormap);
 		else
-			HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap);
+			HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap, texnum);
 
 		if (solid)
 			top = bheight;
@@ -1181,7 +1190,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 	else if (glTex->mipmap.flags & TF_TRANSPARENT)
 		HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Environment, false, lightnum, colormap);
 	else
-		HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap);
+		HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap, texnum);
 }
 
 //
@@ -1301,7 +1310,7 @@ static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t b
 	// set top/bottom coords
 	wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(top); // No real way to find the correct height of this
 	wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(bottom); // worldlow/bottom because it needs to cover up the lower thok barrier wall
-	HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_Clip|PF_NoTexture, 255, NULL);
+	HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_Clip|PF_NoTexture, 255, NULL, -1);
 	// PF_Invisible so it's not drawn into the colour buffer
 	// PF_NoTexture for no texture
 	// PF_Occlude is set in HWR_ProjectWall to draw into the depth buffer
@@ -1448,7 +1457,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			else if (grTex->mipmap.flags & TF_TRANSPARENT)
 				HWR_AddTransparentWall(wallVerts, &Surf, texturetranslation[gr_sidedef->toptexture], PF_Environment, false, lightnum, colormap);
 			else
-				HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
+				HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap, texturetranslation[gr_sidedef->toptexture]);
 		}
 
 		// check BOTTOM TEXTURE
@@ -1486,7 +1495,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			else if (grTex->mipmap.flags & TF_TRANSPARENT)
 				HWR_AddTransparentWall(wallVerts, &Surf, texturetranslation[gr_sidedef->bottomtexture], PF_Environment, false, lightnum, colormap);
 			else
-				HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
+				HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap, texturetranslation[gr_sidedef->bottomtexture]);
 		}
 		gr_midtexture = texturetranslation[gr_sidedef->midtexture];
 		if (gr_midtexture)
@@ -1686,7 +1695,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			else if (!(blendmode & PF_Masked))
 				HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, blendmode, false, lightnum, colormap);
 			else
-				HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap);
+				HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap, gr_midtexture);
 
 			// 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)
@@ -1810,7 +1819,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				if (grTex->mipmap.flags & TF_TRANSPARENT)
 					HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, PF_Environment, false, lightnum, colormap);
 				else
-					HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
+					HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap, gr_midtexture);
 			}
 		}
 
@@ -1936,7 +1945,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 						if (blendmode != PF_Masked)
 							HWR_AddTransparentWall(wallVerts, &Surf, texnum, blendmode, false, lightnum, colormap);
 						else
-							HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
+							HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap, texnum);
 					}
 				}
 			}
@@ -2042,7 +2051,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 						if (blendmode != PF_Masked)
 							HWR_AddTransparentWall(wallVerts, &Surf, texnum, blendmode, false, lightnum, colormap);
 						else
-							HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
+							HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap, texnum);
 					}
 				}
 			}
@@ -2785,7 +2794,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, fixed_t fixedheight
 	else
 		blendmode |= PF_Masked|PF_Modulated|PF_Clip;
 
-	HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode);
+	HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, PP_TriangleFan);
 }
 
 static void HWR_AddPolyObjectPlanes(void)
@@ -2979,6 +2988,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, 255, false, floorcolormap);
 			}
@@ -3814,7 +3824,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
 			if (sSurf.FlatColor.s.alpha > floorheight/4)
 			{
 				sSurf.FlatColor.s.alpha = (UINT8)(sSurf.FlatColor.s.alpha - floorheight/4);
-				HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated|PF_Clip);
+				HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated|PF_Clip, PP_TriangleFan);
 			}
 		}
 	}
@@ -3886,7 +3896,7 @@ noshadow:
 			blend = PF_Translucent|PF_Occlude;
 		}
 
-		HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip);
+		HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, PP_TriangleFan);
 	}
 }
 
@@ -3986,7 +3996,7 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
 		blend = PF_Translucent|PF_Occlude;
 	}
 
-	HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip);
+	HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, PP_TriangleFan);
 }
 #endif
 
@@ -4883,7 +4893,7 @@ static void HWR_DrawSkyBackground(player_t *player)
 		v[0].tow = v[1].tow -= ((float) angle / angleturn);
 	}
 
-	HWD.pfnDrawPolygon(NULL, v, 4, 0);
+	HWD.pfnDrawPolygon(NULL, v, 4, 0, PP_TriangleFan);
 }
 
 
@@ -5075,7 +5085,9 @@ if (0)
 
 	validcount++;
 
+    HWR_ResetVertexBuckets();
 	HWR_RenderBSPNode((INT32)numnodes-1);
+    HWR_DrawVertexBuckets();
 
 	// Make a viewangle int so we can render things based on mouselook
 	if (player == &players[consoleplayer])
@@ -5088,18 +5100,27 @@ if (0)
 	{
 		dup_viewangle += ANGLE_90;
 		HWR_ClearClipSegs();
+
+        HWR_ResetVertexBuckets();
 		HWR_RenderBSPNode((INT32)numnodes-1); //left
+        HWR_DrawVertexBuckets();
 
 		dup_viewangle += ANGLE_90;
 		if (((INT32)aimingangle > ANGLE_45 || (INT32)aimingangle<-ANGLE_45))
 		{
 			HWR_ClearClipSegs();
+
+            HWR_ResetVertexBuckets();
 			HWR_RenderBSPNode((INT32)numnodes-1); //back
+            HWR_DrawVertexBuckets();
 		}
 
 		dup_viewangle += ANGLE_90;
 		HWR_ClearClipSegs();
+
+        HWR_ResetVertexBuckets();
 		HWR_RenderBSPNode((INT32)numnodes-1); //right
+        HWR_DrawVertexBuckets();
 
 		dup_viewangle += ANGLE_90;
 	}
@@ -5305,7 +5326,9 @@ if (0)
 
 	validcount++;
 
+    HWR_ResetVertexBuckets();
 	HWR_RenderBSPNode((INT32)numnodes-1);
+    HWR_DrawVertexBuckets();
 
 	// Make a viewangle int so we can render things based on mouselook
 	if (player == &players[consoleplayer])
@@ -5318,18 +5341,27 @@ if (0)
 	{
 		dup_viewangle += ANGLE_90;
 		HWR_ClearClipSegs();
+
+        HWR_ResetVertexBuckets();
 		HWR_RenderBSPNode((INT32)numnodes-1); //left
+        HWR_DrawVertexBuckets();
 
 		dup_viewangle += ANGLE_90;
 		if (((INT32)aimingangle > ANGLE_45 || (INT32)aimingangle<-ANGLE_45))
 		{
 			HWR_ClearClipSegs();
+
+            HWR_ResetVertexBuckets();
 			HWR_RenderBSPNode((INT32)numnodes-1); //back
+            HWR_DrawVertexBuckets();
 		}
 
 		dup_viewangle += ANGLE_90;
 		HWR_ClearClipSegs();
+
+        HWR_ResetVertexBuckets();
 		HWR_RenderBSPNode((INT32)numnodes-1); //right
+        HWR_DrawVertexBuckets();
 
 		dup_viewangle += ANGLE_90;
 	}
@@ -5774,9 +5806,9 @@ static void HWR_RenderWall(wallVert3D   *wallVerts, FSurfaceInfo *pSurf, FBITFIE
 	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
+		HWD.pfnDrawPolygon(pSurf, trVerts, 4, blend|PF_Modulated|PF_Clip|PF_Occlude, PP_TriangleFan); // PF_Occlude must be used for solid objects
 	else
-		HWD.pfnDrawPolygon(pSurf, trVerts, 4, blend|PF_Modulated|PF_Clip); // No PF_Occlude means overlapping (incorrect) transparency
+		HWD.pfnDrawPolygon(pSurf, trVerts, 4, blend|PF_Modulated|PF_Clip, PP_TriangleFan); // No PF_Occlude means overlapping (incorrect) transparency
 
 #ifdef WALLSPLATS
 	if (gr_curline->linedef->splats && cv_splats.value)
@@ -5830,7 +5862,7 @@ void HWR_DoPostProcessor(player_t *player)
 
 		Surf.FlatColor.s.alpha = 0xc0; // match software mode
 
-		HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Additive|PF_NoTexture|PF_NoDepthTest|PF_Clip|PF_NoZClip);
+		HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Additive|PF_NoTexture|PF_NoDepthTest|PF_Clip|PF_NoZClip, PP_TriangleFan);
 	}
 
 	// Capture the screen for intermission and screen waving
diff --git a/src/hardware/hw_vertarray.c b/src/hardware/hw_vertarray.c
index 07b9e4fa82..70e514c41e 100644
--- a/src/hardware/hw_vertarray.c
+++ b/src/hardware/hw_vertarray.c
@@ -28,7 +28,7 @@ void HWR_InitVertexArray(FVertexArray * varray, unsigned int initialSize)
 {
 	varray->size = initialSize;
 	varray->used = 0;
-	varray->buffer = Z_Malloc(varray->size * sizeof(FOutVector), PU_STATIC, varray);
+	varray->buffer = (FOutVector *) Z_Malloc(varray->size * sizeof(FOutVector), PU_STATIC, varray);
 }
 
 void HWR_FreeVertexArray(FVertexArray * varray)
@@ -39,16 +39,40 @@ void HWR_FreeVertexArray(FVertexArray * varray)
 void HWR_InsertVertexArray(FVertexArray * varray, int numElements, FOutVector * elements)
 {
 	int i = 0;
-	if (varray->used + numElements >= varray->size)
+	FOutVector * actualElements = NULL;
+	int numActualElements = numElements;
+
+	// Expand array from fan to triangles
+	// Not optimal... but the overhead will make up for it significantly
+	{
+		int j = 0;
+		int k = 0;
+		numActualElements -= 3;
+		numActualElements *= 3;
+		numActualElements += 3;
+
+		actualElements = (FOutVector *) Z_Malloc(numActualElements * sizeof(FOutVector), PU_STATIC, NULL);
+
+		for (j = 2; j < numElements; j++)
+		{
+			actualElements[k] = elements[0];
+			actualElements[k+1] = elements[j-1];
+			actualElements[k+2] = elements[j];
+			k += 3;
+		}
+	}
+
+	while (varray->used + numActualElements >= varray->size)
 	{
+		varray->buffer = (FOutVector *) Z_Realloc(varray->buffer, varray->size * RESIZE_FACTOR * sizeof(FOutVector), PU_STATIC, varray);
 		varray->size *= RESIZE_FACTOR;
-		varray->buffer = Z_Realloc(varray->buffer, varray->size * sizeof(FOutVector), PU_STATIC, varray);
 	}
 
-	for (i = 0; i < numElements; i++)
+	for (i = 0; i < numActualElements; i++)
 	{
-		varray->buffer[i + varray->used] = elements[i];
+		varray->buffer[i + varray->used] = actualElements[i];
 	}
 	
-	varray->used += numElements;
+	varray->used += numActualElements;
+	Z_Free(actualElements);
 }
diff --git a/src/hardware/hw_vertbuckets.c b/src/hardware/hw_vertbuckets.c
index c74569ab3c..d1274a7197 100644
--- a/src/hardware/hw_vertbuckets.c
+++ b/src/hardware/hw_vertbuckets.c
@@ -57,6 +57,12 @@ static void DrawArraysFunc(INT32 key, void * value)
 	FVertexArray * varray = (FVertexArray *) value;
 	FSurfaceInfo surf;
 
+	if (varray->used == 0)
+	{
+		return;
+	}
+
+
 	surf.FlatColor.rgba = 0xFFFFFFFF;
 
 	if (rmode == RMODE_FLAT)
@@ -68,7 +74,7 @@ static void DrawArraysFunc(INT32 key, void * value)
 		HWR_GetTexture(key);
 	}
 	// TODO support flags, translucency, etc
-	HWD.pfnDrawPolygon(&surf, varray->buffer, varray->used, 0);
+	HWD.pfnDrawPolygon(&surf, varray->buffer, varray->used, PF_Occlude, PP_Triangles);
 }
 
 static FVertexArray * GetVArray(aatree_t * tree, int index)
diff --git a/src/hardware/hw_vertbuckets.h b/src/hardware/hw_vertbuckets.h
index c93f19d301..95775ced10 100644
--- a/src/hardware/hw_vertbuckets.h
+++ b/src/hardware/hw_vertbuckets.h
@@ -33,6 +33,7 @@
   * should be called before rendering any BSP node. */
 void HWR_ResetVertexBuckets(void);
 
+FVertexArray * HWR_GetVertexArrayForFlat(lumpnum_t lumpnum);
 /** Get a pointer to the vertex array used for a given texture number. */
 FVertexArray * HWR_GetVertexArrayForTexture(int texNum);
 
diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c
index c5b2dfa0d4..687031373e 100644
--- a/src/hardware/r_opengl/r_opengl.c
+++ b/src/hardware/r_opengl/r_opengl.c
@@ -1335,7 +1335,8 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo  *pSurf,
                                     //FTextureInfo  *pTexInfo,
                                     FOutVector    *pOutVerts,
                                     FUINT         iNumPts,
-                                    FBITFIELD     PolyFlags)
+                                    FBITFIELD     PolyFlags,
+                                    int           PrimitiveType)
 {
 	FUINT i;
 	FUINT j;
@@ -1423,7 +1424,17 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo  *pSurf,
 	pglEnableClientState(GL_TEXTURE_COORD_ARRAY);
 	pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x);
 	pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].sow);
-	pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts);
+	switch (PrimitiveType)
+	{
+		case PP_TriangleFan:
+			pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts);
+			break;
+		case PP_Triangles:
+			pglDrawArrays(GL_TRIANGLES, 0, iNumPts);
+			break;
+		default:
+			break;
+	}
 	pglDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	pglDisableClientState(GL_VERTEX_ARRAY);
 
@@ -1648,7 +1659,7 @@ EXPORT void HWRAPI(DrawMD2i) (INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 d
 #endif
 	}
 
-	DrawPolygon(NULL, NULL, 0, PF_Masked|PF_Modulated|PF_Occlude|PF_Clip);
+	DrawPolygon(NULL, NULL, 0, PF_Masked|PF_Modulated|PF_Occlude|PF_Clip, PP_TriangleFan);
 
 	pglPushMatrix(); // should be the same as glLoadIdentity
 	//Hurdler: now it seems to work
diff --git a/src/win32/win_dll.c b/src/win32/win_dll.c
index 7f9ed002bf..7f5decd219 100644
--- a/src/win32/win_dll.c
+++ b/src/win32/win_dll.c
@@ -101,7 +101,7 @@ static loadfunc_t hwdFuncTable[] = {
 	{"SetPalette@8",        &hwdriver.pfnSetPalette},
 	{"FinishUpdate@4",      &hwdriver.pfnFinishUpdate},
 	{"Draw2DLine@12",       &hwdriver.pfnDraw2DLine},
-	{"DrawPolygon@16",      &hwdriver.pfnDrawPolygon},
+	{"DrawPolygon@20",      &hwdriver.pfnDrawPolygon},
 	{"SetBlend@4",          &hwdriver.pfnSetBlend},
 	{"ClearBuffer@12",      &hwdriver.pfnClearBuffer},
 	{"SetTexture@4",        &hwdriver.pfnSetTexture},
-- 
GitLab