]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
two more 4x3 modes
[xonotic/darkplaces.git] / r_shadow.c
index 4a4eae3d1420454e19bccccd405b643af3b57811..88bc073587445478ce9656fe991536ed5a4075d2 100644 (file)
@@ -1424,7 +1424,7 @@ extern float *rsurface_tvector3f;
 extern float *rsurface_normal3f;
 extern void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg);
 
-static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_t *surface, const float *diffusecolor, const float *ambientcolor, float reduce)
+static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_t *surface, const float *diffusecolor, const float *ambientcolor)
 {
        int numverts = surface->num_vertices;
        float *vertex3f = rsurface_vertex3f + 3 * surface->num_firstvertex;
@@ -1440,9 +1440,9 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_
                        if ((dot = DotProduct(n, v)) < 0)
                        {
                                shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
-                               color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) - reduce;
-                               color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) - reduce;
-                               color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) - reduce;
+                               color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]);
+                               color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]);
+                               color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]);
                                if (fogenabled)
                                {
                                        float f = VERTEXFOGTABLE(VectorDistance(v, r_shadow_entityeyeorigin));
@@ -1466,15 +1466,15 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_
                                if ((dot = DotProduct(n, v)) < 0)
                                {
                                        shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
-                                       color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity - reduce;
-                                       color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity - reduce;
-                                       color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity - reduce;
+                                       color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
+                                       color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
+                                       color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
                                }
                                else
                                {
-                                       color4f[0] = ambientcolor[0] * distintensity - reduce;
-                                       color4f[1] = ambientcolor[1] * distintensity - reduce;
-                                       color4f[2] = ambientcolor[2] * distintensity - reduce;
+                                       color4f[0] = ambientcolor[0] * distintensity;
+                                       color4f[1] = ambientcolor[1] * distintensity;
+                                       color4f[2] = ambientcolor[2] * distintensity;
                                }
                                if (fogenabled)
                                {
@@ -1500,15 +1500,15 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_
                                if ((dot = DotProduct(n, v)) < 0)
                                {
                                        shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
-                                       color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity - reduce;
-                                       color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity - reduce;
-                                       color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity - reduce;
+                                       color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
+                                       color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
+                                       color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
                                }
                                else
                                {
-                                       color4f[0] = ambientcolor[0] * distintensity - reduce;
-                                       color4f[1] = ambientcolor[1] * distintensity - reduce;
-                                       color4f[2] = ambientcolor[2] * distintensity - reduce;
+                                       color4f[0] = ambientcolor[0] * distintensity;
+                                       color4f[1] = ambientcolor[1] * distintensity;
+                                       color4f[2] = ambientcolor[2] * distintensity;
                                }
                                if (fogenabled)
                                {
@@ -1662,8 +1662,8 @@ static void R_Shadow_RenderSurfacesLighting_Light_GLSL(const entity_render_t *en
        {
                R_Mesh_TexBind(5, R_GetTexture(pantstexture));
                R_Mesh_TexBind(6, R_GetTexture(shirttexture));
-               qglUniform3fARB(qglGetUniformLocationARB(r_shadow_lightprog, "Color_Pants"), lightcolorpants[0], lightcolorpants[1], lightcolorpants[2]);CHECKGLERROR
-               qglUniform3fARB(qglGetUniformLocationARB(r_shadow_lightprog, "Color_Shirt"), lightcolorshirt[0], lightcolorshirt[1], lightcolorshirt[2]);CHECKGLERROR
+               qglUniform3fARB(qglGetUniformLocationARB(r_shadow_lightprog, "Color_Pants"), ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);CHECKGLERROR
+               qglUniform3fARB(qglGetUniformLocationARB(r_shadow_lightprog, "Color_Shirt"), ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);CHECKGLERROR
        }
        if (r_shadow_lightpermutation & SHADERPERMUTATION_FOG)
        {
@@ -1704,727 +1704,818 @@ static void R_Shadow_RenderSurfacesLighting_Light_GLSL(const entity_render_t *en
        }
 }
 
-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)
+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)
 {
-       // ARB path (any Geforce, any Radeon)
-       int surfacelistindex;
        int renders;
-       float color2[3], colorscale;
+       float color2[3];
        rmeshstate_t m;
-       qboolean doambientbase = r_shadow_rtlight->ambientscale * VectorLength2(lightcolorbase) > 0.00001 && basetexture != r_texture_black;
-       qboolean dodiffusebase = r_shadow_rtlight->diffusescale * VectorLength2(lightcolorbase) > 0.00001 && basetexture != r_texture_black;
-       qboolean doambientpants = r_shadow_rtlight->ambientscale * VectorLength2(lightcolorpants) > 0.00001 && pantstexture != r_texture_black;
-       qboolean dodiffusepants = r_shadow_rtlight->diffusescale * VectorLength2(lightcolorpants) > 0.00001 && pantstexture != r_texture_black;
-       qboolean doambientshirt = r_shadow_rtlight->ambientscale * VectorLength2(lightcolorshirt) > 0.00001 && shirttexture != r_texture_black;
-       qboolean dodiffuseshirt = r_shadow_rtlight->diffusescale * VectorLength2(lightcolorshirt) > 0.00001 && shirttexture != r_texture_black;
-       qboolean dospecular = specularscale * VectorLength2(lightcolorbase) > 0.00001 && glosstexture != r_texture_black;
-       // TODO: add direct pants/shirt rendering
-       if (doambientpants || dodiffusepants)
-               R_Shadow_RenderSurfacesLighting_Light_Dot3(ent, texture, numsurfaces, surfacelist, lightcolorpants, vec3_origin, vec3_origin, pantstexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0);
-       if (doambientshirt || dodiffuseshirt)
-               R_Shadow_RenderSurfacesLighting_Light_Dot3(ent, texture, numsurfaces, surfacelist, lightcolorshirt, vec3_origin, vec3_origin, shirttexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0);
-       if (!doambientbase && !dodiffusebase && !dospecular)
-               return;
-       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
-       {
-               const msurface_t *surface = surfacelist[surfacelistindex];
-               const int *elements = surface->groupmesh->data_element3i + surface->num_firsttriangle * 3;
-               RSurf_SetVertexPointer(ent, texture, surface, r_shadow_entityeyeorigin);
-               if (!rsurface_svector3f)
-               {
-                       rsurface_svector3f = varray_svector3f;
-                       rsurface_tvector3f = varray_tvector3f;
-                       rsurface_normal3f = varray_normal3f;
-                       Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
-               }
-               if (doambientbase)
-               {
-                       GL_Color(1,1,1,1);
-                       colorscale = r_shadow_rtlight->ambientscale;
-                       // colorscale accounts for how much we multiply the brightness
-                       // during combine.
-                       //
-                       // mult is how many times the final pass of the lighting will be
-                       // performed to get more brightness than otherwise possible.
-                       //
-                       // Limit mult to 64 for sanity sake.
-                       if (r_shadow_texture3d.integer && r_shadow_rtlight->currentcubemap != r_texture_whitecube && r_textureunits.integer >= 4)
-                       {
-                               // 3 3D combine path (Geforce3, Radeon 8500)
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
+       const int *elements = surface->groupmesh->data_element3i + surface->num_firsttriangle * 3;
+       GL_Color(1,1,1,1);
+       // colorscale accounts for how much we multiply the brightness
+       // during combine.
+       //
+       // mult is how many times the final pass of the lighting will be
+       // performed to get more brightness than otherwise possible.
+       //
+       // Limit mult to 64 for sanity sake.
+       if (r_shadow_texture3d.integer && r_shadow_rtlight->currentcubemap != r_texture_whitecube && r_textureunits.integer >= 4)
+       {
+               // 3 3D combine path (Geforce3, Radeon 8500)
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[0] = rsurface_vertex3f;
-                               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
+               m.pointer_texcoord3f[0] = rsurface_vertex3f;
+               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
 #else
-                               m.pointer_texcoord3f[0] = varray_texcoord3f[0];
-                               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
+               m.pointer_texcoord3f[0] = varray_texcoord3f[0];
+               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
 #endif
-                               m.tex[1] = R_GetTexture(basetexture);
-                               m.pointer_texcoord[1] = surface->groupmesh->data_texcoordtexture2f;
-                               m.texmatrix[1] = texture->currenttexmatrix;
-                               m.texcubemap[2] = R_GetTexture(r_shadow_rtlight->currentcubemap);
+               m.tex[1] = R_GetTexture(basetexture);
+               m.pointer_texcoord[1] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[1] = texture->currenttexmatrix;
+               m.texcubemap[2] = R_GetTexture(r_shadow_rtlight->currentcubemap);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[2] = rsurface_vertex3f;
-                               m.texmatrix[2] = r_shadow_entitytolight;
+               m.pointer_texcoord3f[2] = rsurface_vertex3f;
+               m.texmatrix[2] = r_shadow_entitytolight;
 #else
-                               m.pointer_texcoord3f[2] = varray_texcoord3f[2];
-                               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[2] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
+               m.pointer_texcoord3f[2] = varray_texcoord3f[2];
+               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[2] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
 #endif
-                               GL_BlendFunc(GL_ONE, GL_ONE);
-                       }
-                       else if (r_shadow_texture3d.integer && r_shadow_rtlight->currentcubemap == r_texture_whitecube && r_textureunits.integer >= 2)
-                       {
-                               // 2 3D combine path (Geforce3, original Radeon)
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
+               GL_BlendFunc(GL_ONE, GL_ONE);
+       }
+       else if (r_shadow_texture3d.integer && r_shadow_rtlight->currentcubemap == r_texture_whitecube && r_textureunits.integer >= 2)
+       {
+               // 2 3D combine path (Geforce3, original Radeon)
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[0] = rsurface_vertex3f;
-                               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
+               m.pointer_texcoord3f[0] = rsurface_vertex3f;
+               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
 #else
-                               m.pointer_texcoord3f[0] = varray_texcoord3f[0];
-                               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
+               m.pointer_texcoord3f[0] = varray_texcoord3f[0];
+               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
 #endif
-                               m.tex[1] = R_GetTexture(basetexture);
-                               m.pointer_texcoord[1] = surface->groupmesh->data_texcoordtexture2f;
-                               m.texmatrix[1] = texture->currenttexmatrix;
-                               GL_BlendFunc(GL_ONE, GL_ONE);
-                       }
-                       else if (r_textureunits.integer >= 4 && r_shadow_rtlight->currentcubemap != r_texture_whitecube)
-                       {
-                               // 4 2D combine path (Geforce3, Radeon 8500)
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
+               m.tex[1] = R_GetTexture(basetexture);
+               m.pointer_texcoord[1] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[1] = texture->currenttexmatrix;
+               GL_BlendFunc(GL_ONE, GL_ONE);
+       }
+       else if (r_textureunits.integer >= 4 && r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+       {
+               // 4 2D combine path (Geforce3, Radeon 8500)
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[0] = rsurface_vertex3f;
-                               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
+               m.pointer_texcoord3f[0] = rsurface_vertex3f;
+               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
 #else
-                               m.pointer_texcoord[0] = varray_texcoord2f[0];
-                               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
+               m.pointer_texcoord[0] = varray_texcoord2f[0];
+               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
 #endif
-                               m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
+               m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[1] = rsurface_vertex3f;
-                               m.texmatrix[1] = r_shadow_entitytoattenuationz;
+               m.pointer_texcoord3f[1] = rsurface_vertex3f;
+               m.texmatrix[1] = r_shadow_entitytoattenuationz;
 #else
-                               m.pointer_texcoord[1] = varray_texcoord2f[1];
-                               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationz);
+               m.pointer_texcoord[1] = varray_texcoord2f[1];
+               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationz);
 #endif
-                               m.tex[2] = R_GetTexture(basetexture);
-                               m.pointer_texcoord[2] = surface->groupmesh->data_texcoordtexture2f;
-                               m.texmatrix[2] = texture->currenttexmatrix;
-                               if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
-                               {
-                                       m.texcubemap[3] = R_GetTexture(r_shadow_rtlight->currentcubemap);
+               m.tex[2] = R_GetTexture(basetexture);
+               m.pointer_texcoord[2] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[2] = texture->currenttexmatrix;
+               if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+               {
+                       m.texcubemap[3] = R_GetTexture(r_shadow_rtlight->currentcubemap);
 #ifdef USETEXMATRIX
-                                       m.pointer_texcoord3f[3] = rsurface_vertex3f;
-                                       m.texmatrix[3] = r_shadow_entitytolight;
+                       m.pointer_texcoord3f[3] = rsurface_vertex3f;
+                       m.texmatrix[3] = r_shadow_entitytolight;
 #else
-                                       m.pointer_texcoord3f[3] = varray_texcoord3f[3];
-                                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[3] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
+                       m.pointer_texcoord3f[3] = varray_texcoord3f[3];
+                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[3] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
 #endif
-                               }
-                               GL_BlendFunc(GL_ONE, GL_ONE);
-                       }
-                       else if (r_textureunits.integer >= 3 && r_shadow_rtlight->currentcubemap == r_texture_whitecube)
-                       {
-                               // 3 2D combine path (Geforce3, original Radeon)
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
+               }
+               GL_BlendFunc(GL_ONE, GL_ONE);
+       }
+       else if (r_textureunits.integer >= 3 && r_shadow_rtlight->currentcubemap == r_texture_whitecube)
+       {
+               // 3 2D combine path (Geforce3, original Radeon)
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[0] = rsurface_vertex3f;
-                               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
+               m.pointer_texcoord3f[0] = rsurface_vertex3f;
+               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
 #else
-                               m.pointer_texcoord[0] = varray_texcoord2f[0];
-                               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
+               m.pointer_texcoord[0] = varray_texcoord2f[0];
+               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
 #endif
-                               m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
+               m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[1] = rsurface_vertex3f;
-                               m.texmatrix[1] = r_shadow_entitytoattenuationz;
+               m.pointer_texcoord3f[1] = rsurface_vertex3f;
+               m.texmatrix[1] = r_shadow_entitytoattenuationz;
 #else
-                               m.pointer_texcoord[1] = varray_texcoord2f[1];
-                               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationz);
+               m.pointer_texcoord[1] = varray_texcoord2f[1];
+               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationz);
 #endif
-                               m.tex[2] = R_GetTexture(basetexture);
-                               m.pointer_texcoord[2] = surface->groupmesh->data_texcoordtexture2f;
-                               m.texmatrix[2] = texture->currenttexmatrix;
-                               GL_BlendFunc(GL_ONE, GL_ONE);
-                       }
-                       else
-                       {
-                               // 2/2/2 2D combine path (any dot3 card)
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
+               m.tex[2] = R_GetTexture(basetexture);
+               m.pointer_texcoord[2] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[2] = texture->currenttexmatrix;
+               GL_BlendFunc(GL_ONE, GL_ONE);
+       }
+       else
+       {
+               // 2/2/2 2D combine path (any dot3 card)
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[0] = rsurface_vertex3f;
-                               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
+               m.pointer_texcoord3f[0] = rsurface_vertex3f;
+               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
 #else
-                               m.pointer_texcoord[0] = varray_texcoord2f[0];
-                               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
+               m.pointer_texcoord[0] = varray_texcoord2f[0];
+               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
 #endif
-                               m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
+               m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[1] = rsurface_vertex3f;
-                               m.texmatrix[1] = r_shadow_entitytoattenuationz;
+               m.pointer_texcoord3f[1] = rsurface_vertex3f;
+               m.texmatrix[1] = r_shadow_entitytoattenuationz;
 #else
-                               m.pointer_texcoord[1] = varray_texcoord2f[1];
-                               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationz);
+               m.pointer_texcoord[1] = varray_texcoord2f[1];
+               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationz);
 #endif
-                               R_Mesh_State(&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);
-                               GL_LockArrays(0, 0);
+               R_Mesh_State(&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);
+               GL_LockArrays(0, 0);
 
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex[0] = R_GetTexture(basetexture);
-                               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                               m.texmatrix[0] = texture->currenttexmatrix;
-                               if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
-                               {
-                                       m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(basetexture);
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+               {
+                       m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
 #ifdef USETEXMATRIX
-                                       m.pointer_texcoord3f[1] = rsurface_vertex3f;
-                                       m.texmatrix[1] = r_shadow_entitytolight;
+                       m.pointer_texcoord3f[1] = rsurface_vertex3f;
+                       m.texmatrix[1] = r_shadow_entitytolight;
 #else
-                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
+                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
 #endif
-                               }
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                       }
-                       // this final code is shared
-                       R_Mesh_State(&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);
                }
-               if (dodiffusebase)
-               {
-                       GL_Color(1,1,1,1);
-                       colorscale = r_shadow_rtlight->diffusescale;
-                       // colorscale accounts for how much we multiply the brightness
-                       // during combine.
-                       //
-                       // mult is how many times the final pass of the lighting will be
-                       // performed to get more brightness than otherwise possible.
-                       //
-                       // Limit mult to 64 for sanity sake.
-                       if (r_shadow_texture3d.integer && r_textureunits.integer >= 4)
-                       {
-                               // 3/2 3D combine path (Geforce3, Radeon 8500)
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex[0] = R_GetTexture(normalmaptexture);
-                               m.texcombinergb[0] = GL_REPLACE;
-                               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                               m.texmatrix[0] = texture->currenttexmatrix;
-                               m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
-                               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                               R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1] + 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);
+               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+       }
+       // this final code is shared
+       R_Mesh_State(&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);
+}
+
+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)
+{
+       int renders;
+       float color2[3];
+       rmeshstate_t m;
+       const int *elements = surface->groupmesh->data_element3i + surface->num_firsttriangle * 3;
+       GL_Color(1,1,1,1);
+       // colorscale accounts for how much we multiply the brightness
+       // during combine.
+       //
+       // mult is how many times the final pass of the lighting will be
+       // performed to get more brightness than otherwise possible.
+       //
+       // Limit mult to 64 for sanity sake.
+       if (r_shadow_texture3d.integer && r_textureunits.integer >= 4)
+       {
+               // 3/2 3D combine path (Geforce3, Radeon 8500)
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(normalmaptexture);
+               m.texcombinergb[0] = GL_REPLACE;
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
+               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+               R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1] + 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);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[2] = rsurface_vertex3f;
-                               m.texmatrix[2] = r_shadow_entitytoattenuationxyz;
+               m.pointer_texcoord3f[2] = rsurface_vertex3f;
+               m.texmatrix[2] = r_shadow_entitytoattenuationxyz;
 #else
-                               m.pointer_texcoord3f[2] = varray_texcoord3f[2];
-                               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[2] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
+               m.pointer_texcoord3f[2] = varray_texcoord3f[2];
+               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[2] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
 #endif
-                               R_Mesh_State(&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);
-                               GL_LockArrays(0, 0);
+               R_Mesh_State(&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);
+               GL_LockArrays(0, 0);
 
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex[0] = R_GetTexture(basetexture);
-                               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                               m.texmatrix[0] = texture->currenttexmatrix;
-                               if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
-                               {
-                                       m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(basetexture);
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+               {
+                       m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
 #ifdef USETEXMATRIX
-                                       m.pointer_texcoord3f[1] = rsurface_vertex3f;
-                                       m.texmatrix[1] = r_shadow_entitytolight;
+                       m.pointer_texcoord3f[1] = rsurface_vertex3f;
+                       m.texmatrix[1] = r_shadow_entitytolight;
 #else
-                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
+                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
 #endif
-                               }
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                       }
-                       else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_rtlight->currentcubemap != r_texture_whitecube)
-                       {
-                               // 1/2/2 3D combine path (original Radeon)
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
+               }
+               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+       }
+       else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+       {
+               // 1/2/2 3D combine path (original Radeon)
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[0] = rsurface_vertex3f;
-                               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
+               m.pointer_texcoord3f[0] = rsurface_vertex3f;
+               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
 #else
-                               m.pointer_texcoord3f[0] = varray_texcoord3f[0];
-                               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
+               m.pointer_texcoord3f[0] = varray_texcoord3f[0];
+               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
 #endif
-                               R_Mesh_State(&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);
-                               GL_LockArrays(0, 0);
+               R_Mesh_State(&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);
+               GL_LockArrays(0, 0);
 
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex[0] = R_GetTexture(normalmaptexture);
-                               m.texcombinergb[0] = GL_REPLACE;
-                               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                               m.texmatrix[0] = texture->currenttexmatrix;
-                               m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
-                               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                               R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1] + 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_State(&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);
-                               GL_LockArrays(0, 0);
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(normalmaptexture);
+               m.texcombinergb[0] = GL_REPLACE;
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
+               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+               R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1] + 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_State(&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);
+               GL_LockArrays(0, 0);
 
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex[0] = R_GetTexture(basetexture);
-                               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                               m.texmatrix[0] = texture->currenttexmatrix;
-                               if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
-                               {
-                                       m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(basetexture);
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+               {
+                       m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
 #ifdef USETEXMATRIX
-                                       m.pointer_texcoord3f[1] = rsurface_vertex3f;
-                                       m.texmatrix[1] = r_shadow_entitytolight;
+                       m.pointer_texcoord3f[1] = rsurface_vertex3f;
+                       m.texmatrix[1] = r_shadow_entitytolight;
 #else
-                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
+                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
 #endif
-                               }
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                       }
-                       else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_rtlight->currentcubemap == r_texture_whitecube)
-                       {
-                               // 2/2 3D combine path (original Radeon)
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex[0] = R_GetTexture(normalmaptexture);
-                               m.texcombinergb[0] = GL_REPLACE;
-                               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                               m.texmatrix[0] = texture->currenttexmatrix;
-                               m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
-                               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                               R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1] + 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_State(&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);
-                               GL_LockArrays(0, 0);
+               }
+               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+       }
+       else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_rtlight->currentcubemap == r_texture_whitecube)
+       {
+               // 2/2 3D combine path (original Radeon)
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(normalmaptexture);
+               m.texcombinergb[0] = GL_REPLACE;
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
+               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+               R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1] + 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_State(&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);
+               GL_LockArrays(0, 0);
 
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex[0] = R_GetTexture(basetexture);
-                               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                               m.texmatrix[0] = texture->currenttexmatrix;
-                               m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(basetexture);
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[1] = rsurface_vertex3f;
-                               m.texmatrix[1] = r_shadow_entitytoattenuationxyz;
+               m.pointer_texcoord3f[1] = rsurface_vertex3f;
+               m.texmatrix[1] = r_shadow_entitytoattenuationxyz;
 #else
-                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
+               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
 #endif
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                       }
-                       else if (r_textureunits.integer >= 4)
-                       {
-                               // 4/2 2D combine path (Geforce3, Radeon 8500)
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex[0] = R_GetTexture(normalmaptexture);
-                               m.texcombinergb[0] = GL_REPLACE;
-                               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                               m.texmatrix[0] = texture->currenttexmatrix;
-                               m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
-                               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                               R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1] + 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);
+               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+       }
+       else if (r_textureunits.integer >= 4)
+       {
+               // 4/2 2D combine path (Geforce3, Radeon 8500)
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(normalmaptexture);
+               m.texcombinergb[0] = GL_REPLACE;
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
+               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+               R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1] + 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);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[2] = rsurface_vertex3f;
-                               m.texmatrix[2] = r_shadow_entitytoattenuationxyz;
+               m.pointer_texcoord3f[2] = rsurface_vertex3f;
+               m.texmatrix[2] = r_shadow_entitytoattenuationxyz;
 #else
-                               m.pointer_texcoord[2] = varray_texcoord2f[2];
-                               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[2] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
+               m.pointer_texcoord[2] = varray_texcoord2f[2];
+               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[2] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
 #endif
-                               m.tex[3] = R_GetTexture(r_shadow_attenuation2dtexture);
+               m.tex[3] = R_GetTexture(r_shadow_attenuation2dtexture);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[3] = rsurface_vertex3f;
-                               m.texmatrix[3] = r_shadow_entitytoattenuationz;
+               m.pointer_texcoord3f[3] = rsurface_vertex3f;
+               m.texmatrix[3] = r_shadow_entitytoattenuationz;
 #else
-                               m.pointer_texcoord[3] = varray_texcoord2f[3];
-                               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[3] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationz);
+               m.pointer_texcoord[3] = varray_texcoord2f[3];
+               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[3] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationz);
 #endif
-                               R_Mesh_State(&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);
-                               GL_LockArrays(0, 0);
+               R_Mesh_State(&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);
+               GL_LockArrays(0, 0);
 
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex[0] = R_GetTexture(basetexture);
-                               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                               m.texmatrix[0] = texture->currenttexmatrix;
-                               if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
-                               {
-                                       m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(basetexture);
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+               {
+                       m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
 #ifdef USETEXMATRIX
-                                       m.pointer_texcoord3f[1] = rsurface_vertex3f;
-                                       m.texmatrix[1] = r_shadow_entitytolight;
+                       m.pointer_texcoord3f[1] = rsurface_vertex3f;
+                       m.texmatrix[1] = r_shadow_entitytolight;
 #else
-                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
+                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
 #endif
-                               }
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                       }
-                       else
-                       {
-                               // 2/2/2 2D combine path (any dot3 card)
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
+               }
+               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+       }
+       else
+       {
+               // 2/2/2 2D combine path (any dot3 card)
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[0] = rsurface_vertex3f;
-                               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
+               m.pointer_texcoord3f[0] = rsurface_vertex3f;
+               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
 #else
-                               m.pointer_texcoord[0] = varray_texcoord2f[0];
-                               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
+               m.pointer_texcoord[0] = varray_texcoord2f[0];
+               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
 #endif
-                               m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
+               m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
 #ifdef USETEXMATRIX
-                               m.pointer_texcoord3f[1] = rsurface_vertex3f;
-                               m.texmatrix[1] = r_shadow_entitytoattenuationz;
+               m.pointer_texcoord3f[1] = rsurface_vertex3f;
+               m.texmatrix[1] = r_shadow_entitytoattenuationz;
 #else
-                               m.pointer_texcoord[1] = varray_texcoord2f[1];
-                               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationz);
+               m.pointer_texcoord[1] = varray_texcoord2f[1];
+               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationz);
 #endif
-                               R_Mesh_State(&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);
-                               GL_LockArrays(0, 0);
+               R_Mesh_State(&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);
+               GL_LockArrays(0, 0);
 
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex[0] = R_GetTexture(normalmaptexture);
-                               m.texcombinergb[0] = GL_REPLACE;
-                               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                               m.texmatrix[0] = texture->currenttexmatrix;
-                               m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
-                               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                               R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1] + 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_State(&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);
-                               GL_LockArrays(0, 0);
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(normalmaptexture);
+               m.texcombinergb[0] = GL_REPLACE;
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
+               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+               R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1] + 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_State(&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);
+               GL_LockArrays(0, 0);
 
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = rsurface_vertex3f;
-                               m.tex[0] = R_GetTexture(basetexture);
-                               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                               m.texmatrix[0] = texture->currenttexmatrix;
-                               if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
-                               {
-                                       m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(basetexture);
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+               {
+                       m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
 #ifdef USETEXMATRIX
-                                       m.pointer_texcoord3f[1] = rsurface_vertex3f;
-                                       m.texmatrix[1] = r_shadow_entitytolight;
+                       m.pointer_texcoord3f[1] = rsurface_vertex3f;
+                       m.texmatrix[1] = r_shadow_entitytolight;
 #else
-                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
+                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
 #endif
-                               }
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                       }
-                       // this final code is shared
-                       R_Mesh_State(&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);
                }
-               if (dospecular)
-               {
-                       // FIXME: detect blendsquare!
-                       //if (gl_support_blendsquare)
-                       {
-                               colorscale = specularscale;
-                               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!
-                               {
-                                       // 2/0/0/1/2 3D combine blendsquare path
-                                       memset(&m, 0, sizeof(m));
-                                       m.pointer_vertex = rsurface_vertex3f;
-                                       m.tex[0] = R_GetTexture(normalmaptexture);
-                                       m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                                       m.texmatrix[0] = texture->currenttexmatrix;
-                                       m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
-                                       m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                                       R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1] + 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_State(&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);
-                                       GL_LockArrays(0, 0);
-
-                                       memset(&m, 0, sizeof(m));
-                                       m.pointer_vertex = rsurface_vertex3f;
-                                       R_Mesh_State(&m);
-                                       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);
-                                       GL_LockArrays(0, 0);
-
-                                       memset(&m, 0, sizeof(m));
-                                       m.pointer_vertex = rsurface_vertex3f;
-                                       m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
+               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+       }
+       // this final code is shared
+       R_Mesh_State(&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);
+}
+
+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)
+{
+       int renders;
+       float color2[3];
+       rmeshstate_t m;
+       const int *elements = surface->groupmesh->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!
+       {
+               // 2/0/0/1/2 3D combine blendsquare path
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(normalmaptexture);
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
+               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+               R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1] + 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_State(&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);
+               GL_LockArrays(0, 0);
+
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               R_Mesh_State(&m);
+               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);
+               GL_LockArrays(0, 0);
+
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
 #ifdef USETEXMATRIX
-                                       m.pointer_texcoord3f[0] = rsurface_vertex3f;
-                                       m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
+               m.pointer_texcoord3f[0] = rsurface_vertex3f;
+               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
 #else
-                                       m.pointer_texcoord3f[0] = varray_texcoord3f[0];
-                                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
+               m.pointer_texcoord3f[0] = varray_texcoord3f[0];
+               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
 #endif
-                                       R_Mesh_State(&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);
-                                       GL_LockArrays(0, 0);
-
-                                       memset(&m, 0, sizeof(m));
-                                       m.pointer_vertex = rsurface_vertex3f;
-                                       m.tex[0] = R_GetTexture(glosstexture);
-                                       m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                                       m.texmatrix[0] = texture->currenttexmatrix;
-                                       if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
-                                       {
-                                               m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
+               R_Mesh_State(&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);
+               GL_LockArrays(0, 0);
+
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(glosstexture);
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+               {
+                       m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
 #ifdef USETEXMATRIX
-                                               m.pointer_texcoord3f[1] = rsurface_vertex3f;
-                                               m.texmatrix[1] = r_shadow_entitytolight;
+                       m.pointer_texcoord3f[1] = rsurface_vertex3f;
+                       m.texmatrix[1] = r_shadow_entitytolight;
 #else
-                                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                                               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
+                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
 #endif
-                                       }
-                                       GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                               }
-                               else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_rtlight->currentcubemap == r_texture_whitecube /* && gl_support_blendsquare*/) // FIXME: detect blendsquare!
-                               {
-                                       // 2/0/0/2 3D combine blendsquare path
-                                       memset(&m, 0, sizeof(m));
-                                       m.pointer_vertex = rsurface_vertex3f;
-                                       m.tex[0] = R_GetTexture(normalmaptexture);
-                                       m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                                       m.texmatrix[0] = texture->currenttexmatrix;
-                                       m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
-                                       m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                                       R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1] + 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_State(&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);
-                                       GL_LockArrays(0, 0);
-
-                                       memset(&m, 0, sizeof(m));
-                                       m.pointer_vertex = rsurface_vertex3f;
-                                       R_Mesh_State(&m);
-                                       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);
-                                       GL_LockArrays(0, 0);
-
-                                       memset(&m, 0, sizeof(m));
-                                       m.pointer_vertex = rsurface_vertex3f;
-                                       m.tex[0] = R_GetTexture(glosstexture);
-                                       m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                                       m.texmatrix[0] = texture->currenttexmatrix;
-                                       m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
+               }
+               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+       }
+       else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_rtlight->currentcubemap == r_texture_whitecube /* && gl_support_blendsquare*/) // FIXME: detect blendsquare!
+       {
+               // 2/0/0/2 3D combine blendsquare path
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(normalmaptexture);
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
+               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+               R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1] + 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_State(&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);
+               GL_LockArrays(0, 0);
+
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               R_Mesh_State(&m);
+               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);
+               GL_LockArrays(0, 0);
+
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(glosstexture);
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
 #ifdef USETEXMATRIX
-                                       m.pointer_texcoord3f[1] = rsurface_vertex3f;
-                                       m.texmatrix[1] = r_shadow_entitytoattenuationxyz;
+               m.pointer_texcoord3f[1] = rsurface_vertex3f;
+               m.texmatrix[1] = r_shadow_entitytoattenuationxyz;
 #else
-                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
+               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
 #endif
-                                       GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                               }
-                               else
-                               {
-                                       // 2/0/0/2/2 2D combine blendsquare path
-                                       memset(&m, 0, sizeof(m));
-                                       m.pointer_vertex = rsurface_vertex3f;
-                                       m.tex[0] = R_GetTexture(normalmaptexture);
-                                       m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                                       m.texmatrix[0] = texture->currenttexmatrix;
-                                       m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
-                                       m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                                       R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1] + 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_State(&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);
-                                       GL_LockArrays(0, 0);
-
-                                       memset(&m, 0, sizeof(m));
-                                       m.pointer_vertex = rsurface_vertex3f;
-                                       R_Mesh_State(&m);
-                                       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);
-                                       GL_LockArrays(0, 0);
-
-                                       memset(&m, 0, sizeof(m));
-                                       m.pointer_vertex = rsurface_vertex3f;
-                                       m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
+               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+       }
+       else
+       {
+               // 2/0/0/2/2 2D combine blendsquare path
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(normalmaptexture);
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
+               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+               R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1] + 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_State(&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);
+               GL_LockArrays(0, 0);
+
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               R_Mesh_State(&m);
+               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);
+               GL_LockArrays(0, 0);
+
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
 #ifdef USETEXMATRIX
-                                       m.pointer_texcoord3f[0] = rsurface_vertex3f;
-                                       m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
+               m.pointer_texcoord3f[0] = rsurface_vertex3f;
+               m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
 #else
-                                       m.pointer_texcoord[0] = varray_texcoord2f[0];
-                                       R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
+               m.pointer_texcoord[0] = varray_texcoord2f[0];
+               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
 #endif
-                                       m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
+               m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
 #ifdef USETEXMATRIX
-                                       m.pointer_texcoord3f[1] = rsurface_vertex3f;
-                                       m.texmatrix[1] = r_shadow_entitytoattenuationz;
+               m.pointer_texcoord3f[1] = rsurface_vertex3f;
+               m.texmatrix[1] = r_shadow_entitytoattenuationz;
 #else
-                                       m.pointer_texcoord[1] = varray_texcoord2f[1];
-                                       R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationz);
+               m.pointer_texcoord[1] = varray_texcoord2f[1];
+               R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationz);
 #endif
-                                       R_Mesh_State(&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);
-                                       GL_LockArrays(0, 0);
-
-                                       memset(&m, 0, sizeof(m));
-                                       m.pointer_vertex = rsurface_vertex3f;
-                                       m.tex[0] = R_GetTexture(glosstexture);
-                                       m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
-                                       m.texmatrix[0] = texture->currenttexmatrix;
-                                       if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
-                                       {
-                                               m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
+               R_Mesh_State(&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);
+               GL_LockArrays(0, 0);
+
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = rsurface_vertex3f;
+               m.tex[0] = R_GetTexture(glosstexture);
+               m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+               m.texmatrix[0] = texture->currenttexmatrix;
+               if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+               {
+                       m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
 #ifdef USETEXMATRIX
-                                               m.pointer_texcoord3f[1] = rsurface_vertex3f;
-                                               m.texmatrix[1] = r_shadow_entitytolight;
+                       m.pointer_texcoord3f[1] = rsurface_vertex3f;
+                       m.texmatrix[1] = r_shadow_entitytolight;
 #else
-                                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
-                                               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
+                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
 #endif
-                                       }
-                                       GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                               }
-                               R_Mesh_State(&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);
-                       }
                }
+               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
        }
+       R_Mesh_State(&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);
 }
 
-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)
+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)
 {
+       // ARB path (any Geforce, any Radeon)
        int surfacelistindex;
-       int renders;
-       float ambientcolor2[3], diffusecolor2[3];
-       rmeshstate_t m;
        qboolean doambientbase = r_shadow_rtlight->ambientscale * VectorLength2(lightcolorbase) > 0.00001 && basetexture != r_texture_black;
        qboolean dodiffusebase = r_shadow_rtlight->diffusescale * VectorLength2(lightcolorbase) > 0.00001 && basetexture != r_texture_black;
        qboolean doambientpants = r_shadow_rtlight->ambientscale * VectorLength2(lightcolorpants) > 0.00001 && pantstexture != r_texture_black;
        qboolean dodiffusepants = r_shadow_rtlight->diffusescale * VectorLength2(lightcolorpants) > 0.00001 && pantstexture != r_texture_black;
        qboolean doambientshirt = r_shadow_rtlight->ambientscale * VectorLength2(lightcolorshirt) > 0.00001 && shirttexture != r_texture_black;
        qboolean dodiffuseshirt = r_shadow_rtlight->diffusescale * VectorLength2(lightcolorshirt) > 0.00001 && shirttexture != r_texture_black;
-       //qboolean dospecular = specularscale * VectorLength2(lightcolorbase) > 0.00001 && glosstexture != r_texture_black;
-       // TODO: add direct pants/shirt rendering
-       if (doambientpants || dodiffusepants)
-               R_Shadow_RenderSurfacesLighting_Light_Vertex(ent, texture, numsurfaces, surfacelist, lightcolorpants, vec3_origin, vec3_origin, pantstexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0);
-       if (doambientshirt || dodiffuseshirt)
-               R_Shadow_RenderSurfacesLighting_Light_Vertex(ent, texture, numsurfaces, surfacelist, lightcolorshirt, vec3_origin, vec3_origin, shirttexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0);
-       if (!doambientbase && !dodiffusebase)
+       qboolean dospecular = specularscale * VectorLength2(lightcolorbase) > 0.00001 && glosstexture != r_texture_black;
+       if (!doambientbase && !dodiffusebase && !doambientpants && !dodiffusepants && !doambientshirt && !dodiffuseshirt && !dospecular)
                return;
-       VectorScale(lightcolorbase, r_shadow_rtlight->ambientscale, ambientcolor2);
-       VectorScale(lightcolorbase, r_shadow_rtlight->diffusescale, diffusecolor2);
-       GL_BlendFunc(GL_ONE, GL_ONE);
+       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+       {
+               const msurface_t *surface = surfacelist[surfacelistindex];
+               RSurf_SetVertexPointer(ent, texture, surface, r_shadow_entityeyeorigin);
+               if (!rsurface_svector3f)
+               {
+                       rsurface_svector3f = varray_svector3f;
+                       rsurface_tvector3f = varray_tvector3f;
+                       rsurface_normal3f = varray_normal3f;
+                       Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
+               }
+               if (doambientbase)
+                       R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(ent, texture, surface, lightcolorbase, basetexture, r_shadow_rtlight->ambientscale);
+               if (doambientpants)
+                       R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(ent, texture, surface, lightcolorpants, pantstexture, r_shadow_rtlight->ambientscale);
+               if (doambientshirt)
+                       R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(ent, texture, surface, lightcolorshirt, shirttexture, r_shadow_rtlight->ambientscale);
+               if (dodiffusebase)
+                       R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(ent, texture, surface, lightcolorbase, basetexture, normalmaptexture, r_shadow_rtlight->diffusescale);
+               if (dodiffusepants)
+                       R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(ent, texture, surface, lightcolorpants, pantstexture, normalmaptexture, r_shadow_rtlight->diffusescale);
+               if (dodiffuseshirt)
+                       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);
+       }
+}
+
+void R_Shadow_RenderSurfacesLighting_Light_Vertex_Pass(const msurface_t *surface, vec3_t diffusecolor2, vec3_t ambientcolor2)
+{
+       int renders;
+       const int *elements = surface->groupmesh->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++)
+       {
+               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 newnumtriangles;
+               int *newe;
+               int newelements[3072];
+               draw = false;
+               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(varray_color4f + e[0] * 4) + VectorLength2(varray_color4f + e[1] * 4) + VectorLength2(varray_color4f + e[2] * 4) >= 0.01)
+                       {
+                               newe[0] = e[0];
+                               newe[1] = e[1];
+                               newe[2] = e[2];
+                               newnumtriangles++;
+                               newe += 3;
+                               draw = true;
+                       }
+               }
+               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;
+               }
+               if (!draw)
+                       break;
+#else
+               for (i = 0, c = varray_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
+               // now reduce the intensity for the next overbright pass
+               for (i = 0, c = varray_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);
+               }
+       }
+}
+
+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)
+{
+       int surfacelistindex;
+       float ambientcolorbase[3], diffusecolorbase[3];
+       float ambientcolorpants[3], diffusecolorpants[3];
+       float ambientcolorshirt[3], diffusecolorshirt[3];
+       rmeshstate_t m;
+       qboolean dobase  = basetexture != r_texture_black;
+       qboolean dopants = pantstexture != r_texture_black;
+       qboolean doshirt = shirttexture != r_texture_black;
+       if (!dobase && !dopants && !doshirt)
+               return;
+       if (dobase)
+       {
+               VectorScale(lightcolorbase, r_shadow_rtlight->ambientscale * 2, ambientcolorbase);
+               VectorScale(lightcolorbase, r_shadow_rtlight->diffusescale * 2, diffusecolorbase);
+       }
+       if (dopants)
+       {
+               VectorScale(lightcolorpants, r_shadow_rtlight->ambientscale * 2, ambientcolorpants);
+               VectorScale(lightcolorpants, r_shadow_rtlight->diffusescale * 2, diffusecolorpants);
+       }
+       if (doshirt)
+       {
+               VectorScale(lightcolorshirt, r_shadow_rtlight->ambientscale * 2, ambientcolorshirt);
+               VectorScale(lightcolorshirt, r_shadow_rtlight->diffusescale * 2, diffusecolorshirt);
+       }
+       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
        memset(&m, 0, sizeof(m));
        m.tex[0] = R_GetTexture(basetexture);
        if (r_textureunits.integer >= 2)
@@ -2454,7 +2545,6 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex(const entity_render_t *
        for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
        {
                const msurface_t *surface = surfacelist[surfacelistindex];
-               const int *elements = surface->groupmesh->data_element3i + surface->num_firsttriangle * 3;
                RSurf_SetVertexPointer(ent, texture, surface, r_shadow_entityeyeorigin);
                if (!rsurface_svector3f)
                {
@@ -2484,69 +2574,20 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex(const entity_render_t *
 #endif
                        }
                }
-               R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(surface, diffusecolor2, ambientcolor2, 0);
-               for (renders = 0;renders < 64 && (ambientcolor2[0] > renders || ambientcolor2[1] > renders || ambientcolor2[2] > renders || diffusecolor2[0] > renders || diffusecolor2[1] > renders || diffusecolor2[2] > renders);renders++)
+               if (dobase)
                {
-                       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 newnumtriangles;
-                       int *newe;
-                       int newelements[3072];
-                       draw = false;
-                       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(varray_color4f + e[0] * 4) + VectorLength2(varray_color4f + e[1] * 4) + VectorLength2(varray_color4f + e[2] * 4) >= 0.01)
-                               {
-                                       newe[0] = e[0];
-                                       newe[1] = e[1];
-                                       newe[2] = e[2];
-                                       newnumtriangles++;
-                                       newe += 3;
-                                       draw = true;
-                               }
-                       }
-                       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;
-                       }
-                       if (!draw)
-                               break;
-#else
-                       for (i = 0, c = varray_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
-                       // now reduce the intensity for the next overbright pass
-                       for (i = 0, c = varray_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);
-                       }
+                       R_Mesh_TexBind(0, R_GetTexture(basetexture));
+                       R_Shadow_RenderSurfacesLighting_Light_Vertex_Pass(surface, diffusecolorbase, ambientcolorbase);
+               }
+               if (dopants)
+               {
+                       R_Mesh_TexBind(0, R_GetTexture(pantstexture));
+                       R_Shadow_RenderSurfacesLighting_Light_Vertex_Pass(surface, diffusecolorpants, ambientcolorpants);
+               }
+               if (doshirt)
+               {
+                       R_Mesh_TexBind(0, R_GetTexture(shirttexture));
+                       R_Shadow_RenderSurfacesLighting_Light_Vertex_Pass(surface, diffusecolorshirt, ambientcolorshirt);
                }
        }
 }
@@ -2558,10 +2599,6 @@ void R_Shadow_RenderSurfacesLighting(const entity_render_t *ent, const texture_t
        rtexture_t *basetexture;
        rtexture_t *glosstexture;
        float specularscale;
-       if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
-               qglDisable(GL_CULL_FACE);
-       else
-               qglEnable(GL_CULL_FACE);
        glosstexture = r_texture_black;
        specularscale = 0;
        if (r_shadow_gloss.integer > 0)
@@ -2587,6 +2624,12 @@ void R_Shadow_RenderSurfacesLighting(const entity_render_t *ent, const texture_t
        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) + specularscale * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
+               return;
+       if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
+               qglDisable(GL_CULL_FACE);
+       else
+               qglEnable(GL_CULL_FACE);
        if ((VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor)) >= (1.0f / 1048576.0f))
        {
                lightcolorpants[0] = r_shadow_rtlight->currentcolor[0] * ent->colormap_pantscolor[0] * texture->currentalpha;
@@ -2595,8 +2638,6 @@ void R_Shadow_RenderSurfacesLighting(const entity_render_t *ent, const texture_t
                lightcolorshirt[0] = r_shadow_rtlight->currentcolor[0] * ent->colormap_shirtcolor[0] * texture->currentalpha;
                lightcolorshirt[1] = r_shadow_rtlight->currentcolor[1] * ent->colormap_shirtcolor[1] * texture->currentalpha;
                lightcolorshirt[2] = r_shadow_rtlight->currentcolor[2] * ent->colormap_shirtcolor[2] * texture->currentalpha;
-               if ((r_shadow_rtlight->ambientscale + r_shadow_rtlight->diffusescale) * (VectorLength2(lightcolorbase) + VectorLength2(lightcolorpants) + VectorLength2(lightcolorshirt)) + specularscale * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
-                       return;
                basetexture = texture->skin.base;
                switch (r_shadow_rendermode)
                {
@@ -2619,8 +2660,6 @@ void R_Shadow_RenderSurfacesLighting(const entity_render_t *ent, const texture_t
        }
        else
        {
-               if ((r_shadow_rtlight->ambientscale + r_shadow_rtlight->diffusescale) * VectorLength2(lightcolorbase) + specularscale * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
-                       return;
                basetexture = texture->skin.merged ? texture->skin.merged : texture->skin.base;
                switch (r_shadow_rendermode)
                {