]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
Tomaz changed skybox rendering/loading to flip skyboxes and use cubemaps directly...
[xonotic/darkplaces.git] / r_shadow.c
index b2e4d9730b64e2baa704e085025ab489a57bf9a6..20c95578f552bda8c248e6499e3921826feabb88 100644 (file)
@@ -162,30 +162,31 @@ rtexture_t *r_shadow_blankwhitetexture;
 // used only for light filters (cubemaps)
 rtexturepool_t *r_shadow_filters_texturepool;
 
-cvar_t r_shadow_realtime_world_lightmaps = {0, "r_shadow_realtime_world_lightmaps", "0"};
+cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "0"};
+cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4"};
+cvar_t r_shadow_cull = {0, "r_shadow_cull", "1"};
+cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1"};
+cvar_t r_shadow_gloss = {0, "r_shadow_gloss", "1"};
+cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.25"};
+cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "1"};
 cvar_t r_shadow_lightattenuationpower = {0, "r_shadow_lightattenuationpower", "0.5"};
 cvar_t r_shadow_lightattenuationscale = {0, "r_shadow_lightattenuationscale", "1"};
 cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1"};
-cvar_t r_shadow_realtime_world = {0, "r_shadow_realtime_world", "0"};
-cvar_t r_shadow_realtime_dlight = {0, "r_shadow_realtime_dlight", "0"};
-cvar_t r_shadow_visiblevolumes = {0, "r_shadow_visiblevolumes", "0"};
-cvar_t r_shadow_gloss = {0, "r_shadow_gloss", "1"};
-cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "1"};
-cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.25"};
-cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1"};
-cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1"};
-cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4"};
-cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "0"};
 cvar_t r_shadow_polygonfactor = {0, "r_shadow_polygonfactor", "0"};
 cvar_t r_shadow_polygonoffset = {0, "r_shadow_polygonoffset", "1"};
 cvar_t r_shadow_portallight = {0, "r_shadow_portallight", "1"};
-cvar_t r_shadow_projectdistance = {0, "r_shadow_projectdistance", "10000"};
-cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "1"};
+cvar_t r_shadow_projectdistance = {0, "r_shadow_projectdistance", "1000000"};
+cvar_t r_shadow_realtime_dlight = {0, "r_shadow_realtime_dlight", "1"};
+cvar_t r_shadow_realtime_dlight_shadows = {0, "r_shadow_realtime_dlight_shadows", "0"};
+cvar_t r_shadow_realtime_world = {0, "r_shadow_realtime_world", "0"};
+cvar_t r_shadow_realtime_world_dlightshadows = {0, "r_shadow_realtime_world_dlightshadows", "1"};
+cvar_t r_shadow_realtime_world_lightmaps = {0, "r_shadow_realtime_world_lightmaps", "0"};
+cvar_t r_shadow_realtime_world_shadows = {0, "r_shadow_realtime_world_shadows", "1"};
+cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1"};
 cvar_t r_shadow_singlepassvolumegeneration = {0, "r_shadow_singlepassvolumegeneration", "1"};
-cvar_t r_shadow_worldshadows = {0, "r_shadow_worldshadows", "1"};
-cvar_t r_shadow_dlightshadows = {CVAR_SAVE, "r_shadow_dlightshadows", "1"};
 cvar_t r_shadow_staticworldlights = {0, "r_shadow_staticworldlights", "1"};
-cvar_t r_shadow_cull = {0, "r_shadow_cull", "1"};
+cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "1"};
+cvar_t r_shadow_visiblevolumes = {0, "r_shadow_visiblevolumes", "0"};
 cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1"};
 
 int c_rt_lights, c_rt_clears, c_rt_scissored;
@@ -274,28 +275,29 @@ void R_Shadow_Help_f(void)
        Con_Printf(
 "Documentation on r_shadow system:\n"
 "Settings:\n"
+"r_shadow_bumpscale_basetexture : base texture as bumpmap with this scale\n"
+"r_shadow_bumpscale_bumpmap : depth scale for bumpmap conversion\n"
+"r_shadow_debuglight : render only this light number (-1 = all)\n"
+"r_shadow_gloss 0/1/2 : no gloss, gloss textures only, force gloss\n"
+"r_shadow_gloss2intensity : brightness of forced gloss\n"
+"r_shadow_glossintensity : brightness of textured gloss\n"
 "r_shadow_lightattenuationpower : used to generate attenuation texture\n"
 "r_shadow_lightattenuationscale : used to generate attenuation texture\n"
 "r_shadow_lightintensityscale : scale rendering brightness of all lights\n"
-"r_shadow_realtime_world : use realtime world light rendering\n"
-"r_shadow_realtime_dlight : use high quality dlight rendering\n"
-"r_shadow_realtime_world_lightmaps : use lightmaps in addition to rtlights\n"
-"r_shadow_visiblevolumes : useful for performance testing; bright = slow!\n"
-"r_shadow_gloss 0/1/2 : no gloss, gloss textures only, force gloss\n"
-"r_shadow_glossintensity : brightness of textured gloss\n"
-"r_shadow_gloss2intensity : brightness of forced gloss\n"
-"r_shadow_debuglight : render only this light number (-1 = all)\n"
-"r_shadow_scissor : use scissor optimization\n"
-"r_shadow_bumpscale_bumpmap : depth scale for bumpmap conversion\n"
-"r_shadow_bumpscale_basetexture : base texture as bumpmap with this scale\n"
 "r_shadow_polygonfactor : nudge shadow volumes closer/further\n"
 "r_shadow_polygonoffset : nudge shadow volumes closer/further\n"
 "r_shadow_portallight : use portal visibility for static light precomputation\n"
 "r_shadow_projectdistance : shadow volume projection distance\n"
-"r_shadow_texture3d : use 3d attenuation texture (if hardware supports)\n"
+"r_shadow_realtime_dlight : use high quality dynamic lights in normal mode\n"
+"r_shadow_realtime_dlight_shadows : cast shadows from dlights\n"
+"r_shadow_realtime_world : use high quality world lighting mode\n"
+"r_shadow_realtime_world_dlightshadows : cast shadows from dlights\n"
+"r_shadow_realtime_world_lightmaps : use lightmaps in addition to lights\n"
+"r_shadow_realtime_world_shadows : cast shadows from world lights\n"
+"r_shadow_scissor : use scissor optimization\n"
 "r_shadow_singlepassvolumegeneration : selects shadow volume algorithm\n"
-"r_shadow_worldshadows : enable world shadows\n"
-"r_shadow_dlightshadows : enable dlight shadows\n"
+"r_shadow_texture3d : use 3d attenuation texture (if hardware supports)\n"
+"r_shadow_visiblevolumes : useful for performance testing; bright = slow!\n"
 "Commands:\n"
 "r_shadow_help : this help\n"
        );
@@ -303,30 +305,31 @@ void R_Shadow_Help_f(void)
 
 void R_Shadow_Init(void)
 {
+       Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture);
+       Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap);
+       Cvar_RegisterVariable(&r_shadow_cull);
+       Cvar_RegisterVariable(&r_shadow_debuglight);
+       Cvar_RegisterVariable(&r_shadow_gloss);
+       Cvar_RegisterVariable(&r_shadow_gloss2intensity);
+       Cvar_RegisterVariable(&r_shadow_glossintensity);
        Cvar_RegisterVariable(&r_shadow_lightattenuationpower);
        Cvar_RegisterVariable(&r_shadow_lightattenuationscale);
        Cvar_RegisterVariable(&r_shadow_lightintensityscale);
-       Cvar_RegisterVariable(&r_shadow_realtime_world);
-       Cvar_RegisterVariable(&r_shadow_realtime_world_lightmaps);
-       Cvar_RegisterVariable(&r_shadow_realtime_dlight);
-       Cvar_RegisterVariable(&r_shadow_visiblevolumes);
-       Cvar_RegisterVariable(&r_shadow_gloss);
-       Cvar_RegisterVariable(&r_shadow_glossintensity);
-       Cvar_RegisterVariable(&r_shadow_gloss2intensity);
-       Cvar_RegisterVariable(&r_shadow_debuglight);
-       Cvar_RegisterVariable(&r_shadow_scissor);
-       Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap);
-       Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture);
        Cvar_RegisterVariable(&r_shadow_polygonfactor);
        Cvar_RegisterVariable(&r_shadow_polygonoffset);
        Cvar_RegisterVariable(&r_shadow_portallight);
        Cvar_RegisterVariable(&r_shadow_projectdistance);
-       Cvar_RegisterVariable(&r_shadow_texture3d);
+       Cvar_RegisterVariable(&r_shadow_realtime_dlight);
+       Cvar_RegisterVariable(&r_shadow_realtime_dlight_shadows);
+       Cvar_RegisterVariable(&r_shadow_realtime_world);
+       Cvar_RegisterVariable(&r_shadow_realtime_world_dlightshadows);
+       Cvar_RegisterVariable(&r_shadow_realtime_world_lightmaps);
+       Cvar_RegisterVariable(&r_shadow_realtime_world_shadows);
+       Cvar_RegisterVariable(&r_shadow_scissor);
        Cvar_RegisterVariable(&r_shadow_singlepassvolumegeneration);
-       Cvar_RegisterVariable(&r_shadow_worldshadows);
-       Cvar_RegisterVariable(&r_shadow_dlightshadows);
        Cvar_RegisterVariable(&r_shadow_staticworldlights);
-       Cvar_RegisterVariable(&r_shadow_cull);
+       Cvar_RegisterVariable(&r_shadow_texture3d);
+       Cvar_RegisterVariable(&r_shadow_visiblevolumes);
        Cvar_RegisterVariable(&gl_ext_stenciltwoside);
        if (gamemode == GAME_TENEBRAE)
        {
@@ -930,9 +933,7 @@ int R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
        if (!r_shadow_scissor.integer)
                return false;
        // if view is inside the box, just say yes it's visible
-       // LordHavoc: for some odd reason scissor seems broken without stencil
-       // (?!?  seems like a driver bug) so abort if gl_stencil is false
-       if (!gl_stencil || BoxesOverlap(r_vieworigin, r_vieworigin, mins, maxs))
+       if (BoxesOverlap(r_vieworigin, r_vieworigin, mins, maxs))
        {
                GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
                return false;
@@ -1094,7 +1095,7 @@ int R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
        return false;
 }
 
-void R_Shadow_VertexLighting(int numverts, const float *vertex3f, const float *normal3f, const float *lightcolor, const matrix4x4_t *m)
+static void R_Shadow_VertexShadingWithXYZAttenuation(int numverts, const float *vertex3f, const float *normal3f, const float *lightcolor, const matrix4x4_t *m)
 {
        float *color4f = varray_color4f;
        float dist, dot, intensity, v[3], n[3];
@@ -1107,7 +1108,8 @@ void R_Shadow_VertexLighting(int numverts, const float *vertex3f, const float *n
                        if ((dot = DotProduct(n, v)) > 0)
                        {
                                dist = sqrt(dist);
-                               intensity = pow(1 - dist, r_shadow_attenpower) * r_shadow_attenscale * dot / sqrt(DotProduct(n,n));
+                               intensity = dot / sqrt(VectorLength2(v) * VectorLength2(n));
+                               intensity *= pow(1 - dist, r_shadow_attenpower) * r_shadow_attenscale;
                                VectorScale(lightcolor, intensity, color4f);
                                color4f[3] = 1;
                        }
@@ -1125,7 +1127,7 @@ void R_Shadow_VertexLighting(int numverts, const float *vertex3f, const float *n
        }
 }
 
-void R_Shadow_VertexLightingWithXYAttenuationTexture(int numverts, const float *vertex3f, const float *normal3f, const float *lightcolor, const matrix4x4_t *m)
+static void R_Shadow_VertexShadingWithZAttenuation(int numverts, const float *vertex3f, const float *normal3f, const float *lightcolor, const matrix4x4_t *m)
 {
        float *color4f = varray_color4f;
        float dist, dot, intensity, v[3], n[3];
@@ -1137,7 +1139,8 @@ void R_Shadow_VertexLightingWithXYAttenuationTexture(int numverts, const float *
                        Matrix4x4_Transform3x3(m, normal3f, n);
                        if ((dot = DotProduct(n, v)) > 0)
                        {
-                               intensity = pow(1 - dist, r_shadow_attenpower) * r_shadow_attenscale * dot / sqrt(DotProduct(n,n));
+                               intensity = dot / sqrt(VectorLength2(v) * VectorLength2(n));
+                               intensity *= pow(1 - dist, r_shadow_attenpower) * r_shadow_attenscale;
                                VectorScale(lightcolor, intensity, color4f);
                                color4f[3] = 1;
                        }
@@ -1155,9 +1158,33 @@ void R_Shadow_VertexLightingWithXYAttenuationTexture(int numverts, const float *
        }
 }
 
-// FIXME: this should be done in a vertex program when possible
+static void R_Shadow_VertexShading(int numverts, const float *vertex3f, const float *normal3f, const float *lightcolor, const matrix4x4_t *m)
+{
+       float *color4f = varray_color4f;
+       float dot, intensity, v[3], n[3];
+       for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4)
+       {
+               Matrix4x4_Transform(m, vertex3f, v);
+               Matrix4x4_Transform3x3(m, normal3f, n);
+               if ((dot = DotProduct(n, v)) > 0)
+               {
+                       intensity = dot / sqrt(VectorLength2(v) * VectorLength2(n));
+                       VectorScale(lightcolor, intensity, color4f);
+                       color4f[3] = 1;
+               }
+               else
+               {
+                       VectorClear(color4f);
+                       color4f[3] = 1;
+               }
+       }
+}
+
+#define USETEXMATRIX 1
+#ifndef USETEXMATRIX
+// FIXME: this should be done in a texture matrix or vertex program when possible
 // FIXME: if vertex program not available, this would really benefit from 3DNow! or SSE
-void R_Shadow_Transform_Vertex3f_TexCoord3f(float *tc3f, int numverts, const float *vertex3f, const matrix4x4_t *matrix)
+static void R_Shadow_Transform_Vertex3f_TexCoord3f(float *tc3f, int numverts, const float *vertex3f, const matrix4x4_t *matrix)
 {
        do
        {
@@ -1170,7 +1197,7 @@ void R_Shadow_Transform_Vertex3f_TexCoord3f(float *tc3f, int numverts, const flo
        while (--numverts);
 }
 
-void R_Shadow_Transform_Vertex3f_TexCoord2f(float *tc2f, int numverts, const float *vertex3f, const matrix4x4_t *matrix)
+static void R_Shadow_Transform_Vertex3f_TexCoord2f(float *tc2f, int numverts, const float *vertex3f, const matrix4x4_t *matrix)
 {
        do
        {
@@ -1181,8 +1208,9 @@ void R_Shadow_Transform_Vertex3f_TexCoord2f(float *tc2f, int numverts, const flo
        }
        while (--numverts);
 }
+#endif
 
-void R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(float *out3f, int numverts, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const vec3_t relativelightorigin)
+static void R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(float *out3f, int numverts, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const vec3_t relativelightorigin)
 {
        int i;
        float lightdir[3];
@@ -1196,7 +1224,7 @@ void R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(float *out3f, int numverts, con
        }
 }
 
-void R_Shadow_GenTexCoords_Specular_NormalCubeMap(float *out3f, int numverts, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const vec3_t relativelightorigin, const vec3_t relativeeyeorigin)
+static void R_Shadow_GenTexCoords_Specular_NormalCubeMap(float *out3f, int numverts, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const vec3_t relativelightorigin, const vec3_t relativeeyeorigin)
 {
        int i;
        float lightdir[3], eyedir[3], halfdir[3];
@@ -1230,25 +1258,34 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                if (lighting & LIGHTING_DIFFUSE)
                {
                        GL_Color(1,1,1,1);
-                       // colorscale accounts for how much we multiply the brightness during combine
+                       colorscale = r_shadow_lightintensityscale.value;
+                       // 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
+                       // 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 = vertex3f;
                                m.tex[0] = R_GetTexture(bumptexture);
-                               m.pointer_texcoord[0] = texcoord2f;
                                m.texcombinergb[0] = GL_REPLACE;
+                               m.pointer_texcoord[0] = texcoord2f;
                                m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
                                m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                               m.pointer_texcoord[1] = varray_texcoord3f[1];
+                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
                                R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin);
                                m.tex3d[2] = R_GetTexture(r_shadow_attenuation3dtexture);
-                               m.pointer_texcoord[2] = varray_texcoord3f[2];
+#if USETEXMATRIX
+                               m.pointer_texcoord3f[2] = vertex3f;
+                               m.texmatrix[2] = *matrix_modeltoattenuationxyz;
+#else
+                               m.pointer_texcoord3f[2] = varray_texcoord3f[2];
                                R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[2], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
                                R_Mesh_State(&m);
                                GL_ColorMask(0,0,0,1);
                                GL_BlendFunc(GL_ONE, GL_ZERO);
@@ -1257,7 +1294,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                GL_LockArrays(0, 0);
                                c_rt_lightmeshes++;
                                c_rt_lighttris += numtriangles;
-
+       
                                memset(&m, 0, sizeof(m));
                                m.pointer_vertex = vertex3f;
                                m.tex[0] = R_GetTexture(basetexture);
@@ -1265,25 +1302,14 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                if (lightcubemap)
                                {
                                        m.texcubemap[1] = R_GetTexture(lightcubemap);
-                                       m.pointer_texcoord[1] = varray_texcoord3f[1];
+#if USETEXMATRIX
+                                       m.pointer_texcoord3f[1] = vertex3f;
+                                       m.texmatrix[1] = *matrix_modeltolight;
+#else
+                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
                                        R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight);
+#endif
                                }
-                               R_Mesh_State(&m);
-                               GL_LockArrays(0, numverts);
-                               GL_ColorMask(1,1,1,0);
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                               VectorScale(lightcolor, r_shadow_lightintensityscale.value, color2);
-                               for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
-                               {
-                                       color[0] = bound(0, color2[0], 1);
-                                       color[1] = bound(0, color2[1], 1);
-                                       color[2] = bound(0, color2[2], 1);
-                                       GL_Color(color[0], color[1], color[2], 1);
-                                       R_Mesh_Draw(numverts, numtriangles, elements);
-                                       c_rt_lightmeshes++;
-                                       c_rt_lighttris += numtriangles;
-                               }
-                               GL_LockArrays(0, 0);
                        }
                        else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && lightcubemap)
                        {
@@ -1291,8 +1317,13 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                memset(&m, 0, sizeof(m));
                                m.pointer_vertex = vertex3f;
                                m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
-                               m.pointer_texcoord[0] = varray_texcoord3f[0];
+#if USETEXMATRIX
+                               m.pointer_texcoord3f[0] = vertex3f;
+                               m.texmatrix[0] = *matrix_modeltoattenuationxyz;
+#else
+                               m.pointer_texcoord3f[0] = varray_texcoord3f[0];
                                R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
                                R_Mesh_State(&m);
                                GL_ColorMask(0,0,0,1);
                                GL_BlendFunc(GL_ONE, GL_ZERO);
@@ -1301,7 +1332,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                GL_LockArrays(0, 0);
                                c_rt_lightmeshes++;
                                c_rt_lighttris += numtriangles;
-
+       
                                memset(&m, 0, sizeof(m));
                                m.pointer_vertex = vertex3f;
                                m.tex[0] = R_GetTexture(bumptexture);
@@ -1309,7 +1340,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                m.pointer_texcoord[0] = texcoord2f;
                                m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
                                m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                               m.pointer_texcoord[1] = varray_texcoord3f[1];
+                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
                                R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin);
                                R_Mesh_State(&m);
                                GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
@@ -1318,7 +1349,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                GL_LockArrays(0, 0);
                                c_rt_lightmeshes++;
                                c_rt_lighttris += numtriangles;
-
+       
                                memset(&m, 0, sizeof(m));
                                m.pointer_vertex = vertex3f;
                                m.tex[0] = R_GetTexture(basetexture);
@@ -1326,25 +1357,14 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                if (lightcubemap)
                                {
                                        m.texcubemap[1] = R_GetTexture(lightcubemap);
-                                       m.pointer_texcoord[1] = varray_texcoord3f[1];
+#if USETEXMATRIX
+                                       m.pointer_texcoord3f[1] = vertex3f;
+                                       m.texmatrix[1] = *matrix_modeltolight;
+#else
+                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
                                        R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight);
+#endif
                                }
-                               R_Mesh_State(&m);
-                               GL_LockArrays(0, numverts);
-                               GL_ColorMask(1,1,1,0);
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                               VectorScale(lightcolor, r_shadow_lightintensityscale.value, color2);
-                               for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
-                               {
-                                       color[0] = bound(0, color2[0], 1);
-                                       color[1] = bound(0, color2[1], 1);
-                                       color[2] = bound(0, color2[2], 1);
-                                       GL_Color(color[0], color[1], color[2], 1);
-                                       R_Mesh_Draw(numverts, numtriangles, elements);
-                                       c_rt_lightmeshes++;
-                                       c_rt_lighttris += numtriangles;
-                               }
-                               GL_LockArrays(0, 0);
                        }
                        else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && !lightcubemap)
                        {
@@ -1356,7 +1376,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                m.pointer_texcoord[0] = texcoord2f;
                                m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
                                m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                               m.pointer_texcoord[1] = varray_texcoord3f[1];
+                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
                                R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin);
                                R_Mesh_State(&m);
                                GL_ColorMask(0,0,0,1);
@@ -1366,30 +1386,19 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                GL_LockArrays(0, 0);
                                c_rt_lightmeshes++;
                                c_rt_lighttris += numtriangles;
-
+       
                                memset(&m, 0, sizeof(m));
                                m.pointer_vertex = vertex3f;
                                m.tex[0] = R_GetTexture(basetexture);
                                m.pointer_texcoord[0] = texcoord2f;
                                m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
-                               m.pointer_texcoord[1] = varray_texcoord3f[1];
+#if USETEXMATRIX
+                               m.pointer_texcoord3f[1] = vertex3f;
+                               m.texmatrix[1] = *matrix_modeltoattenuationxyz;
+#else
+                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
                                R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltoattenuationxyz);
-                               R_Mesh_State(&m);
-                               GL_LockArrays(0, numverts);
-                               GL_ColorMask(1,1,1,0);
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                               VectorScale(lightcolor, r_shadow_lightintensityscale.value, color2);
-                               for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
-                               {
-                                       color[0] = bound(0, color2[0], 1);
-                                       color[1] = bound(0, color2[1], 1);
-                                       color[2] = bound(0, color2[2], 1);
-                                       GL_Color(color[0], color[1], color[2], 1);
-                                       R_Mesh_Draw(numverts, numtriangles, elements);
-                                       c_rt_lightmeshes++;
-                                       c_rt_lighttris += numtriangles;
-                               }
-                               GL_LockArrays(0, 0);
+#endif
                        }
                        else if (r_textureunits.integer >= 4)
                        {
@@ -1401,14 +1410,24 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                m.pointer_texcoord[0] = texcoord2f;
                                m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
                                m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                               m.pointer_texcoord[1] = varray_texcoord3f[1];
+                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
                                R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin);
                                m.tex[2] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+                               m.pointer_texcoord3f[2] = vertex3f;
+                               m.texmatrix[2] = *matrix_modeltoattenuationxyz;
+#else
                                m.pointer_texcoord[2] = varray_texcoord2f[2];
                                R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[2], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
                                m.tex[3] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+                               m.pointer_texcoord3f[3] = vertex3f;
+                               m.texmatrix[3] = *matrix_modeltoattenuationz;
+#else
                                m.pointer_texcoord[3] = varray_texcoord2f[3];
                                R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[3], numverts, vertex3f, matrix_modeltoattenuationz);
+#endif
                                R_Mesh_State(&m);
                                GL_ColorMask(0,0,0,1);
                                GL_BlendFunc(GL_ONE, GL_ZERO);
@@ -1417,7 +1436,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                GL_LockArrays(0, 0);
                                c_rt_lightmeshes++;
                                c_rt_lighttris += numtriangles;
-
+       
                                memset(&m, 0, sizeof(m));
                                m.pointer_vertex = vertex3f;
                                m.tex[0] = R_GetTexture(basetexture);
@@ -1425,25 +1444,14 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                if (lightcubemap)
                                {
                                        m.texcubemap[1] = R_GetTexture(lightcubemap);
-                                       m.pointer_texcoord[1] = varray_texcoord3f[1];
+#if USETEXMATRIX
+                                       m.pointer_texcoord3f[1] = vertex3f;
+                                       m.texmatrix[1] = *matrix_modeltolight;
+#else
+                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
                                        R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight);
+#endif
                                }
-                               R_Mesh_State(&m);
-                               GL_LockArrays(0, numverts);
-                               GL_ColorMask(1,1,1,0);
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                               VectorScale(lightcolor, r_shadow_lightintensityscale.value, color2);
-                               for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
-                               {
-                                       color[0] = bound(0, color2[0], 1);
-                                       color[1] = bound(0, color2[1], 1);
-                                       color[2] = bound(0, color2[2], 1);
-                                       GL_Color(color[0], color[1], color[2], 1);
-                                       R_Mesh_Draw(numverts, numtriangles, elements);
-                                       c_rt_lightmeshes++;
-                                       c_rt_lighttris += numtriangles;
-                               }
-                               GL_LockArrays(0, 0);
                        }
                        else
                        {
@@ -1451,11 +1459,21 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                memset(&m, 0, sizeof(m));
                                m.pointer_vertex = vertex3f;
                                m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+                               m.pointer_texcoord3f[0] = vertex3f;
+                               m.texmatrix[0] = *matrix_modeltoattenuationxyz;
+#else
                                m.pointer_texcoord[0] = varray_texcoord2f[0];
                                R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[0], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
                                m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+                               m.pointer_texcoord3f[1] = vertex3f;
+                               m.texmatrix[1] = *matrix_modeltoattenuationz;
+#else
                                m.pointer_texcoord[1] = varray_texcoord2f[1];
                                R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationz);
+#endif
                                R_Mesh_State(&m);
                                GL_ColorMask(0,0,0,1);
                                GL_BlendFunc(GL_ONE, GL_ZERO);
@@ -1464,7 +1482,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                GL_LockArrays(0, 0);
                                c_rt_lightmeshes++;
                                c_rt_lighttris += numtriangles;
-
+       
                                memset(&m, 0, sizeof(m));
                                m.pointer_vertex = vertex3f;
                                m.tex[0] = R_GetTexture(bumptexture);
@@ -1472,7 +1490,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                m.pointer_texcoord[0] = texcoord2f;
                                m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
                                m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                               m.pointer_texcoord[1] = varray_texcoord3f[1];
+                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
                                R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin);
                                R_Mesh_State(&m);
                                GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
@@ -1481,7 +1499,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                GL_LockArrays(0, 0);
                                c_rt_lightmeshes++;
                                c_rt_lighttris += numtriangles;
-
+       
                                memset(&m, 0, sizeof(m));
                                m.pointer_vertex = vertex3f;
                                m.tex[0] = R_GetTexture(basetexture);
@@ -1489,257 +1507,259 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                if (lightcubemap)
                                {
                                        m.texcubemap[1] = R_GetTexture(lightcubemap);
-                                       m.pointer_texcoord[1] = varray_texcoord3f[1];
+#if USETEXMATRIX
+                                       m.pointer_texcoord3f[1] = vertex3f;
+                                       m.texmatrix[1] = *matrix_modeltolight;
+#else
+                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
                                        R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight);
+#endif
                                }
-                               R_Mesh_State(&m);
-                               GL_LockArrays(0, numverts);
-                               GL_ColorMask(1,1,1,0);
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                               VectorScale(lightcolor, r_shadow_lightintensityscale.value, color2);
-                               for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
-                               {
-                                       color[0] = bound(0, color2[0], 1);
-                                       color[1] = bound(0, color2[1], 1);
-                                       color[2] = bound(0, color2[2], 1);
-                                       GL_Color(color[0], color[1], color[2], 1);
-                                       R_Mesh_Draw(numverts, numtriangles, elements);
-                                       c_rt_lightmeshes++;
-                                       c_rt_lighttris += numtriangles;
-                               }
-                               GL_LockArrays(0, 0);
                        }
-               }
-               if ((lighting & LIGHTING_SPECULAR) && (r_shadow_gloss.integer >= 2 || (r_shadow_gloss.integer >= 1 && glosstexture != r_shadow_blankglosstexture)))
-               {
-                       colorscale = r_shadow_glossintensity.value;
-                       if (glosstexture == r_shadow_blankglosstexture)
-                               colorscale *= r_shadow_gloss2intensity.value;
-                       GL_Color(1,1,1,1);
-                       if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && lightcubemap /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare!
+                       // this final code is shared
+                       R_Mesh_State(&m);
+                       GL_ColorMask(1,1,1,0);
+                       GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+                       VectorScale(lightcolor, colorscale, color2);
+                       for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
                        {
-                               // 2/0/0/1/2 3D combine blendsquare path
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = vertex3f;
-                               m.tex[0] = R_GetTexture(bumptexture);
-                               m.pointer_texcoord[0] = texcoord2f;
-                               m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
-                               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                               m.pointer_texcoord[1] = varray_texcoord3f[1];
-                               R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin);
-                               R_Mesh_State(&m);
-                               GL_ColorMask(0,0,0,1);
-                               // this squares the result
-                               GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO);
-                               GL_LockArrays(0, numverts);
-                               R_Mesh_Draw(numverts, numtriangles, elements);
-                               GL_LockArrays(0, 0);
-                               c_rt_lightmeshes++;
-                               c_rt_lighttris += numtriangles;
-
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = vertex3f;
-                               R_Mesh_State(&m);
-                               GL_LockArrays(0, numverts);
-                               // 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(numverts, numtriangles, elements);
-                               c_rt_lightmeshes++;
-                               c_rt_lighttris += numtriangles;
-                               R_Mesh_Draw(numverts, numtriangles, elements);
-                               c_rt_lightmeshes++;
-                               c_rt_lighttris += numtriangles;
-                               GL_LockArrays(0, 0);
-
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = vertex3f;
-                               m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
-                               m.pointer_texcoord[0] = varray_texcoord3f[0];
-                               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0], numverts, vertex3f, matrix_modeltoattenuationxyz);
-                               R_Mesh_State(&m);
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
+                               GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1);
                                GL_LockArrays(0, numverts);
                                R_Mesh_Draw(numverts, numtriangles, elements);
                                GL_LockArrays(0, 0);
                                c_rt_lightmeshes++;
                                c_rt_lighttris += numtriangles;
-
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = vertex3f;
-                               m.tex[0] = R_GetTexture(glosstexture);
-                               m.pointer_texcoord[0] = texcoord2f;
-                               if (lightcubemap)
+                       }
+               }
+               if ((lighting & LIGHTING_SPECULAR) && (r_shadow_gloss.integer >= 2 || (r_shadow_gloss.integer >= 1 && glosstexture != r_shadow_blankglosstexture)))
+               {
+                       // FIXME: detect blendsquare!
+                       //if (gl_support_blendsquare)
+                       {
+                               colorscale = r_shadow_lightintensityscale.value * r_shadow_glossintensity.value;
+                               if (glosstexture == r_shadow_blankglosstexture)
+                                       colorscale *= r_shadow_gloss2intensity.value;
+                               GL_Color(1,1,1,1);
+                               if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && lightcubemap /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare!
                                {
-                                       m.texcubemap[1] = R_GetTexture(lightcubemap);
-                                       m.pointer_texcoord[1] = varray_texcoord3f[1];
-                                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight);
+                                       // 2/0/0/1/2 3D combine blendsquare path
+                                       memset(&m, 0, sizeof(m));
+                                       m.pointer_vertex = vertex3f;
+                                       m.tex[0] = R_GetTexture(bumptexture);
+                                       m.pointer_texcoord[0] = texcoord2f;
+                                       m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
+                                       m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+                                       R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin);
+                                       R_Mesh_State(&m);
+                                       GL_ColorMask(0,0,0,1);
+                                       // this squares the result
+                                       GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO);
+                                       GL_LockArrays(0, numverts);
+                                       R_Mesh_Draw(numverts, numtriangles, elements);
+                                       GL_LockArrays(0, 0);
+                                       c_rt_lightmeshes++;
+                                       c_rt_lighttris += numtriangles;
+               
+                                       memset(&m, 0, sizeof(m));
+                                       m.pointer_vertex = vertex3f;
+                                       R_Mesh_State(&m);
+                                       GL_LockArrays(0, numverts);
+                                       // 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(numverts, numtriangles, elements);
+                                       c_rt_lightmeshes++;
+                                       c_rt_lighttris += numtriangles;
+                                       R_Mesh_Draw(numverts, numtriangles, elements);
+                                       c_rt_lightmeshes++;
+                                       c_rt_lighttris += numtriangles;
+                                       GL_LockArrays(0, 0);
+               
+                                       memset(&m, 0, sizeof(m));
+                                       m.pointer_vertex = vertex3f;
+                                       m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
+#if USETEXMATRIX
+                                       m.pointer_texcoord3f[0] = vertex3f;
+                                       m.texmatrix[0] = *matrix_modeltoattenuationxyz;
+#else
+                                       m.pointer_texcoord3f[0] = varray_texcoord3f[0];
+                                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
+                                       R_Mesh_State(&m);
+                                       GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
+                                       GL_LockArrays(0, numverts);
+                                       R_Mesh_Draw(numverts, numtriangles, elements);
+                                       GL_LockArrays(0, 0);
+                                       c_rt_lightmeshes++;
+                                       c_rt_lighttris += numtriangles;
+               
+                                       memset(&m, 0, sizeof(m));
+                                       m.pointer_vertex = vertex3f;
+                                       m.tex[0] = R_GetTexture(glosstexture);
+                                       m.pointer_texcoord[0] = texcoord2f;
+                                       if (lightcubemap)
+                                       {
+                                               m.texcubemap[1] = R_GetTexture(lightcubemap);
+#if USETEXMATRIX
+                                               m.pointer_texcoord3f[1] = vertex3f;
+                                               m.texmatrix[1] = *matrix_modeltolight;
+#else
+                                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+                                               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight);
+#endif
+                                       }
                                }
-                               R_Mesh_State(&m);
-                               GL_LockArrays(0, numverts);
-                               GL_ColorMask(1,1,1,0);
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                               VectorScale(lightcolor, colorscale, color2);
-                               for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
+                               else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && !lightcubemap /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare!
                                {
-                                       color[0] = bound(0, color2[0], 1);
-                                       color[1] = bound(0, color2[1], 1);
-                                       color[2] = bound(0, color2[2], 1);
-                                       GL_Color(color[0], color[1], color[2], 1);
+                                       // 2/0/0/2 3D combine blendsquare path
+                                       memset(&m, 0, sizeof(m));
+                                       m.pointer_vertex = vertex3f;
+                                       m.tex[0] = R_GetTexture(bumptexture);
+                                       m.pointer_texcoord[0] = texcoord2f;
+                                       m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
+                                       m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+                                       R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin);
+                                       R_Mesh_State(&m);
+                                       GL_ColorMask(0,0,0,1);
+                                       // this squares the result
+                                       GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO);
+                                       GL_LockArrays(0, numverts);
                                        R_Mesh_Draw(numverts, numtriangles, elements);
+                                       GL_LockArrays(0, 0);
                                        c_rt_lightmeshes++;
                                        c_rt_lighttris += numtriangles;
+               
+                                       memset(&m, 0, sizeof(m));
+                                       m.pointer_vertex = vertex3f;
+                                       R_Mesh_State(&m);
+                                       GL_LockArrays(0, numverts);
+                                       // 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(numverts, numtriangles, elements);
+                                       c_rt_lightmeshes++;
+                                       c_rt_lighttris += numtriangles;
+                                       R_Mesh_Draw(numverts, numtriangles, elements);
+                                       c_rt_lightmeshes++;
+                                       c_rt_lighttris += numtriangles;
+                                       GL_LockArrays(0, 0);
+               
+                                       memset(&m, 0, sizeof(m));
+                                       m.pointer_vertex = vertex3f;
+                                       m.tex[0] = R_GetTexture(glosstexture);
+                                       m.pointer_texcoord[0] = texcoord2f;
+                                       m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
+#if USETEXMATRIX
+                                       m.pointer_texcoord3f[1] = vertex3f;
+                                       m.texmatrix[1] = *matrix_modeltoattenuationxyz;
+#else
+                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+                                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
                                }
-                               GL_LockArrays(0, 0);
-                       }
-                       else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && !lightcubemap /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare!
-                       {
-                               // 2/0/0/2 3D combine blendsquare path
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = vertex3f;
-                               m.tex[0] = R_GetTexture(bumptexture);
-                               m.pointer_texcoord[0] = texcoord2f;
-                               m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
-                               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                               m.pointer_texcoord[1] = varray_texcoord3f[1];
-                               R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin);
-                               R_Mesh_State(&m);
-                               GL_ColorMask(0,0,0,1);
-                               // this squares the result
-                               GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO);
-                               GL_LockArrays(0, numverts);
-                               R_Mesh_Draw(numverts, numtriangles, elements);
-                               GL_LockArrays(0, 0);
-                               c_rt_lightmeshes++;
-                               c_rt_lighttris += numtriangles;
-
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = vertex3f;
-                               R_Mesh_State(&m);
-                               GL_LockArrays(0, numverts);
-                               // 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(numverts, numtriangles, elements);
-                               c_rt_lightmeshes++;
-                               c_rt_lighttris += numtriangles;
-                               R_Mesh_Draw(numverts, numtriangles, elements);
-                               c_rt_lightmeshes++;
-                               c_rt_lighttris += numtriangles;
-                               GL_LockArrays(0, 0);
-
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = vertex3f;
-                               m.tex[0] = R_GetTexture(glosstexture);
-                               m.pointer_texcoord[0] = texcoord2f;
-                               m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
-                               m.pointer_texcoord[1] = varray_texcoord3f[1];
-                               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltoattenuationxyz);
-                               R_Mesh_State(&m);
-                               GL_LockArrays(0, numverts);
-                               GL_ColorMask(1,1,1,0);
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                               VectorScale(lightcolor, colorscale, color2);
-                               for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
+                               else
                                {
-                                       color[0] = bound(0, color2[0], 1);
-                                       color[1] = bound(0, color2[1], 1);
-                                       color[2] = bound(0, color2[2], 1);
-                                       GL_Color(color[0], color[1], color[2], 1);
+                                       // 2/0/0/2/2 2D combine blendsquare path
+                                       memset(&m, 0, sizeof(m));
+                                       m.pointer_vertex = vertex3f;
+                                       m.tex[0] = R_GetTexture(bumptexture);
+                                       m.pointer_texcoord[0] = texcoord2f;
+                                       m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
+                                       m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+                                       m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+                                       R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin);
+                                       R_Mesh_State(&m);
+                                       GL_ColorMask(0,0,0,1);
+                                       // this squares the result
+                                       GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO);
+                                       GL_LockArrays(0, numverts);
                                        R_Mesh_Draw(numverts, numtriangles, elements);
+                                       GL_LockArrays(0, 0);
                                        c_rt_lightmeshes++;
                                        c_rt_lighttris += numtriangles;
+               
+                                       memset(&m, 0, sizeof(m));
+                                       m.pointer_vertex = vertex3f;
+                                       R_Mesh_State(&m);
+                                       GL_LockArrays(0, numverts);
+                                       // 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(numverts, numtriangles, elements);
+                                       c_rt_lightmeshes++;
+                                       c_rt_lighttris += numtriangles;
+                                       R_Mesh_Draw(numverts, numtriangles, elements);
+                                       c_rt_lightmeshes++;
+                                       c_rt_lighttris += numtriangles;
+                                       GL_LockArrays(0, 0);
+               
+                                       memset(&m, 0, sizeof(m));
+                                       m.pointer_vertex = vertex3f;
+                                       m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+                                       m.pointer_texcoord3f[0] = vertex3f;
+                                       m.texmatrix[0] = *matrix_modeltoattenuationxyz;
+#else
+                                       m.pointer_texcoord[0] = varray_texcoord2f[0];
+                                       R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[0], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
+                                       m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+                                       m.pointer_texcoord3f[1] = vertex3f;
+                                       m.texmatrix[1] = *matrix_modeltoattenuationz;
+#else
+                                       m.pointer_texcoord[1] = varray_texcoord2f[1];
+                                       R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationz);
+#endif
+                                       R_Mesh_State(&m);
+                                       GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
+                                       GL_LockArrays(0, numverts);
+                                       R_Mesh_Draw(numverts, numtriangles, elements);
+                                       GL_LockArrays(0, 0);
+                                       c_rt_lightmeshes++;
+                                       c_rt_lighttris += numtriangles;
+               
+                                       memset(&m, 0, sizeof(m));
+                                       m.pointer_vertex = vertex3f;
+                                       m.tex[0] = R_GetTexture(glosstexture);
+                                       m.pointer_texcoord[0] = texcoord2f;
+                                       if (lightcubemap)
+                                       {
+                                               m.texcubemap[1] = R_GetTexture(lightcubemap);
+#if USETEXMATRIX
+                                               m.pointer_texcoord3f[1] = vertex3f;
+                                               m.texmatrix[1] = *matrix_modeltolight;
+#else
+                                               m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+                                               R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight);
+#endif
+                                       }
                                }
-                               GL_LockArrays(0, 0);
                        }
-                       else if (r_textureunits.integer >= 2 /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare!
+                       R_Mesh_State(&m);
+                       GL_ColorMask(1,1,1,0);
+                       GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+                       VectorScale(lightcolor, colorscale, color2);
+                       GL_LockArrays(0, numverts);
+                       for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
                        {
-                               // 2/0/0/2/2 2D combine blendsquare path
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = vertex3f;
-                               m.tex[0] = R_GetTexture(bumptexture);
-                               m.pointer_texcoord[0] = texcoord2f;
-                               m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
-                               m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
-                               m.pointer_texcoord[1] = varray_texcoord3f[1];
-                               R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin);
-                               R_Mesh_State(&m);
-                               GL_ColorMask(0,0,0,1);
-                               // this squares the result
-                               GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO);
-                               GL_LockArrays(0, numverts);
-                               R_Mesh_Draw(numverts, numtriangles, elements);
-                               GL_LockArrays(0, 0);
-                               c_rt_lightmeshes++;
-                               c_rt_lighttris += numtriangles;
-
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = vertex3f;
-                               R_Mesh_State(&m);
-                               GL_LockArrays(0, numverts);
-                               // 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)
+                               GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1);
                                R_Mesh_Draw(numverts, numtriangles, elements);
                                c_rt_lightmeshes++;
                                c_rt_lighttris += numtriangles;
-                               R_Mesh_Draw(numverts, numtriangles, elements);
-                               c_rt_lightmeshes++;
-                               c_rt_lighttris += numtriangles;
-                               GL_LockArrays(0, 0);
-
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = vertex3f;
-                               m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
-                               m.pointer_texcoord[0] = varray_texcoord2f[0];
-                               R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[0], numverts, vertex3f, matrix_modeltoattenuationxyz);
-                               m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
-                               m.pointer_texcoord[1] = varray_texcoord2f[1];
-                               R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationz);
-                               R_Mesh_State(&m);
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
-                               GL_LockArrays(0, numverts);
-                               R_Mesh_Draw(numverts, numtriangles, elements);
-                               GL_LockArrays(0, 0);
-                               c_rt_lightmeshes++;
-                               c_rt_lighttris += numtriangles;
-
-                               memset(&m, 0, sizeof(m));
-                               m.pointer_vertex = vertex3f;
-                               m.tex[0] = R_GetTexture(glosstexture);
-                               m.pointer_texcoord[0] = texcoord2f;
-                               if (lightcubemap)
-                               {
-                                       m.texcubemap[1] = R_GetTexture(lightcubemap);
-                                       m.pointer_texcoord[1] = varray_texcoord3f[1];
-                                       R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight);
-                               }
-                               R_Mesh_State(&m);
-                               GL_LockArrays(0, numverts);
-                               GL_ColorMask(1,1,1,0);
-                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                               VectorScale(lightcolor, colorscale, color2);
-                               for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
-                               {
-                                       color[0] = bound(0, color2[0], 1);
-                                       color[1] = bound(0, color2[1], 1);
-                                       color[2] = bound(0, color2[2], 1);
-                                       GL_Color(color[0], color[1], color[2], 1);
-                                       R_Mesh_Draw(numverts, numtriangles, elements);
-                                       c_rt_lightmeshes++;
-                                       c_rt_lighttris += numtriangles;
-                               }
-                               GL_LockArrays(0, 0);
                        }
+                       GL_LockArrays(0, 0);
                }
        }
        else
@@ -1757,8 +1777,25 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                        {
                                // voodoo2
                                m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+                               m.pointer_texcoord3f[1] = vertex3f;
+                               m.texmatrix[1] = *matrix_modeltoattenuationxyz;
+#else
                                m.pointer_texcoord[1] = varray_texcoord2f[1];
                                R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
+                               if (r_textureunits.integer >= 3)
+                               {
+                                       // Geforce3/Radeon class but not using dot3
+                                       m.tex[2] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+                                       m.pointer_texcoord3f[2] = vertex3f;
+                                       m.texmatrix[2] = *matrix_modeltoattenuationz;
+#else
+                                       m.pointer_texcoord[2] = varray_texcoord2f[2];
+                                       R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[2], numverts, vertex3f, matrix_modeltoattenuationz);
+#endif
+                               }
                        }
                        R_Mesh_State(&m);
                        for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
@@ -1766,10 +1803,12 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                color[0] = bound(0, color2[0], 1);
                                color[1] = bound(0, color2[1], 1);
                                color[2] = bound(0, color2[2], 1);
-                               if (r_textureunits.integer >= 2)
-                                       R_Shadow_VertexLightingWithXYAttenuationTexture(numverts, vertex3f, normal3f, color, matrix_modeltolight);
+                               if (r_textureunits.integer >= 3)
+                                       R_Shadow_VertexShading(numverts, vertex3f, normal3f, color, matrix_modeltolight);
+                               else if (r_textureunits.integer >= 2)
+                                       R_Shadow_VertexShadingWithZAttenuation(numverts, vertex3f, normal3f, color, matrix_modeltolight);
                                else
-                                       R_Shadow_VertexLighting(numverts, vertex3f, normal3f, color, matrix_modeltolight);
+                                       R_Shadow_VertexShadingWithXYZAttenuation(numverts, vertex3f, normal3f, color, matrix_modeltolight);
                                GL_LockArrays(0, numverts);
                                R_Mesh_Draw(numverts, numtriangles, elements);
                                GL_LockArrays(0, 0);
@@ -1819,7 +1858,7 @@ void R_RTLight_UpdateFromDLight(rtlight_t *rtlight, const dlight_t *light, int i
 
        rtlight->lightmap_cullradius = bound(0, rtlight->radius, 2048.0f);
        rtlight->lightmap_cullradius2 = rtlight->lightmap_cullradius * rtlight->lightmap_cullradius;
-       VectorScale(rtlight->color, rtlight->radius * d_lightstylevalue[rtlight->style] * 0.25f, rtlight->lightmap_light);
+       VectorScale(rtlight->color, rtlight->radius * d_lightstylevalue[rtlight->style] * 0.125f, rtlight->lightmap_light);
        rtlight->lightmap_subtract = 1.0f / rtlight->lightmap_cullradius2;
 }
 
@@ -1851,7 +1890,7 @@ void R_RTLight_Compile(rtlight_t *rtlight)
                // this variable directs the DrawShadowVolume and DrawLight code to capture into the mesh chain instead of rendering
                r_shadow_compilingrtlight = rtlight;
                R_Shadow_EnlargeClusterBuffer(model->brush.num_pvsclusters);
-               R_Shadow_EnlargeSurfaceBuffer(model->numsurfaces); 
+               R_Shadow_EnlargeSurfaceBuffer(model->nummodelsurfaces); 
                model->GetLightInfo(ent, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs, r_shadow_buffer_clusterlist, r_shadow_buffer_clusterpvs, &numclusters, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces);
                if (numclusters)
                {
@@ -1979,7 +2018,7 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes)
        else if (cl.worldmodel && cl.worldmodel->GetLightInfo)
        {
                R_Shadow_EnlargeClusterBuffer(cl.worldmodel->brush.num_pvsclusters);
-               R_Shadow_EnlargeSurfaceBuffer(cl.worldmodel->numsurfaces); 
+               R_Shadow_EnlargeSurfaceBuffer(cl.worldmodel->nummodelsurfaces); 
                cl.worldmodel->GetLightInfo(&cl_entities[0].render, rtlight->shadoworigin, rtlight->radius, cullmins, cullmaxs, r_shadow_buffer_clusterlist, r_shadow_buffer_clusterpvs, &numclusters, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces);
                clusterlist = r_shadow_buffer_clusterlist;
                clusterpvs = r_shadow_buffer_clusterpvs;
@@ -2013,7 +2052,24 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes)
        else
                cubemaptexture = NULL;
 
-       shadow = rtlight->shadow && (rtlight->isstatic ? r_shadow_worldshadows.integer : r_shadow_dlightshadows.integer);
+#if 1
+       shadow = rtlight->shadow && (rtlight->isstatic ? r_shadow_realtime_world_shadows.integer : (r_shadow_realtime_world.integer ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer));
+#else
+       shadow = false;
+       if (rtlight->shadow)
+       {
+               if (rtlight->isstatic)
+                       shadow = r_shadow_realtime_world_shadows.integer;
+               else
+               {
+                       if (r_shadow_realtime_world.integer)
+                               shadow = r_shadow_realtime_world_dlightshadows.integer;
+                       else
+                               shadow = r_shadow_realtime_dlight_shadows.integer;
+               }
+       }
+#endif
+
        if (shadow && (gl_stencil || visiblevolumes))
        {
                if (!visiblevolumes)
@@ -2067,7 +2123,10 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes)
                                if (!(ent->flags & RENDER_SHADOW) || !ent->model || !ent->model->DrawShadowVolume)
                                        continue;
                                Matrix4x4_Transform(&ent->inversematrix, rtlight->shadoworigin, relativelightorigin);
-                               ent->model->DrawShadowVolume(ent, relativelightorigin, rtlight->radius, ent->model->numsurfaces, ent->model->surfacelist);
+                               // light emitting entities should not cast their own shadow
+                               if (VectorLength2(relativelightorigin) < 0.1)
+                                       continue;
+                               ent->model->DrawShadowVolume(ent, relativelightorigin, rtlight->radius, ent->model->nummodelsurfaces, ent->model->surfacelist);
                        }
                }
        }
@@ -2108,7 +2167,7 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes)
                                        Matrix4x4_Concat(&matrix_modeltolight, &rtlight->matrix_worldtolight, &ent->matrix);
                                        Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &rtlight->matrix_worldtoattenuationxyz, &ent->matrix);
                                        Matrix4x4_Concat(&matrix_modeltoattenuationz, &rtlight->matrix_worldtoattenuationz, &ent->matrix);
-                                       ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rtlight->radius, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture, ent->model->numsurfaces, ent->model->surfacelist);
+                                       ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rtlight->radius, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture, ent->model->nummodelsurfaces, ent->model->surfacelist);
                                }
                        }
                }
@@ -2188,11 +2247,19 @@ static cubemapinfo_t cubemaps[MAX_CUBEMAPS];
 typedef struct suffixinfo_s
 {
        char *suffix;
-       int flipx, flipy, flipdiagonal;
+       qboolean flipx, flipy, flipdiagonal;
 }
 suffixinfo_t;
 static suffixinfo_t suffix[3][6] =
 {
+       {
+               {"px",   false, false, false},
+               {"nx",   false, false, false},
+               {"py",   false, false, false},
+               {"ny",   false, false, false},
+               {"pz",   false, false, false},
+               {"nz",   false, false, false}
+       },
        {
                {"posx", false, false, false},
                {"negx", false, false, false},
@@ -2202,20 +2269,12 @@ static suffixinfo_t suffix[3][6] =
                {"negz", false, false, false}
        },
        {
-               {"px", false, false, false},
-               {"nx", false, false, false},
-               {"py", false, false, false},
-               {"ny", false, false, false},
-               {"pz", false, false, false},
-               {"nz", false, false, false}
-       },
-       {
-               {"ft", true, false, true},
-               {"bk", false, true, true},
-               {"lf", true, true, false},
-               {"rt", false, false, false},
-               {"up", false, false, false},
-               {"dn", false, false, false}
+               {"rt",    true, false,  true},
+               {"lf",   false,  true,  true},
+               {"ft",    true,  true, false},
+               {"bk",   false, false, false},
+               {"up",    true, false,  true},
+               {"dn",    true, false,  true}
        }
 };
 
@@ -2231,30 +2290,39 @@ rtexture_t *R_Shadow_LoadCubemap(const char *basename)
        cubemapsize = 0;
        cubemappixels = NULL;
        cubemaptexture = NULL;
+       // keep trying different suffix groups (posx, px, rt) until one loads
        for (j = 0;j < 3 && !cubemappixels;j++)
        {
+               // load the 6 images in the suffix group
                for (i = 0;i < 6;i++)
                {
+                       // generate an image name based on the base and and suffix
                        snprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
+                       // load it
                        if ((image_rgba = loadimagepixels(name, false, cubemapsize, cubemapsize)))
                        {
+                               // an image loaded, make sure width and height are equal
                                if (image_width == image_height)
                                {
+                                       // if this is the first image to load successfully, allocate the cubemap memory
                                        if (!cubemappixels && image_width >= 1)
                                        {
                                                cubemapsize = image_width;
-                                               // note this clears to black, so unavailable sizes are black
+                                               // note this clears to black, so unavailable sides are black
                                                cubemappixels = Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
                                        }
+                                       // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
                                        if (cubemappixels)
                                                Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_rgba, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
                                }
                                else
                                        Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
+                               // free the image
                                Mem_Free(image_rgba);
                        }
                }
        }
+       // if a cubemap loaded, upload it
        if (cubemappixels)
        {
                if (!r_shadow_filters_texturepool)
@@ -2429,7 +2497,7 @@ void R_Shadow_LoadWorldLights(void)
        }
        FS_StripExtension (cl.worldmodel->name, name, sizeof (name));
        strlcat (name, ".rtlights", sizeof (name));
-       lightsstring = FS_LoadFile(name, false);
+       lightsstring = FS_LoadFile(name, tempmempool, false);
        if (lightsstring)
        {
                s = lightsstring;
@@ -2547,7 +2615,7 @@ void R_Shadow_LoadLightsFile(void)
        }
        FS_StripExtension (cl.worldmodel->name, name, sizeof (name));
        strlcat (name, ".lights", sizeof (name));
-       lightsstring = FS_LoadFile(name, false);
+       lightsstring = FS_LoadFile(name, tempmempool, false);
        if (lightsstring)
        {
                s = lightsstring;