]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
redesigned skeletal model loading and rendering to use matrix-palette animation ...
[xonotic/darkplaces.git] / r_shadow.c
index 9ddb71f74cb7214dedfb98072767f14df5f1a23a..e1a736e4e317e3af85658085aa4be9b76daedbac 100644 (file)
@@ -709,20 +709,22 @@ void R_Shadow_RenderVolume(int numvertices, int numtriangles, const float *verte
                return;
        }
        renderstats.lights_shadowtriangles += numtriangles;
+       CHECKGLERROR
        R_Mesh_VertexPointer(vertex3f);
        GL_LockArrays(0, numvertices);
        if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCIL)
        {
                // decrement stencil if backface is behind depthbuffer
-               qglCullFace(GL_BACK); // quake is backwards, this culls front faces
-               qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
+               qglCullFace(GL_BACK);CHECKGLERROR // quake is backwards, this culls front faces
+               qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
                R_Mesh_Draw(0, numvertices, numtriangles, element3i);
                // increment stencil if frontface is behind depthbuffer
-               qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
-               qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
+               qglCullFace(GL_FRONT);CHECKGLERROR // quake is backwards, this culls back faces
+               qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
        }
        R_Mesh_Draw(0, numvertices, numtriangles, element3i);
        GL_LockArrays(0, 0);
+       CHECKGLERROR
 }
 
 static void R_Shadow_MakeTextures(void)
@@ -793,8 +795,6 @@ void R_Shadow_ValidateCvars(void)
 // light currently being rendered
 rtlight_t *r_shadow_rtlight;
 
-// this is the location of the eye in entity space
-vec3_t r_shadow_entityeyeorigin;
 // this is the location of the light in entity space
 vec3_t r_shadow_entitylightorigin;
 // this transforms entity coordinates to light filter cubemap coordinates
@@ -816,14 +816,15 @@ void R_Shadow_RenderMode_Begin(void)
         || r_shadow_lightattenuationscale.value != r_shadow_attenscale)
                R_Shadow_MakeTextures();
 
+       CHECKGLERROR
        R_Mesh_ColorPointer(NULL);
        R_Mesh_ResetTextureState();
        GL_BlendFunc(GL_ONE, GL_ZERO);
        GL_DepthMask(false);
        GL_DepthTest(true);
        GL_Color(0, 0, 0, 1);
-       qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
-       qglEnable(GL_CULL_FACE);
+       qglCullFace(GL_FRONT);CHECKGLERROR // quake is backwards, this culls back faces
+       qglEnable(GL_CULL_FACE);CHECKGLERROR
        GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
 
        r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
@@ -848,51 +849,51 @@ void R_Shadow_RenderMode_ActiveLight(rtlight_t *rtlight)
 
 void R_Shadow_RenderMode_Reset(void)
 {
+       CHECKGLERROR
        if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL)
        {
-               qglUseProgramObjectARB(0);
-               // HACK HACK HACK: work around for bug in NVIDIAI 6xxx drivers that causes GL_OUT_OF_MEMORY and/or software rendering
-               qglBegin(GL_TRIANGLES);
-               qglEnd();
-               CHECKGLERROR
+               qglUseProgramObjectARB(0);CHECKGLERROR
        }
        else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCILTWOSIDE)
-               qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
+       {
+               qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
+       }
        R_Mesh_ColorPointer(NULL);
        R_Mesh_ResetTextureState();
 }
 
 void R_Shadow_RenderMode_StencilShadowVolumes(void)
 {
+       CHECKGLERROR
        R_Shadow_RenderMode_Reset();
        GL_Color(1, 1, 1, 1);
        GL_ColorMask(0, 0, 0, 0);
        GL_BlendFunc(GL_ONE, GL_ZERO);
        GL_DepthMask(false);
        GL_DepthTest(true);
-       qglPolygonOffset(r_shadowpolygonfactor, r_shadowpolygonoffset);
-       qglDepthFunc(GL_LESS);
-       qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
-       qglEnable(GL_STENCIL_TEST);
-       qglStencilFunc(GL_ALWAYS, 128, ~0);
+       qglPolygonOffset(r_shadowpolygonfactor, r_shadowpolygonoffset);CHECKGLERROR
+       qglDepthFunc(GL_LESS);CHECKGLERROR
+       qglCullFace(GL_FRONT);CHECKGLERROR // quake is backwards, this culls back faces
+       qglEnable(GL_STENCIL_TEST);CHECKGLERROR
+       qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
        r_shadow_rendermode = r_shadow_shadowingrendermode;
        if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCILTWOSIDE)
        {
-               qglDisable(GL_CULL_FACE);
-               qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
-               qglActiveStencilFaceEXT(GL_BACK); // quake is backwards, this is front faces
-               qglStencilMask(~0);
-               qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
-               qglActiveStencilFaceEXT(GL_FRONT); // quake is backwards, this is back faces
-               qglStencilMask(~0);
-               qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
+               qglDisable(GL_CULL_FACE);CHECKGLERROR
+               qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
+               qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR // quake is backwards, this is front faces
+               qglStencilMask(~0);CHECKGLERROR
+               qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
+               qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR // quake is backwards, this is back faces
+               qglStencilMask(~0);CHECKGLERROR
+               qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
        }
        else
        {
-               qglEnable(GL_CULL_FACE);
-               qglStencilMask(~0);
+               qglEnable(GL_CULL_FACE);CHECKGLERROR
+               qglStencilMask(~0);CHECKGLERROR
                // this is changed by every shadow render so its value here is unimportant
-               qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+               qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
        }
        GL_Clear(GL_STENCIL_BUFFER_BIT);
        renderstats.lights_clears++;
@@ -900,29 +901,38 @@ void R_Shadow_RenderMode_StencilShadowVolumes(void)
 
 void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent)
 {
+       CHECKGLERROR
        R_Shadow_RenderMode_Reset();
        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
        GL_DepthMask(false);
        GL_DepthTest(true);
-       qglPolygonOffset(r_polygonfactor, r_polygonoffset);
-       //qglDisable(GL_POLYGON_OFFSET_FILL);
+       qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
+       //qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
        GL_Color(1, 1, 1, 1);
        GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
        if (transparent)
-               qglDepthFunc(GL_LEQUAL);
+       {
+               qglDepthFunc(GL_LEQUAL);CHECKGLERROR
+       }
        else
-               qglDepthFunc(GL_EQUAL);
-       qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
-       qglEnable(GL_CULL_FACE);
+       {
+               qglDepthFunc(GL_EQUAL);CHECKGLERROR
+       }
+       qglCullFace(GL_FRONT);CHECKGLERROR // quake is backwards, this culls back faces
+       qglEnable(GL_CULL_FACE);CHECKGLERROR
        if (stenciltest)
-               qglEnable(GL_STENCIL_TEST);
+       {
+               qglEnable(GL_STENCIL_TEST);CHECKGLERROR
+       }
        else
-               qglDisable(GL_STENCIL_TEST);
-       qglStencilMask(~0);
-       qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+       {
+               qglDisable(GL_STENCIL_TEST);CHECKGLERROR
+       }
+       qglStencilMask(~0);CHECKGLERROR
+       qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
        // only draw light where this geometry was already rendered AND the
        // stencil is 128 (values other than this mean shadow)
-       qglStencilFunc(GL_EQUAL, 128, ~0);
+       qglStencilFunc(GL_EQUAL, 128, ~0);CHECKGLERROR
        r_shadow_rendermode = r_shadow_lightingrendermode;
        // do global setup needed for the chosen lighting mode
        if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL)
@@ -946,63 +956,76 @@ void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent)
 
 void R_Shadow_RenderMode_VisibleShadowVolumes(void)
 {
+       CHECKGLERROR
        R_Shadow_RenderMode_Reset();
        GL_BlendFunc(GL_ONE, GL_ONE);
        GL_DepthMask(false);
        GL_DepthTest(!r_showdisabledepthtest.integer);
-       qglPolygonOffset(r_polygonfactor, r_polygonoffset);
+       qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
        GL_Color(0.0, 0.0125, 0.1, 1);
        GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
-       qglDepthFunc(GL_GEQUAL);
-       qglCullFace(GL_FRONT); // this culls back
-       qglDisable(GL_CULL_FACE);
-       qglDisable(GL_STENCIL_TEST);
+       qglDepthFunc(GL_GEQUAL);CHECKGLERROR
+       qglCullFace(GL_FRONT);CHECKGLERROR // this culls back
+       qglDisable(GL_CULL_FACE);CHECKGLERROR
+       qglDisable(GL_STENCIL_TEST);CHECKGLERROR
        r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLEVOLUMES;
 }
 
 void R_Shadow_RenderMode_VisibleLighting(qboolean stenciltest, qboolean transparent)
 {
+       CHECKGLERROR
        R_Shadow_RenderMode_Reset();
        GL_BlendFunc(GL_ONE, GL_ONE);
        GL_DepthMask(false);
        GL_DepthTest(!r_showdisabledepthtest.integer);
-       qglPolygonOffset(r_polygonfactor, r_polygonoffset);
+       qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
        GL_Color(0.1, 0.0125, 0, 1);
        GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
        if (transparent)
-               qglDepthFunc(GL_LEQUAL);
+       {
+               qglDepthFunc(GL_LEQUAL);CHECKGLERROR
+       }
        else
-               qglDepthFunc(GL_EQUAL);
-       qglCullFace(GL_FRONT); // this culls back
-       qglEnable(GL_CULL_FACE);
+       {
+               qglDepthFunc(GL_EQUAL);CHECKGLERROR
+       }
+       qglCullFace(GL_FRONT);CHECKGLERROR // this culls back
+       qglEnable(GL_CULL_FACE);CHECKGLERROR
        if (stenciltest)
-               qglEnable(GL_STENCIL_TEST);
+       {
+               qglEnable(GL_STENCIL_TEST);CHECKGLERROR
+       }
        else
-               qglDisable(GL_STENCIL_TEST);
+       {
+               qglDisable(GL_STENCIL_TEST);CHECKGLERROR
+       }
        r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLELIGHTING;
 }
 
 void R_Shadow_RenderMode_End(void)
 {
+       CHECKGLERROR
        R_Shadow_RenderMode_Reset();
        R_Shadow_RenderMode_ActiveLight(NULL);
        GL_BlendFunc(GL_ONE, GL_ZERO);
        GL_DepthMask(true);
        GL_DepthTest(true);
-       qglPolygonOffset(r_polygonfactor, r_polygonoffset);
-       //qglDisable(GL_POLYGON_OFFSET_FILL);
+       qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
+       //qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
        GL_Color(1, 1, 1, 1);
        GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
        GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
-       qglDepthFunc(GL_LEQUAL);
-       qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
-       qglEnable(GL_CULL_FACE);
-       qglDisable(GL_STENCIL_TEST);
-       qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+       qglDepthFunc(GL_LEQUAL);CHECKGLERROR
+       qglCullFace(GL_FRONT);CHECKGLERROR // quake is backwards, this culls back faces
+       qglEnable(GL_CULL_FACE);CHECKGLERROR
+       qglDisable(GL_STENCIL_TEST);CHECKGLERROR
+       qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
        if (gl_support_stenciltwoside)
-               qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
-       qglStencilMask(~0);
-       qglStencilFunc(GL_ALWAYS, 128, ~0);
+       {
+               qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
+       }
+       qglStencilMask(~0);CHECKGLERROR
+       qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
        r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
 }
 
@@ -1090,8 +1113,8 @@ qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
 
        // the light area is visible, set up the scissor rectangle
        GL_Scissor(ix1, vid.height - iy2, ix2 - ix1, iy2 - iy1);
-       //qglScissor(ix1, iy1, ix2 - ix1, iy2 - iy1);
-       //qglEnable(GL_SCISSOR_TEST);
+       //qglScissor(ix1, iy1, ix2 - ix1, iy2 - iy1);CHECKGLERROR
+       //qglEnable(GL_SCISSOR_TEST);CHECKGLERROR
        renderstats.lights_scissored++;
        return false;
 }
@@ -1117,7 +1140,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_
                                color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]);
                                if (fogenabled)
                                {
-                                       float f = VERTEXFOGTABLE(VectorDistance(v, r_shadow_entityeyeorigin));
+                                       float f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
                                        VectorScale(color4f, f, color4f);
                                }
                        }
@@ -1150,7 +1173,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_
                                }
                                if (fogenabled)
                                {
-                                       float f = VERTEXFOGTABLE(VectorDistance(v, r_shadow_entityeyeorigin));
+                                       float f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
                                        VectorScale(color4f, f, color4f);
                                }
                        }
@@ -1184,7 +1207,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_
                                }
                                if (fogenabled)
                                {
-                                       float f = VERTEXFOGTABLE(VectorDistance(v, r_shadow_entityeyeorigin));
+                                       float f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
                                        VectorScale(color4f, f, color4f);
                                }
                        }
@@ -1197,84 +1220,106 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_
 
 // TODO: use glTexGen instead of feeding vertices to texcoordpointer?
 
-static void R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(float *out3f, int numverts, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const vec3_t relativelightorigin)
+static void R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(int numsurfaces, msurface_t **surfacelist)
 {
-       int i;
-       float lightdir[3];
-       for (i = 0;i < numverts;i++, vertex3f += 3, svector3f += 3, tvector3f += 3, normal3f += 3, out3f += 3)
+       int surfacelistindex;
+       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
        {
-               VectorSubtract(relativelightorigin, vertex3f, lightdir);
-               // the cubemap normalizes this for us
-               out3f[0] = DotProduct(svector3f, lightdir);
-               out3f[1] = DotProduct(tvector3f, lightdir);
-               out3f[2] = DotProduct(normal3f, lightdir);
+               const msurface_t *surface = surfacelist[surfacelistindex];
+               int i;
+               float *out3f = rsurface_array_texcoord3f + 3 * surface->num_firstvertex;
+               const float *vertex3f = rsurface_vertex3f + 3 * surface->num_firstvertex;
+               const float *svector3f = rsurface_svector3f + 3 * surface->num_firstvertex;
+               const float *tvector3f = rsurface_tvector3f + 3 * surface->num_firstvertex;
+               const float *normal3f = rsurface_normal3f + 3 * surface->num_firstvertex;
+               float lightdir[3];
+               for (i = 0;i < surface->num_vertices;i++, vertex3f += 3, svector3f += 3, tvector3f += 3, normal3f += 3, out3f += 3)
+               {
+                       VectorSubtract(r_shadow_entitylightorigin, vertex3f, lightdir);
+                       // the cubemap normalizes this for us
+                       out3f[0] = DotProduct(svector3f, lightdir);
+                       out3f[1] = DotProduct(tvector3f, lightdir);
+                       out3f[2] = DotProduct(normal3f, lightdir);
+               }
        }
 }
 
-static void R_Shadow_GenTexCoords_Specular_NormalCubeMap(float *out3f, int numverts, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const vec3_t relativelightorigin, const vec3_t relativeeyeorigin)
+static void R_Shadow_GenTexCoords_Specular_NormalCubeMap(int numsurfaces, msurface_t **surfacelist)
 {
-       int i;
-       float lightdir[3], eyedir[3], halfdir[3];
-       for (i = 0;i < numverts;i++, vertex3f += 3, svector3f += 3, tvector3f += 3, normal3f += 3, out3f += 3)
+       int surfacelistindex;
+       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
        {
-               VectorSubtract(relativelightorigin, vertex3f, lightdir);
-               VectorNormalize(lightdir);
-               VectorSubtract(relativeeyeorigin, vertex3f, eyedir);
-               VectorNormalize(eyedir);
-               VectorAdd(lightdir, eyedir, halfdir);
-               // the cubemap normalizes this for us
-               out3f[0] = DotProduct(svector3f, halfdir);
-               out3f[1] = DotProduct(tvector3f, halfdir);
-               out3f[2] = DotProduct(normal3f, halfdir);
+               const msurface_t *surface = surfacelist[surfacelistindex];
+               int i;
+               float *out3f = rsurface_array_texcoord3f + 3 * surface->num_firstvertex;
+               const float *vertex3f = rsurface_vertex3f + 3 * surface->num_firstvertex;
+               const float *svector3f = rsurface_svector3f + 3 * surface->num_firstvertex;
+               const float *tvector3f = rsurface_tvector3f + 3 * surface->num_firstvertex;
+               const float *normal3f = rsurface_normal3f + 3 * surface->num_firstvertex;
+               float lightdir[3], eyedir[3], halfdir[3];
+               for (i = 0;i < surface->num_vertices;i++, vertex3f += 3, svector3f += 3, tvector3f += 3, normal3f += 3, out3f += 3)
+               {
+                       VectorSubtract(r_shadow_entitylightorigin, vertex3f, lightdir);
+                       VectorNormalize(lightdir);
+                       VectorSubtract(rsurface_modelorg, vertex3f, eyedir);
+                       VectorNormalize(eyedir);
+                       VectorAdd(lightdir, eyedir, halfdir);
+                       // the cubemap normalizes this for us
+                       out3f[0] = DotProduct(svector3f, halfdir);
+                       out3f[1] = DotProduct(tvector3f, halfdir);
+                       out3f[2] = DotProduct(normal3f, halfdir);
+               }
        }
 }
 
-static void R_Shadow_RenderSurfacesLighting_VisibleLighting(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, qboolean dopants, qboolean doshirt)
+static void R_Shadow_RenderSurfacesLighting_VisibleLighting(int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, qboolean dopants, qboolean doshirt)
 {
        // used to display how many times a surface is lit for level design purposes
-       int surfacelistindex;
-       model_t *model = ent->model;
        GL_Color(0.1, 0.025, 0, 1);
        R_Mesh_ColorPointer(NULL);
        R_Mesh_ResetTextureState();
-       RSurf_PrepareVerticesForBatch(ent, texture, r_shadow_entityeyeorigin, false, false, numsurfaces, surfacelist);
-       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
-       {
-               const msurface_t *surface = surfacelist[surfacelistindex];
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
-               GL_LockArrays(0, 0);
-       }
+       RSurf_PrepareVerticesForBatch(false, false, numsurfaces, surfacelist);
+       RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
+       GL_LockArrays(0, 0);
 }
 
-static void R_Shadow_RenderSurfacesLighting_Light_GLSL(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, qboolean dopants, qboolean doshirt)
+static void R_Shadow_RenderSurfacesLighting_Light_GLSL(int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, qboolean dopants, qboolean doshirt)
 {
        // ARB2 GLSL shader path (GFFX5200, Radeon 9500)
-       int surfacelistindex;
-       model_t *model = ent->model;
-       RSurf_PrepareVerticesForBatch(ent, texture, r_shadow_entityeyeorigin, true, true, numsurfaces, surfacelist);
-       R_SetupSurfaceShader(ent, texture, r_shadow_entityeyeorigin, lightcolorbase, false);
-       R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
+       RSurf_PrepareVerticesForBatch(true, true, numsurfaces, surfacelist);
+       R_SetupSurfaceShader(lightcolorbase, false);
+       R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
        R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
        R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
        R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
-       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+       if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
        {
-               const msurface_t *surface = surfacelist[surfacelistindex];
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, model->surfmesh.data_element3i + surface->num_firsttriangle * 3);
+               qglDepthFunc(GL_EQUAL);CHECKGLERROR
        }
+       RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
        GL_LockArrays(0, 0);
+       if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
+       {
+               qglDepthFunc(GL_LEQUAL);CHECKGLERROR
+       }
 }
 
-static void R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t lightcolorbase, rtexture_t *basetexture, float colorscale)
+static void R_Shadow_RenderSurfacesLighting_Light_Dot3_Finalize(int numsurfaces, msurface_t **surfacelist, float r, float g, float b)
 {
+       // shared final code for all the dot3 layers
        int renders;
-       model_t *model = ent->model;
-       float color2[3];
+       GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
+       for (renders = 0;renders < 64 && (r > 0 || g > 0 || b > 0);renders++, r--, g--, b--)
+       {
+               GL_Color(bound(0, r, 1), bound(0, g, 1), bound(0, b, 1), 1);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
+               GL_LockArrays(0, 0);
+       }
+}
+
+static void R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, rtexture_t *basetexture, float colorscale)
+{
        rmeshstate_t m;
-       const int *elements = model->surfmesh.data_element3i + surface->num_firsttriangle * 3;
-       GL_Color(1,1,1,1);
        // colorscale accounts for how much we multiply the brightness
        // during combine.
        //
@@ -1282,6 +1327,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(const entity_
        // performed to get more brightness than otherwise possible.
        //
        // Limit mult to 64 for sanity sake.
+       GL_Color(1,1,1,1);
        if (r_shadow_texture3d.integer && r_shadow_rtlight->currentcubemap != r_texture_whitecube && r_textureunits.integer >= 4)
        {
                // 3 3D combine path (Geforce3, Radeon 8500)
@@ -1290,8 +1336,8 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(const entity_
                m.pointer_texcoord3f[0] = rsurface_vertex3f;
                m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
                m.tex[1] = R_GetTexture(basetexture);
-               m.pointer_texcoord[1] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[1] = texture->currenttexmatrix;
+               m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[1] = rsurface_texture->currenttexmatrix;
                m.texcubemap[2] = R_GetTexture(r_shadow_rtlight->currentcubemap);
                m.pointer_texcoord3f[2] = rsurface_vertex3f;
                m.texmatrix[2] = r_shadow_entitytolight;
@@ -1305,8 +1351,8 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(const entity_
                m.pointer_texcoord3f[0] = rsurface_vertex3f;
                m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
                m.tex[1] = R_GetTexture(basetexture);
-               m.pointer_texcoord[1] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[1] = texture->currenttexmatrix;
+               m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[1] = rsurface_texture->currenttexmatrix;
                GL_BlendFunc(GL_ONE, GL_ONE);
        }
        else if (r_textureunits.integer >= 4 && r_shadow_rtlight->currentcubemap != r_texture_whitecube)
@@ -1320,8 +1366,8 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(const entity_
                m.pointer_texcoord3f[1] = rsurface_vertex3f;
                m.texmatrix[1] = r_shadow_entitytoattenuationz;
                m.tex[2] = R_GetTexture(basetexture);
-               m.pointer_texcoord[2] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[2] = texture->currenttexmatrix;
+               m.pointer_texcoord[2] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[2] = rsurface_texture->currenttexmatrix;
                if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
                {
                        m.texcubemap[3] = R_GetTexture(r_shadow_rtlight->currentcubemap);
@@ -1341,8 +1387,8 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(const entity_
                m.pointer_texcoord3f[1] = rsurface_vertex3f;
                m.texmatrix[1] = r_shadow_entitytoattenuationz;
                m.tex[2] = R_GetTexture(basetexture);
-               m.pointer_texcoord[2] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[2] = texture->currenttexmatrix;
+               m.pointer_texcoord[2] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[2] = rsurface_texture->currenttexmatrix;
                GL_BlendFunc(GL_ONE, GL_ONE);
        }
        else
@@ -1358,14 +1404,14 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(const entity_
                R_Mesh_TextureState(&m);
                GL_ColorMask(0,0,0,1);
                GL_BlendFunc(GL_ONE, GL_ZERO);
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // second pass
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(basetexture);
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
                {
                        m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
@@ -1376,25 +1422,12 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(const entity_
        }
        // this final code is shared
        R_Mesh_TextureState(&m);
-       GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
-       VectorScale(lightcolorbase, colorscale, color2);
-       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-       for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
-       {
-               GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
-       }
-       GL_LockArrays(0, 0);
+       R_Shadow_RenderSurfacesLighting_Light_Dot3_Finalize(numsurfaces, surfacelist, lightcolorbase[0] * colorscale, lightcolorbase[1] * colorscale, lightcolorbase[2] * colorscale);
 }
 
-static void R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t lightcolorbase, rtexture_t *basetexture, rtexture_t *normalmaptexture, float colorscale)
+static void R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, rtexture_t *basetexture, rtexture_t *normalmaptexture, float colorscale)
 {
-       int renders;
-       model_t *model = ent->model;
-       float color2[3];
        rmeshstate_t m;
-       const int *elements = model->surfmesh.data_element3i + surface->num_firsttriangle * 3;
-       GL_Color(1,1,1,1);
        // colorscale accounts for how much we multiply the brightness
        // during combine.
        //
@@ -1402,32 +1435,34 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(const entity_
        // performed to get more brightness than otherwise possible.
        //
        // Limit mult to 64 for sanity sake.
+       GL_Color(1,1,1,1);
+       // generate normalization cubemap texcoords
+       R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(numsurfaces, surfacelist);
        if (r_shadow_texture3d.integer && r_textureunits.integer >= 4)
        {
                // 3/2 3D combine path (Geforce3, Radeon 8500)
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(normalmaptexture);
                m.texcombinergb[0] = GL_REPLACE;
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
                m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
                m.pointer_texcoord3f[1] = rsurface_array_texcoord3f;
-               R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(rsurface_array_texcoord3f + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin);
                m.tex3d[2] = R_GetTexture(r_shadow_attenuation3dtexture);
                m.pointer_texcoord3f[2] = rsurface_vertex3f;
                m.texmatrix[2] = r_shadow_entitytoattenuationxyz;
                R_Mesh_TextureState(&m);
                GL_ColorMask(0,0,0,1);
                GL_BlendFunc(GL_ONE, GL_ZERO);
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // second pass
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(basetexture);
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
                {
                        m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
@@ -1446,29 +1481,28 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(const entity_
                R_Mesh_TextureState(&m);
                GL_ColorMask(0,0,0,1);
                GL_BlendFunc(GL_ONE, GL_ZERO);
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // second pass
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(normalmaptexture);
                m.texcombinergb[0] = GL_REPLACE;
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
                m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
                m.pointer_texcoord3f[1] = rsurface_array_texcoord3f;
-               R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(rsurface_array_texcoord3f + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin);
                R_Mesh_TextureState(&m);
                GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // second pass
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(basetexture);
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
                {
                        m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
@@ -1483,23 +1517,22 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(const entity_
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(normalmaptexture);
                m.texcombinergb[0] = GL_REPLACE;
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
                m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
                m.pointer_texcoord3f[1] = rsurface_array_texcoord3f;
-               R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(rsurface_array_texcoord3f + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin);
                R_Mesh_TextureState(&m);
                GL_ColorMask(0,0,0,1);
                GL_BlendFunc(GL_ONE, GL_ZERO);
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // second pass
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(basetexture);
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
                m.pointer_texcoord3f[1] = rsurface_vertex3f;
                m.texmatrix[1] = r_shadow_entitytoattenuationxyz;
@@ -1511,12 +1544,11 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(const entity_
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(normalmaptexture);
                m.texcombinergb[0] = GL_REPLACE;
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
                m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
                m.pointer_texcoord3f[1] = rsurface_array_texcoord3f;
-               R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(rsurface_array_texcoord3f + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin);
                m.tex[2] = R_GetTexture(r_shadow_attenuation2dtexture);
                m.pointer_texcoord3f[2] = rsurface_vertex3f;
                m.texmatrix[2] = r_shadow_entitytoattenuationxyz;
@@ -1526,14 +1558,14 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(const entity_
                R_Mesh_TextureState(&m);
                GL_ColorMask(0,0,0,1);
                GL_BlendFunc(GL_ONE, GL_ZERO);
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // second pass
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(basetexture);
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
                {
                        m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
@@ -1555,29 +1587,28 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(const entity_
                R_Mesh_TextureState(&m);
                GL_ColorMask(0,0,0,1);
                GL_BlendFunc(GL_ONE, GL_ZERO);
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // second pass
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(normalmaptexture);
                m.texcombinergb[0] = GL_REPLACE;
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
                m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
                m.pointer_texcoord3f[1] = rsurface_array_texcoord3f;
-               R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(rsurface_array_texcoord3f + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin);
                R_Mesh_TextureState(&m);
                GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // second pass
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(basetexture);
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
                {
                        m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
@@ -1588,73 +1619,62 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(const entity_
        }
        // this final code is shared
        R_Mesh_TextureState(&m);
-       GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
-       VectorScale(lightcolorbase, colorscale, color2);
-       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-       for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
-       {
-               GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
-       }
-       GL_LockArrays(0, 0);
+       R_Shadow_RenderSurfacesLighting_Light_Dot3_Finalize(numsurfaces, surfacelist, lightcolorbase[0] * colorscale, lightcolorbase[1] * colorscale, lightcolorbase[2] * colorscale);
 }
 
-static void R_Shadow_RenderSurfacesLighting_Light_Dot3_SpecularPass(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t lightcolorbase, rtexture_t *glosstexture, rtexture_t *normalmaptexture, float colorscale)
+static void R_Shadow_RenderSurfacesLighting_Light_Dot3_SpecularPass(int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, rtexture_t *glosstexture, rtexture_t *normalmaptexture, float colorscale)
 {
-       int renders;
-       model_t *model = ent->model;
-       float color2[3];
        rmeshstate_t m;
-       const int *elements = model->surfmesh.data_element3i + surface->num_firsttriangle * 3;
        // FIXME: detect blendsquare!
        //if (!gl_support_blendsquare)
        //      return;
        GL_Color(1,1,1,1);
-       if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_rtlight->currentcubemap != r_texture_whitecube /* && gl_support_blendsquare*/) // FIXME: detect blendsquare!
+       // generate normalization cubemap texcoords
+       R_Shadow_GenTexCoords_Specular_NormalCubeMap(numsurfaces, surfacelist);
+       if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_rtlight->currentcubemap != r_texture_whitecube)
        {
                // 2/0/0/1/2 3D combine blendsquare path
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(normalmaptexture);
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
                m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
                m.pointer_texcoord3f[1] = rsurface_array_texcoord3f;
-               R_Shadow_GenTexCoords_Specular_NormalCubeMap(rsurface_array_texcoord3f + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin, r_shadow_entityeyeorigin);
                R_Mesh_TextureState(&m);
                GL_ColorMask(0,0,0,1);
                // this squares the result
                GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO);
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // second and third pass
                R_Mesh_ResetTextureState();
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                // square alpha in framebuffer a few times to make it shiny
                GL_BlendFunc(GL_ZERO, GL_DST_ALPHA);
                // these comments are a test run through this math for intensity 0.5
                // 0.5 * 0.5 = 0.25 (done by the BlendFunc earlier)
                // 0.25 * 0.25 = 0.0625 (this is another pass)
                // 0.0625 * 0.0625 = 0.00390625 (this is another pass)
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // fourth pass
                memset(&m, 0, sizeof(m));
                m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
                m.pointer_texcoord3f[0] = rsurface_vertex3f;
                m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
                R_Mesh_TextureState(&m);
                GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // fifth pass
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(glosstexture);
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
                {
                        m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
@@ -1668,36 +1688,35 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_SpecularPass(const entity
                // 2/0/0/2 3D combine blendsquare path
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(normalmaptexture);
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
                m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
                m.pointer_texcoord3f[1] = rsurface_array_texcoord3f;
-               R_Shadow_GenTexCoords_Specular_NormalCubeMap(rsurface_array_texcoord3f + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin, r_shadow_entityeyeorigin);
                R_Mesh_TextureState(&m);
                GL_ColorMask(0,0,0,1);
                // this squares the result
                GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO);
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // second and third pass
                R_Mesh_ResetTextureState();
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                // square alpha in framebuffer a few times to make it shiny
                GL_BlendFunc(GL_ZERO, GL_DST_ALPHA);
                // these comments are a test run through this math for intensity 0.5
                // 0.5 * 0.5 = 0.25 (done by the BlendFunc earlier)
                // 0.25 * 0.25 = 0.0625 (this is another pass)
                // 0.0625 * 0.0625 = 0.00390625 (this is another pass)
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // fourth pass
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(glosstexture);
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
                m.pointer_texcoord3f[1] = rsurface_vertex3f;
                m.texmatrix[1] = r_shadow_entitytoattenuationxyz;
@@ -1708,32 +1727,31 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_SpecularPass(const entity
                // 2/0/0/2/2 2D combine blendsquare path
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(normalmaptexture);
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
                m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
                m.pointer_texcoord3f[1] = rsurface_array_texcoord3f;
-               R_Shadow_GenTexCoords_Specular_NormalCubeMap(rsurface_array_texcoord3f + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin, r_shadow_entityeyeorigin);
                R_Mesh_TextureState(&m);
                GL_ColorMask(0,0,0,1);
                // this squares the result
                GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO);
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // second and third pass
                R_Mesh_ResetTextureState();
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                // square alpha in framebuffer a few times to make it shiny
                GL_BlendFunc(GL_ZERO, GL_DST_ALPHA);
                // these comments are a test run through this math for intensity 0.5
                // 0.5 * 0.5 = 0.25 (done by the BlendFunc earlier)
                // 0.25 * 0.25 = 0.0625 (this is another pass)
                // 0.0625 * 0.0625 = 0.00390625 (this is another pass)
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // fourth pass
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
                m.pointer_texcoord3f[0] = rsurface_vertex3f;
@@ -1743,14 +1761,14 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_SpecularPass(const entity
                m.texmatrix[1] = r_shadow_entitytoattenuationz;
                R_Mesh_TextureState(&m);
                GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+               RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
                GL_LockArrays(0, 0);
 
+               // fifth pass
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(glosstexture);
-               m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
-               m.texmatrix[0] = texture->currenttexmatrix;
+               m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+               m.texmatrix[0] = rsurface_texture->currenttexmatrix;
                if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
                {
                        m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
@@ -1759,129 +1777,153 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_SpecularPass(const entity
                }
                GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
        }
+       // this final code is shared
        R_Mesh_TextureState(&m);
-       GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
-       VectorScale(lightcolorbase, colorscale, color2);
-       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-       for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
-       {
-               GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
-       }
-       GL_LockArrays(0, 0);
+       R_Shadow_RenderSurfacesLighting_Light_Dot3_Finalize(numsurfaces, surfacelist, lightcolorbase[0] * colorscale, lightcolorbase[1] * colorscale, lightcolorbase[2] * colorscale);
 }
 
-static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, qboolean dopants, qboolean doshirt)
+static void R_Shadow_RenderSurfacesLighting_Light_Dot3(int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, qboolean dopants, qboolean doshirt)
 {
        // ARB path (any Geforce, any Radeon)
-       int surfacelistindex;
        qboolean doambient = r_shadow_rtlight->ambientscale > 0;
        qboolean dodiffuse = r_shadow_rtlight->diffusescale > 0;
        qboolean dospecular = specularscale > 0;
        if (!doambient && !dodiffuse && !dospecular)
                return;
-       RSurf_PrepareVerticesForBatch(ent, texture, r_shadow_entityeyeorigin, true, true, numsurfaces, surfacelist);
+       RSurf_PrepareVerticesForBatch(true, true, numsurfaces, surfacelist);
        R_Mesh_ColorPointer(NULL);
-       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+       if (doambient)
+               R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(numsurfaces, surfacelist, lightcolorbase, basetexture, r_shadow_rtlight->ambientscale);
+       if (dodiffuse)
+               R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(numsurfaces, surfacelist, lightcolorbase, basetexture, normalmaptexture, r_shadow_rtlight->diffusescale);
+       if (dopants)
        {
-               const msurface_t *surface = surfacelist[surfacelistindex];
                if (doambient)
-                       R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(ent, texture, surface, lightcolorbase, basetexture, r_shadow_rtlight->ambientscale);
+                       R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(numsurfaces, surfacelist, lightcolorpants, pantstexture, r_shadow_rtlight->ambientscale);
                if (dodiffuse)
-                       R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(ent, texture, surface, lightcolorbase, basetexture, normalmaptexture, r_shadow_rtlight->diffusescale);
-               if (dopants)
-               {
-                       if (doambient)
-                               R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(ent, texture, surface, lightcolorpants, pantstexture, r_shadow_rtlight->ambientscale);
-                       if (dodiffuse)
-                               R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(ent, texture, surface, lightcolorpants, pantstexture, normalmaptexture, r_shadow_rtlight->diffusescale);
-               }
-               if (doshirt)
-               {
-                       if (doambient)
-                               R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(ent, texture, surface, lightcolorshirt, shirttexture, r_shadow_rtlight->ambientscale);
-                       if (dodiffuse)
-                               R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(ent, texture, surface, lightcolorshirt, shirttexture, normalmaptexture, r_shadow_rtlight->diffusescale);
-               }
-               if (dospecular)
-                       R_Shadow_RenderSurfacesLighting_Light_Dot3_SpecularPass(ent, texture, surface, lightcolorbase, glosstexture, normalmaptexture, specularscale);
+                       R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(numsurfaces, surfacelist, lightcolorpants, pantstexture, normalmaptexture, r_shadow_rtlight->diffusescale);
        }
+       if (doshirt)
+       {
+               if (doambient)
+                       R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(numsurfaces, surfacelist, lightcolorshirt, shirttexture, r_shadow_rtlight->ambientscale);
+               if (dodiffuse)
+                       R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(numsurfaces, surfacelist, lightcolorshirt, shirttexture, normalmaptexture, r_shadow_rtlight->diffusescale);
+       }
+       if (dospecular)
+               R_Shadow_RenderSurfacesLighting_Light_Dot3_SpecularPass(numsurfaces, surfacelist, lightcolorbase, glosstexture, normalmaptexture, specularscale);
 }
 
-void R_Shadow_RenderSurfacesLighting_Light_Vertex_Pass(const model_t *model, const msurface_t *surface, vec3_t diffusecolor2, vec3_t ambientcolor2)
+void R_Shadow_RenderSurfacesLighting_Light_Vertex_Pass(const model_t *model, int numsurfaces, msurface_t **surfacelist, vec3_t diffusecolor2, vec3_t ambientcolor2)
 {
+       int surfacelistindex;
        int renders;
-       const int *elements = model->surfmesh.data_element3i + surface->num_firsttriangle * 3;
-       R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(surface, diffusecolor2, ambientcolor2);
-       for (renders = 0;renders < 64 && (ambientcolor2[0] > renders || ambientcolor2[1] > renders || ambientcolor2[2] > renders || diffusecolor2[0] > renders || diffusecolor2[1] > renders || diffusecolor2[2] > renders);renders++)
+       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+       {
+               const msurface_t *surface = surfacelist[surfacelistindex];
+               R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(surface, diffusecolor2, ambientcolor2);
+       }
+       for (renders = 0;renders < 64;renders++)
        {
-               int i;
-               float *c;
-#if 1
-               // due to low fillrate on the cards this vertex lighting path is
-               // designed for, we manually cull all triangles that do not
-               // contain a lit vertex
-               int draw;
                const int *e;
+               int stop;
+               int firstvertex;
+               int lastvertex;
                int newnumtriangles;
                int *newe;
                int newelements[3072];
-               draw = false;
+               stop = true;
+               firstvertex = 0;
+               lastvertex = 0;
                newnumtriangles = 0;
                newe = newelements;
-               for (i = 0, e = elements;i < surface->num_triangles;i++, e += 3)
-               {
-                       if (newnumtriangles >= 1024)
-                       {
-                               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, newnumtriangles, newelements);
-                               GL_LockArrays(0, 0);
-                               newnumtriangles = 0;
-                               newe = newelements;
-                       }
-                       if (VectorLength2(rsurface_array_color4f + e[0] * 4) + VectorLength2(rsurface_array_color4f + e[1] * 4) + VectorLength2(rsurface_array_color4f + e[2] * 4) >= 0.01)
+               for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+               {
+                       const msurface_t *surface = surfacelist[surfacelistindex];
+                       const int *elements = rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3;
+                       int i;
+                       // due to low fillrate on the cards this vertex lighting path is
+                       // designed for, we manually cull all triangles that do not
+                       // contain a lit vertex
+                       // this builds batches of triangles from multiple surfaces and
+                       // renders them at once
+                       for (i = 0, e = elements;i < surface->num_triangles;i++, e += 3)
                        {
-                               newe[0] = e[0];
-                               newe[1] = e[1];
-                               newe[2] = e[2];
-                               newnumtriangles++;
-                               newe += 3;
-                               draw = true;
+                               if (VectorLength2(rsurface_array_color4f + e[0] * 4) + VectorLength2(rsurface_array_color4f + e[1] * 4) + VectorLength2(rsurface_array_color4f + e[2] * 4) >= 0.01)
+                               {
+                                       if (newnumtriangles)
+                                       {
+                                               firstvertex = min(firstvertex, e[0]);
+                                               lastvertex = max(lastvertex, e[0]);
+                                       }
+                                       else
+                                       {
+                                               firstvertex = e[0];
+                                               lastvertex = e[0];
+                                       }
+                                       firstvertex = min(firstvertex, e[1]);
+                                       lastvertex = max(lastvertex, e[1]);
+                                       firstvertex = min(firstvertex, e[2]);
+                                       lastvertex = max(lastvertex, e[2]);
+                                       newe[0] = e[0];
+                                       newe[1] = e[1];
+                                       newe[2] = e[2];
+                                       newnumtriangles++;
+                                       newe += 3;
+                                       if (newnumtriangles >= 1024)
+                                       {
+                                               GL_LockArrays(firstvertex, lastvertex - firstvertex + 1);
+                                               R_Mesh_Draw(firstvertex, lastvertex - firstvertex + 1, newnumtriangles, newelements);
+                                               newnumtriangles = 0;
+                                               newe = newelements;
+                                               stop = false;
+                                       }
+                               }
                        }
                }
                if (newnumtriangles >= 1)
                {
-                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, newnumtriangles, newelements);
-                       GL_LockArrays(0, 0);
-                       draw = true;
+                       GL_LockArrays(firstvertex, lastvertex - firstvertex + 1);
+                       R_Mesh_Draw(firstvertex, lastvertex - firstvertex + 1, newnumtriangles, newelements);
+                       stop = false;
                }
-               if (!draw)
-                       break;
-#else
-               for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
-                       if (VectorLength2(c))
-                               goto goodpass;
-               break;
-goodpass:
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
                GL_LockArrays(0, 0);
-#endif
+               // if we couldn't find any lit triangles, exit early
+               if (stop)
+                       break;
                // now reduce the intensity for the next overbright pass
-               for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
-               {
-                       c[0] = max(0, c[0] - 1);
-                       c[1] = max(0, c[1] - 1);
-                       c[2] = max(0, c[2] - 1);
+               // we have to clamp to 0 here incase the drivers have improper
+               // handling of negative colors
+               // (some old drivers even have improper handling of >1 color)
+               stop = true;
+               for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+               {
+                       int i;
+                       float *c;
+                       const msurface_t *surface = surfacelist[surfacelistindex];
+                       for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
+                       {
+                               if (c[0] > 1 || c[1] > 1 || c[2] > 1)
+                               {
+                                       c[0] = max(0, c[0] - 1);
+                                       c[1] = max(0, c[1] - 1);
+                                       c[2] = max(0, c[2] - 1);
+                                       stop = false;
+                               }
+                               else
+                                       VectorClear(c);
+                       }
                }
+               // another check...
+               if (stop)
+                       break;
        }
 }
 
-static void R_Shadow_RenderSurfacesLighting_Light_Vertex(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, qboolean dopants, qboolean doshirt)
+static void R_Shadow_RenderSurfacesLighting_Light_Vertex(int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, qboolean dopants, qboolean doshirt)
 {
-       int surfacelistindex;
-       model_t *model = ent->model;
+       // OpenGL 1.1 path (anything)
+       model_t *model = rsurface_entity->model;
        float ambientcolorbase[3], diffusecolorbase[3];
        float ambientcolorpants[3], diffusecolorpants[3];
        float ambientcolorshirt[3], diffusecolorshirt[3];
@@ -1896,8 +1938,8 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex(const entity_render_t *
        R_Mesh_ColorPointer(rsurface_array_color4f);
        memset(&m, 0, sizeof(m));
        m.tex[0] = R_GetTexture(basetexture);
-       m.texmatrix[0] = texture->currenttexmatrix;
-       m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
+       m.texmatrix[0] = rsurface_texture->currenttexmatrix;
+       m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
        if (r_textureunits.integer >= 2)
        {
                // voodoo2 or TNT
@@ -1913,73 +1955,72 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex(const entity_render_t *
                }
        }
        R_Mesh_TextureState(&m);
-       RSurf_PrepareVerticesForBatch(ent, texture, r_shadow_entityeyeorigin, true, false, numsurfaces, surfacelist);
-       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+       RSurf_PrepareVerticesForBatch(true, false, numsurfaces, surfacelist);
+       R_Mesh_TexBind(0, R_GetTexture(basetexture));
+       R_Shadow_RenderSurfacesLighting_Light_Vertex_Pass(model, numsurfaces, surfacelist, diffusecolorbase, ambientcolorbase);
+       if (dopants)
        {
-               const msurface_t *surface = surfacelist[surfacelistindex];
-               // OpenGL 1.1 path (anything)
-               R_Mesh_TexBind(0, R_GetTexture(basetexture));
-               R_Shadow_RenderSurfacesLighting_Light_Vertex_Pass(model, surface, diffusecolorbase, ambientcolorbase);
-               if (dopants)
-               {
-                       R_Mesh_TexBind(0, R_GetTexture(pantstexture));
-                       R_Shadow_RenderSurfacesLighting_Light_Vertex_Pass(model, surface, diffusecolorpants, ambientcolorpants);
-               }
-               if (doshirt)
-               {
-                       R_Mesh_TexBind(0, R_GetTexture(shirttexture));
-                       R_Shadow_RenderSurfacesLighting_Light_Vertex_Pass(model, surface, diffusecolorshirt, ambientcolorshirt);
-               }
+               R_Mesh_TexBind(0, R_GetTexture(pantstexture));
+               R_Shadow_RenderSurfacesLighting_Light_Vertex_Pass(model, numsurfaces, surfacelist, diffusecolorpants, ambientcolorpants);
+       }
+       if (doshirt)
+       {
+               R_Mesh_TexBind(0, R_GetTexture(shirttexture));
+               R_Shadow_RenderSurfacesLighting_Light_Vertex_Pass(model, numsurfaces, surfacelist, diffusecolorshirt, ambientcolorshirt);
        }
 }
 
-void R_Shadow_RenderSurfacesLighting(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist)
+void R_Shadow_RenderSurfacesLighting(int numsurfaces, msurface_t **surfacelist)
 {
        // FIXME: support MATERIALFLAG_NODEPTHTEST
        vec3_t lightcolorbase, lightcolorpants, lightcolorshirt;
        // calculate colors to render this texture with
-       lightcolorbase[0] = r_shadow_rtlight->currentcolor[0] * ent->colormod[0] * texture->currentalpha;
-       lightcolorbase[1] = r_shadow_rtlight->currentcolor[1] * ent->colormod[1] * texture->currentalpha;
-       lightcolorbase[2] = r_shadow_rtlight->currentcolor[2] * ent->colormod[2] * texture->currentalpha;
-       if ((r_shadow_rtlight->ambientscale + r_shadow_rtlight->diffusescale) * VectorLength2(lightcolorbase) + (r_shadow_rtlight->specularscale * texture->specularscale) * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
+       lightcolorbase[0] = r_shadow_rtlight->currentcolor[0] * rsurface_entity->colormod[0] * rsurface_texture->currentalpha;
+       lightcolorbase[1] = r_shadow_rtlight->currentcolor[1] * rsurface_entity->colormod[1] * rsurface_texture->currentalpha;
+       lightcolorbase[2] = r_shadow_rtlight->currentcolor[2] * rsurface_entity->colormod[2] * rsurface_texture->currentalpha;
+       if ((r_shadow_rtlight->ambientscale + r_shadow_rtlight->diffusescale) * VectorLength2(lightcolorbase) + (r_shadow_rtlight->specularscale * rsurface_texture->specularscale) * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
                return;
-       if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
-               qglDisable(GL_CULL_FACE);
+       if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
+       {
+               qglDisable(GL_CULL_FACE);CHECKGLERROR
+       }
        else
-               qglEnable(GL_CULL_FACE);
-       if (texture->colormapping)
        {
-               qboolean dopants = texture->skin.pants != NULL && VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f);
-               qboolean doshirt = texture->skin.shirt != NULL && VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
+               qglEnable(GL_CULL_FACE);CHECKGLERROR
+       }
+       if (rsurface_texture->colormapping)
+       {
+               qboolean dopants = rsurface_texture->skin.pants != NULL && VectorLength2(rsurface_entity->colormap_pantscolor) >= (1.0f / 1048576.0f);
+               qboolean doshirt = rsurface_texture->skin.shirt != NULL && VectorLength2(rsurface_entity->colormap_shirtcolor) >= (1.0f / 1048576.0f);
                if (dopants)
                {
-                       lightcolorpants[0] = lightcolorbase[0] * ent->colormap_pantscolor[0];
-                       lightcolorpants[1] = lightcolorbase[1] * ent->colormap_pantscolor[1];
-                       lightcolorpants[2] = lightcolorbase[2] * ent->colormap_pantscolor[2];
+                       lightcolorpants[0] = lightcolorbase[0] * rsurface_entity->colormap_pantscolor[0];
+                       lightcolorpants[1] = lightcolorbase[1] * rsurface_entity->colormap_pantscolor[1];
+                       lightcolorpants[2] = lightcolorbase[2] * rsurface_entity->colormap_pantscolor[2];
                }
                else
                        VectorClear(lightcolorpants);
                if (doshirt)
                {
-                       lightcolorshirt[0] = lightcolorbase[0] * ent->colormap_shirtcolor[0];
-                       lightcolorshirt[1] = lightcolorbase[1] * ent->colormap_shirtcolor[1];
-                       lightcolorshirt[2] = lightcolorbase[2] * ent->colormap_shirtcolor[2];
+                       lightcolorshirt[0] = lightcolorbase[0] * rsurface_entity->colormap_shirtcolor[0];
+                       lightcolorshirt[1] = lightcolorbase[1] * rsurface_entity->colormap_shirtcolor[1];
+                       lightcolorshirt[2] = lightcolorbase[2] * rsurface_entity->colormap_shirtcolor[2];
                }
                else
                        VectorClear(lightcolorshirt);
                switch (r_shadow_rendermode)
                {
                case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
-                       R_Shadow_RenderSurfacesLighting_VisibleLighting(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, texture->basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, dopants, doshirt);
+                       R_Shadow_RenderSurfacesLighting_VisibleLighting(numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, rsurface_texture->basetexture, rsurface_texture->skin.pants, rsurface_texture->skin.shirt, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, dopants, doshirt);
                        break;
                case R_SHADOW_RENDERMODE_LIGHT_GLSL:
-                       R_Shadow_RenderSurfacesLighting_Light_GLSL(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, texture->basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, dopants, doshirt);
+                       R_Shadow_RenderSurfacesLighting_Light_GLSL(numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, rsurface_texture->basetexture, rsurface_texture->skin.pants, rsurface_texture->skin.shirt, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, dopants, doshirt);
                        break;
                case R_SHADOW_RENDERMODE_LIGHT_DOT3:
-                       R_Shadow_RenderSurfacesLighting_Light_Dot3(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, texture->basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, dopants, doshirt);
+                       R_Shadow_RenderSurfacesLighting_Light_Dot3(numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, rsurface_texture->basetexture, rsurface_texture->skin.pants, rsurface_texture->skin.shirt, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, dopants, doshirt);
                        break;
                case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
-                       R_Shadow_RenderSurfacesLighting_Light_Vertex(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, texture->basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, dopants, doshirt);
+                       R_Shadow_RenderSurfacesLighting_Light_Vertex(numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, rsurface_texture->basetexture, rsurface_texture->skin.pants, rsurface_texture->skin.shirt, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, dopants, doshirt);
                        break;
                default:
                        Con_Printf("R_Shadow_RenderSurfacesLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
@@ -1991,16 +2032,16 @@ void R_Shadow_RenderSurfacesLighting(const entity_render_t *ent, const texture_t
                switch (r_shadow_rendermode)
                {
                case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
-                       R_Shadow_RenderSurfacesLighting_VisibleLighting(ent, texture, numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, texture->basetexture, r_texture_black, r_texture_black, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, false, false);
+                       R_Shadow_RenderSurfacesLighting_VisibleLighting(numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, rsurface_texture->basetexture, r_texture_black, r_texture_black, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, false, false);
                        break;
                case R_SHADOW_RENDERMODE_LIGHT_GLSL:
-                       R_Shadow_RenderSurfacesLighting_Light_GLSL(ent, texture, numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, texture->basetexture, r_texture_black, r_texture_black, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, false, false);
+                       R_Shadow_RenderSurfacesLighting_Light_GLSL(numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, rsurface_texture->basetexture, r_texture_black, r_texture_black, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, false, false);
                        break;
                case R_SHADOW_RENDERMODE_LIGHT_DOT3:
-                       R_Shadow_RenderSurfacesLighting_Light_Dot3(ent, texture, numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, texture->basetexture, r_texture_black, r_texture_black, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, false, false);
+                       R_Shadow_RenderSurfacesLighting_Light_Dot3(numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, rsurface_texture->basetexture, r_texture_black, r_texture_black, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, false, false);
                        break;
                case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
-                       R_Shadow_RenderSurfacesLighting_Light_Vertex(ent, texture, numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, texture->basetexture, r_texture_black, r_texture_black, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, false, false);
+                       R_Shadow_RenderSurfacesLighting_Light_Vertex(numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, rsurface_texture->basetexture, r_texture_black, r_texture_black, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, false, false);
                        break;
                default:
                        Con_Printf("R_Shadow_RenderSurfacesLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
@@ -2160,6 +2201,7 @@ void R_Shadow_DrawEntityShadow(entity_render_t *ent, int numsurfaces, int *surfa
                {
                        shadowmesh_t *mesh;
                        R_Mesh_Matrix(&ent->matrix);
+                       CHECKGLERROR
                        for (mesh = r_shadow_rtlight->static_meshchain_shadow;mesh;mesh = mesh->next)
                        {
                                renderstats.lights_shadowtriangles += mesh->numtriangles;
@@ -2168,16 +2210,17 @@ void R_Shadow_DrawEntityShadow(entity_render_t *ent, int numsurfaces, int *surfa
                                if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCIL)
                                {
                                        // decrement stencil if backface is behind depthbuffer
-                                       qglCullFace(GL_BACK); // quake is backwards, this culls front faces
-                                       qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
+                                       qglCullFace(GL_BACK);CHECKGLERROR // quake is backwards, this culls front faces
+                                       qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
                                        R_Mesh_Draw(0, mesh->numverts, mesh->numtriangles, mesh->element3i);
                                        // increment stencil if frontface is behind depthbuffer
-                                       qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
-                                       qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
+                                       qglCullFace(GL_FRONT);CHECKGLERROR // quake is backwards, this culls back faces
+                                       qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
                                }
                                R_Mesh_Draw(0, mesh->numverts, mesh->numtriangles, mesh->element3i);
                                GL_LockArrays(0, 0);
                        }
+                       CHECKGLERROR
                }
                else if (numsurfaces)
                {
@@ -2203,12 +2246,13 @@ void R_Shadow_DrawEntityShadow(entity_render_t *ent, int numsurfaces, int *surfa
 void R_Shadow_SetupEntityLight(const entity_render_t *ent)
 {
        // set up properties for rendering light onto this entity
+       RSurf_ActiveEntity(ent, true, true);
        Matrix4x4_Concat(&r_shadow_entitytolight, &r_shadow_rtlight->matrix_worldtolight, &ent->matrix);
        Matrix4x4_Concat(&r_shadow_entitytoattenuationxyz, &matrix_attenuationxyz, &r_shadow_entitytolight);
        Matrix4x4_Concat(&r_shadow_entitytoattenuationz, &matrix_attenuationz, &r_shadow_entitytolight);
        Matrix4x4_Transform(&ent->inversematrix, r_shadow_rtlight->shadoworigin, r_shadow_entitylightorigin);
-       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, r_shadow_entityeyeorigin);
-       R_Mesh_Matrix(&ent->matrix);
+       if (r_shadow_lightingrendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL)
+               R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
 }
 
 void R_Shadow_DrawEntityLight(entity_render_t *ent, int numsurfaces, int *surfacelist)
@@ -2613,14 +2657,17 @@ void R_Shadow_SelectLight(dlight_t *light)
                r_shadow_selectedlight->selected = true;
 }
 
-void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
+       // this is never batched (there can be only one)
        float scale = r_editlights_cursorgrid.value * 0.5f;
        R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_crosshairs[1]->tex, NULL, false, r_editlights_cursorlocation, r_viewright, r_viewup, scale, -scale, -scale, scale, 1, 1, 1, 0.5f);
 }
 
-void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
+       // this is never batched (due to the ent parameter changing every time)
+       // so numsurfaces == 1 and surfacelist[0] == lightnumber
        float intensity;
        const dlight_t *light = (dlight_t *)ent;
        intensity = 0.5;
@@ -2628,7 +2675,7 @@ void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, in
                intensity = 0.75 + 0.25 * sin(realtime * M_PI * 4.0);
        if (!light->shadow)
                intensity *= 0.5f;
-       R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_crosshairs[surfacenumber]->tex, NULL, false, light->origin, r_viewright, r_viewup, 8, -8, -8, 8, intensity, intensity, intensity, 0.5);
+       R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_crosshairs[surfacelist[0]]->tex, NULL, false, light->origin, r_viewright, r_viewup, 8, -8, -8, 8, intensity, intensity, intensity, 0.5);
 }
 
 void R_Shadow_DrawLightSprites(void)