]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
implemented and debugged BIH (Bounding Interval Hierarchy) code, more
[xonotic/darkplaces.git] / r_shadow.c
index 47f1a1bc1560dd246d0bb25c901d9ee1c9df6d82..b47711144f1845bff441a76804743a8b248ef7f4 100644 (file)
@@ -140,8 +140,6 @@ demonstrated by the game Doom3.
 #include "portals.h"
 #include "image.h"
 
-#define R_SHADOW_SHADOWMAP_NUMCUBEMAPS 8
-
 extern void R_Shadow_EditLights_Init(void);
 
 typedef enum r_shadow_rendermode_e
@@ -182,6 +180,7 @@ r_shadow_rendermode_t r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_N
 qboolean r_shadow_usingshadowmaprect;
 qboolean r_shadow_usingshadowmap2d;
 qboolean r_shadow_usingshadowmapcube;
+qboolean r_shadow_usingshadowmaportho;
 int r_shadow_shadowmapside;
 float r_shadow_shadowmap_texturescale[2];
 float r_shadow_shadowmap_parameters[4];
@@ -202,7 +201,9 @@ qboolean r_shadow_shadowmapvsdct;
 qboolean r_shadow_shadowmapsampler;
 int r_shadow_shadowmappcf;
 int r_shadow_shadowmapborder;
+matrix4x4_t r_shadow_shadowmapmatrix;
 int r_shadow_lightscissor[4];
+qboolean r_shadow_usingdeferredprepass;
 
 int maxshadowtriangles;
 int *shadowelements;
@@ -253,15 +254,29 @@ rtexture_t *r_shadow_shadowmapvsdcttexture;
 int r_shadow_shadowmapsize; // changes for each light based on distance
 int r_shadow_shadowmaplod; // changes for each light based on distance
 
+GLuint r_shadow_prepassgeometryfbo;
+GLuint r_shadow_prepasslightingfbo;
+int r_shadow_prepass_width;
+int r_shadow_prepass_height;
+rtexture_t *r_shadow_prepassgeometrydepthtexture;
+rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
+rtexture_t *r_shadow_prepasslightingdiffusetexture;
+rtexture_t *r_shadow_prepasslightingspeculartexture;
+
 // lights are reloaded when this changes
 char r_shadow_mapname[MAX_QPATH];
 
 // used only for light filters (cubemaps)
 rtexturepool_t *r_shadow_filters_texturepool;
 
+static const GLenum r_shadow_prepasslightingdrawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT};
+
 cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "0", "generate fake bumpmaps from diffuse textures at this bumpyness, try 4 to match tenebrae, higher values increase depth, requires r_restart to take effect"};
 cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4", "what magnitude to interpret _bump.tga textures as, higher values increase depth, requires r_restart to take effect"};
 cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1", "renders only one light, for level design purposes or debugging"};
+cvar_t r_shadow_deferred = {CVAR_SAVE, "r_shadow_deferred", "0", "uses image-based lighting instead of geometry-based lighting, the method used renders a depth image and a normalmap image, renders lights into separate diffuse and specular images, and then combines this into the normal rendering, requires r_shadow_shadowmapping"};
+cvar_t r_shadow_deferred_8bitrange = {CVAR_SAVE, "r_shadow_deferred_8bitrange", "2", "dynamic range of image-based lighting when using 32bit color (does not apply to fp)"};
+//cvar_t r_shadow_deferred_fp = {CVAR_SAVE, "r_shadow_deferred_fp", "0", "use 16bit (1) or 32bit (2) floating point for accumulation of image-based lighting"};
 cvar_t r_shadow_usenormalmap = {CVAR_SAVE, "r_shadow_usenormalmap", "1", "enables use of directional shading on lights"};
 cvar_t r_shadow_gloss = {CVAR_SAVE, "r_shadow_gloss", "1", "0 disables gloss (specularity) rendering, 1 uses gloss if textures are found, 2 forces a flat metallic specular effect on everything without textures (similar to tenebrae)"};
 cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.125", "how bright the forced flat gloss should look if r_shadow_gloss is 2"};
@@ -273,8 +288,7 @@ cvar_t r_shadow_lightattenuationdividebias = {0, "r_shadow_lightattenuationdivid
 cvar_t r_shadow_lightattenuationlinearscale = {0, "r_shadow_lightattenuationlinearscale", "2", "changes attenuation texture generation"};
 cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1", "renders all world lights brighter or darker"};
 cvar_t r_shadow_lightradiusscale = {0, "r_shadow_lightradiusscale", "1", "renders all world lights larger or smaller"};
-cvar_t r_shadow_portallight = {0, "r_shadow_portallight", "1", "use portal culling to exactly determine lit triangles when compiling world lights"};
-cvar_t r_shadow_projectdistance = {0, "r_shadow_projectdistance", "1000000", "how far to cast shadows"};
+cvar_t r_shadow_projectdistance = {0, "r_shadow_projectdistance", "0", "how far to cast shadows"};
 cvar_t r_shadow_frontsidecasting = {0, "r_shadow_frontsidecasting", "1", "whether to cast shadows from illuminated triangles (front side of model) or unlit triangles (back side of model)"};
 cvar_t r_shadow_realtime_dlight = {CVAR_SAVE, "r_shadow_realtime_dlight", "1", "enables rendering of dynamic lights such as explosions and rocket light"};
 cvar_t r_shadow_realtime_dlight_shadows = {CVAR_SAVE, "r_shadow_realtime_dlight_shadows", "1", "enables rendering of shadows from dynamic lights"};
@@ -285,8 +299,8 @@ cvar_t r_shadow_realtime_world_lightmaps = {CVAR_SAVE, "r_shadow_realtime_world_
 cvar_t r_shadow_realtime_world_shadows = {CVAR_SAVE, "r_shadow_realtime_world_shadows", "1", "enables rendering of shadows from world lights"};
 cvar_t r_shadow_realtime_world_compile = {0, "r_shadow_realtime_world_compile", "1", "enables compilation of world lights for higher performance rendering"};
 cvar_t r_shadow_realtime_world_compileshadow = {0, "r_shadow_realtime_world_compileshadow", "1", "enables compilation of shadows from world lights for higher performance rendering"};
-cvar_t r_shadow_realtime_world_compilesvbsp = {0, "r_shadow_realtime_world_compilesvbsp", "1", "enables svbsp optimization during compilation"};
-cvar_t r_shadow_realtime_world_compileportalculling = {0, "r_shadow_realtime_world_compileportalculling", "1", "enables portal-based culling optimization during compilation"};
+cvar_t r_shadow_realtime_world_compilesvbsp = {0, "r_shadow_realtime_world_compilesvbsp", "1", "enables svbsp optimization during compilation (slower than compileportalculling but more exact)"};
+cvar_t r_shadow_realtime_world_compileportalculling = {0, "r_shadow_realtime_world_compileportalculling", "0", "enables portal-based culling optimization during compilation (overrides compilesvbsp)"};
 cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1", "use scissor optimization of light rendering (restricts rendering to the portion of the screen affected by the light)"};
 cvar_t r_shadow_shadowmapping = {CVAR_SAVE, "r_shadow_shadowmapping", "0", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes, requires gl_fbo 1"};
 cvar_t r_shadow_shadowmapping_texturetype = {CVAR_SAVE, "r_shadow_shadowmapping_texturetype", "-1", "shadowmap texture types: -1 = auto-select, 0 = 2D, 1 = rectangle, 2 = cubemap"};
@@ -303,7 +317,6 @@ cvar_t r_shadow_shadowmapping_nearclip = {CVAR_SAVE, "r_shadow_shadowmapping_nea
 cvar_t r_shadow_shadowmapping_bias = {CVAR_SAVE, "r_shadow_shadowmapping_bias", "0.03", "shadowmap bias parameter (this is multiplied by nearclip * 1024 / lodsize)"};
 cvar_t r_shadow_shadowmapping_polygonfactor = {CVAR_SAVE, "r_shadow_shadowmapping_polygonfactor", "2", "slope-dependent shadowmapping bias"};
 cvar_t r_shadow_shadowmapping_polygonoffset = {CVAR_SAVE, "r_shadow_shadowmapping_polygonoffset", "0", "constant shadowmapping bias"};
-cvar_t r_shadow_culltriangles = {0, "r_shadow_culltriangles", "1", "performs more expensive tests to remove unnecessary triangles of lit surfaces"};
 cvar_t r_shadow_polygonfactor = {0, "r_shadow_polygonfactor", "0", "how much to enlarge shadow volume polygons when rendering (should be 0!)"};
 cvar_t r_shadow_polygonoffset = {0, "r_shadow_polygonoffset", "1", "how much to push shadow volumes into the distance when rendering, to reduce chances of zfighting artifacts (should not be less than 0)"};
 cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "1", "use 3D voxel textures for spherical attenuation rather than cylindrical (does not affect OpenGL 2.0 render path)"};
@@ -339,16 +352,6 @@ vec3_t r_editlights_cursorlocation;
 
 extern int con_vislines;
 
-typedef struct cubemapinfo_s
-{
-       char basename[64];
-       rtexture_t *texture;
-}
-cubemapinfo_t;
-
-static int numcubemaps;
-static cubemapinfo_t cubemaps[MAX_CUBEMAPS];
-
 void R_Shadow_UncompileWorldLights(void);
 void R_Shadow_ClearWorldLights(void);
 void R_Shadow_SaveWorldLights(void);
@@ -383,17 +386,18 @@ void R_Shadow_SetShadowMode(void)
        switch(vid.renderpath)
        {
        case RENDERPATH_GL20:
-               if(r_shadow_shadowmapping.integer && vid.support.ext_framebuffer_object)
+       case RENDERPATH_CGGL:
+               if ((r_shadow_shadowmapping.integer || r_shadow_deferred.integer) && vid.support.ext_framebuffer_object)
                {
                        if(r_shadow_shadowmapfilterquality < 0)
                        {
-                               if(strstr(gl_vendor, "NVIDIA")) 
+                               if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather)
+                                       r_shadow_shadowmappcf = 1;
+                               else if(strstr(gl_vendor, "NVIDIA") || strstr(gl_renderer, "Radeon HD")) 
                                {
                                        r_shadow_shadowmapsampler = vid.support.arb_shadow;
                                        r_shadow_shadowmappcf = 1;
                                }
-                               else if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather) 
-                                       r_shadow_shadowmappcf = 1;
                                else if(strstr(gl_vendor, "ATI")) 
                                        r_shadow_shadowmappcf = 1;
                                else 
@@ -447,6 +451,19 @@ void R_Shadow_SetShadowMode(void)
        }
 }
 
+qboolean R_Shadow_ShadowMappingEnabled(void)
+{
+       switch (r_shadow_shadowmode)
+       {
+       case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
+       case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
+       case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
+               return true;
+       default:
+               return false;
+       }
+}
+
 void R_Shadow_FreeShadowMaps(void)
 {
        int i;
@@ -493,7 +510,6 @@ void R_Shadow_FreeShadowMaps(void)
 void r_shadow_start(void)
 {
        // allocate vertex processing arrays
-       numcubemaps = 0;
        r_shadow_attenuationgradienttexture = NULL;
        r_shadow_attenuation2dtexture = NULL;
        r_shadow_attenuation3dtexture = NULL;
@@ -550,8 +566,12 @@ void r_shadow_start(void)
        r_shadow_buffer_shadowtrispvs = NULL;
        r_shadow_buffer_numlighttrispvsbytes = 0;
        r_shadow_buffer_lighttrispvs = NULL;
+
+       r_shadow_usingdeferredprepass = false;
+       r_shadow_prepass_width = r_shadow_prepass_height = 0;
 }
 
+static void R_Shadow_FreeDeferred(void);
 void r_shadow_shutdown(void)
 {
        CHECKGLERROR
@@ -559,8 +579,12 @@ void r_shadow_shutdown(void)
 
        R_Shadow_FreeShadowMaps();
 
+       r_shadow_usingdeferredprepass = false;
+       if (r_shadow_prepass_width)
+               R_Shadow_FreeDeferred();
+       r_shadow_prepass_width = r_shadow_prepass_height = 0;
+
        CHECKGLERROR
-       numcubemaps = 0;
        r_shadow_attenuationgradienttexture = NULL;
        r_shadow_attenuation2dtexture = NULL;
        r_shadow_attenuation3dtexture = NULL;
@@ -645,6 +669,9 @@ void R_Shadow_Init(void)
        Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap);
        Cvar_RegisterVariable(&r_shadow_usenormalmap);
        Cvar_RegisterVariable(&r_shadow_debuglight);
+       Cvar_RegisterVariable(&r_shadow_deferred);
+       Cvar_RegisterVariable(&r_shadow_deferred_8bitrange);
+//     Cvar_RegisterVariable(&r_shadow_deferred_fp);
        Cvar_RegisterVariable(&r_shadow_gloss);
        Cvar_RegisterVariable(&r_shadow_gloss2intensity);
        Cvar_RegisterVariable(&r_shadow_glossintensity);
@@ -655,7 +682,6 @@ void R_Shadow_Init(void)
        Cvar_RegisterVariable(&r_shadow_lightattenuationlinearscale);
        Cvar_RegisterVariable(&r_shadow_lightintensityscale);
        Cvar_RegisterVariable(&r_shadow_lightradiusscale);
-       Cvar_RegisterVariable(&r_shadow_portallight);
        Cvar_RegisterVariable(&r_shadow_projectdistance);
        Cvar_RegisterVariable(&r_shadow_frontsidecasting);
        Cvar_RegisterVariable(&r_shadow_realtime_dlight);
@@ -685,7 +711,6 @@ void R_Shadow_Init(void)
        Cvar_RegisterVariable(&r_shadow_shadowmapping_bias);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonfactor);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonoffset);
-       Cvar_RegisterVariable(&r_shadow_culltriangles);
        Cvar_RegisterVariable(&r_shadow_polygonfactor);
        Cvar_RegisterVariable(&r_shadow_polygonoffset);
        Cvar_RegisterVariable(&r_shadow_texture3d);
@@ -1308,7 +1333,6 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f,
                r_refdef.stats.lights_shadowtriangles += tris;
                CHECKGLERROR
                R_Mesh_VertexPointer(shadowvertex3f, 0, 0);
-               GL_LockArrays(0, outverts);
                if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
                {
                        // increment stencil if frontface is infront of depthbuffer
@@ -1330,7 +1354,6 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f,
                        qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
                }
                R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0);
-               GL_LockArrays(0, 0);
                CHECKGLERROR
        }
 }
@@ -1484,19 +1507,48 @@ int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
        }
        // this next test usually clips off more sides than the former, but occasionally clips fewer/different ones, so do both and combine results
        // check if frustum corners/origin cross plane sides
+#if 1
+    // infinite version, assumes frustum corners merely give direction and extend to infinite distance
+    Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.origin, p);
+    dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
+    masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
+    masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
+    dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
+    masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
+    masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
+    dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
+    masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
+    masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
+    for (i = 0;i < 4;i++)
+    {
+        Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.frustumcorner[i], n);
+        VectorSubtract(n, p, n);
+        dp = n[0] + n[1], dn = n[0] - n[1], ap = fabs(dp), an = fabs(dn);
+        if(ap > 0) masks[0] |= dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2);
+        if(an > 0) masks[1] |= dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2);
+        dp = n[1] + n[2], dn = n[1] - n[2], ap = fabs(dp), an = fabs(dn);
+        if(ap > 0) masks[2] |= dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4);
+        if(an > 0) masks[3] |= dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4);
+        dp = n[2] + n[0], dn = n[2] - n[0], ap = fabs(dp), an = fabs(dn);
+        if(ap > 0) masks[4] |= dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0);
+        if(an > 0) masks[5] |= dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0);
+    }
+#else
+    // finite version, assumes corners are a finite distance from origin dependent on far plane
        for (i = 0;i < 5;i++)
        {
                Matrix4x4_Transform(&rtlight->matrix_worldtolight, !i ? r_refdef.view.origin : r_refdef.view.frustumcorner[i-1], p);
-               dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn),
+               dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
                masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
                masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
-               dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn),
+               dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
                masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
                masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
-               dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn),
+               dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
                masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
                masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
        }
+#endif
        return sides & masks[0] & masks[1] & masks[2] & masks[3] & masks[4] & masks[5];
 }
 
@@ -1663,7 +1715,7 @@ static void R_Shadow_MakeTextures_MakeCorona(void)
                        pixels[y][x][3] = 255;
                }
        }
-       r_shadow_lightcorona = R_SkinFrame_LoadInternalBGRA("lightcorona", TEXF_PRECACHE | TEXF_FORCELINEAR, &pixels[0][0][0], 32, 32);
+       r_shadow_lightcorona = R_SkinFrame_LoadInternalBGRA("lightcorona", TEXF_FORCELINEAR, &pixels[0][0][0], 32, 32);
 }
 
 static unsigned int R_Shadow_MakeTextures_SamplePoint(float x, float y, float z)
@@ -1695,12 +1747,12 @@ static void R_Shadow_MakeTextures(void)
        // 1D gradient texture
        for (x = 0;x < ATTEN1DSIZE;x++)
                data[x] = R_Shadow_MakeTextures_SamplePoint((x + 0.5f) * (1.0f / ATTEN1DSIZE) * (1.0f / 0.9375), 0, 0);
-       r_shadow_attenuationgradienttexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation1d", ATTEN1DSIZE, 1, (unsigned char *)data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, NULL);
+       r_shadow_attenuationgradienttexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation1d", ATTEN1DSIZE, 1, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, NULL);
        // 2D circle texture
        for (y = 0;y < ATTEN2DSIZE;y++)
                for (x = 0;x < ATTEN2DSIZE;x++)
                        data[y*ATTEN2DSIZE+x] = R_Shadow_MakeTextures_SamplePoint(((x + 0.5f) * (2.0f / ATTEN2DSIZE) - 1.0f) * (1.0f / 0.9375), ((y + 0.5f) * (2.0f / ATTEN2DSIZE) - 1.0f) * (1.0f / 0.9375), 0);
-       r_shadow_attenuation2dtexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation2d", ATTEN2DSIZE, ATTEN2DSIZE, (unsigned char *)data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, NULL);
+       r_shadow_attenuation2dtexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation2d", ATTEN2DSIZE, ATTEN2DSIZE, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, NULL);
        // 3D sphere texture
        if (r_shadow_texture3d.integer && vid.support.ext_texture_3d)
        {
@@ -1708,7 +1760,7 @@ static void R_Shadow_MakeTextures(void)
                        for (y = 0;y < ATTEN3DSIZE;y++)
                                for (x = 0;x < ATTEN3DSIZE;x++)
                                        data[(z*ATTEN3DSIZE+y)*ATTEN3DSIZE+x] = R_Shadow_MakeTextures_SamplePoint(((x + 0.5f) * (2.0f / ATTEN3DSIZE) - 1.0f) * (1.0f / 0.9375), ((y + 0.5f) * (2.0f / ATTEN3DSIZE) - 1.0f) * (1.0f / 0.9375), ((z + 0.5f) * (2.0f / ATTEN3DSIZE) - 1.0f) * (1.0f / 0.9375));
-               r_shadow_attenuation3dtexture = R_LoadTexture3D(r_shadow_texturepool, "attenuation3d", ATTEN3DSIZE, ATTEN3DSIZE, ATTEN3DSIZE, (unsigned char *)data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, NULL);
+               r_shadow_attenuation3dtexture = R_LoadTexture3D(r_shadow_texturepool, "attenuation3d", ATTEN3DSIZE, ATTEN3DSIZE, ATTEN3DSIZE, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, NULL);
        }
        else
                r_shadow_attenuation3dtexture = NULL;
@@ -1717,7 +1769,7 @@ static void R_Shadow_MakeTextures(void)
        R_Shadow_MakeTextures_MakeCorona();
 
        // Editor light sprites
-       r_editlights_sprcursor = R_SkinFrame_LoadInternal8bit("gfx/editlights/cursor", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
+       r_editlights_sprcursor = R_SkinFrame_LoadInternal8bit("gfx/editlights/cursor", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
        "................"
        ".3............3."
        "..5...2332...5.."
@@ -1735,7 +1787,7 @@ static void R_Shadow_MakeTextures(void)
        ".3............3."
        "................"
        , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
-       r_editlights_sprlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/light", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
+       r_editlights_sprlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/light", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
        "................"
        "................"
        "......1111......"
@@ -1753,7 +1805,7 @@ static void R_Shadow_MakeTextures(void)
        "................"
        "................"
        , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
-       r_editlights_sprnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/noshadow", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
+       r_editlights_sprnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/noshadow", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
        "................"
        "................"
        "......1111......"
@@ -1771,7 +1823,7 @@ static void R_Shadow_MakeTextures(void)
        "................"
        "................"
        , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
-       r_editlights_sprcubemaplight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemaplight", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
+       r_editlights_sprcubemaplight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemaplight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
        "................"
        "................"
        "......2772......"
@@ -1789,7 +1841,7 @@ static void R_Shadow_MakeTextures(void)
        "................"
        "................"
        , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
-       r_editlights_sprcubemapnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemapnoshadowlight", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
+       r_editlights_sprcubemapnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemapnoshadowlight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
        "................"
        "................"
        "......2772......"
@@ -1807,7 +1859,7 @@ static void R_Shadow_MakeTextures(void)
        "................"
        "................"
        , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
-       r_editlights_sprselection = R_SkinFrame_LoadInternal8bit("gfx/editlights/selection", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (unsigned char *)
+       r_editlights_sprselection = R_SkinFrame_LoadInternal8bit("gfx/editlights/selection", TEXF_ALPHA | TEXF_CLAMP, (unsigned char *)
        "................"
        ".777752..257777."
        ".742........247."
@@ -1883,6 +1935,7 @@ void R_Shadow_RenderMode_Begin(void)
        switch(vid.renderpath)
        {
        case RENDERPATH_GL20:
+       case RENDERPATH_CGGL:
                r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_GLSL;
                break;
        case RENDERPATH_GL13:
@@ -1939,19 +1992,20 @@ void R_Shadow_RenderMode_Reset(void)
        qglDepthFunc(GL_LEQUAL);CHECKGLERROR
        GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
        qglDisable(GL_STENCIL_TEST);CHECKGLERROR
-       qglStencilMask(~0);CHECKGLERROR
+       qglStencilMask(255);CHECKGLERROR
        qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
-       qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
+       qglStencilFunc(GL_ALWAYS, 128, 255);CHECKGLERROR
        r_refdef.view.cullface_front = r_shadow_cullface_front;
        r_refdef.view.cullface_back = r_shadow_cullface_back;
        GL_CullFace(r_refdef.view.cullface_back);
        GL_Color(1, 1, 1, 1);
        GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
        GL_BlendFunc(GL_ONE, GL_ZERO);
-       R_SetupGenericShader(false);
+       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
        r_shadow_usingshadowmaprect = false;
        r_shadow_usingshadowmapcube = false;
        r_shadow_usingshadowmap2d = false;
+       r_shadow_usingshadowmaportho = false;
        CHECKGLERROR
 }
 
@@ -1971,7 +2025,7 @@ void R_Shadow_RenderMode_StencilShadowVolumes(qboolean zpass)
        R_Shadow_RenderMode_Reset();
        GL_ColorMask(0, 0, 0, 0);
        GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
-       R_SetupDepthOrShadowShader();
+       R_SetupShader_DepthOrShadow();
        qglDepthFunc(GL_LESS);CHECKGLERROR
        qglEnable(GL_STENCIL_TEST);CHECKGLERROR
        r_shadow_rendermode = mode;
@@ -1993,20 +2047,20 @@ void R_Shadow_RenderMode_StencilShadowVolumes(qboolean zpass)
                GL_CullFace(GL_NONE);
                qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
                qglActiveStencilFaceEXT(r_refdef.view.cullface_front);CHECKGLERROR
-               qglStencilMask(~0);CHECKGLERROR
+               qglStencilMask(255);CHECKGLERROR
                qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR
                qglActiveStencilFaceEXT(r_refdef.view.cullface_back);CHECKGLERROR
-               qglStencilMask(~0);CHECKGLERROR
+               qglStencilMask(255);CHECKGLERROR
                qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR
                break;
        case R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE:
                GL_CullFace(GL_NONE);
                qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
                qglActiveStencilFaceEXT(r_refdef.view.cullface_front);CHECKGLERROR
-               qglStencilMask(~0);CHECKGLERROR
+               qglStencilMask(255);CHECKGLERROR
                qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
                qglActiveStencilFaceEXT(r_refdef.view.cullface_back);CHECKGLERROR
-               qglStencilMask(~0);CHECKGLERROR
+               qglStencilMask(255);CHECKGLERROR
                qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
                break;
        }
@@ -2029,29 +2083,69 @@ static void R_Shadow_MakeVSDCT(void)
                0,   0, 0x33, 0xFF, // +Z: <0, 0>, <0.5, 2.5>
                0,   0, 0x99, 0xFF, // -Z: <0, 0>, <1.5, 2.5>
        };
-       r_shadow_shadowmapvsdcttexture = R_LoadTextureCubeMap(r_shadow_texturepool, "shadowmapvsdct", 1, data, TEXTYPE_RGBA, TEXF_ALWAYSPRECACHE | TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, NULL); 
+       r_shadow_shadowmapvsdcttexture = R_LoadTextureCubeMap(r_shadow_texturepool, "shadowmapvsdct", 1, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, NULL);
 }
 
-void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size)
+static void R_Shadow_MakeShadowMap(int side, int size)
 {
        int status;
-       int maxsize;
+       switch (r_shadow_shadowmode)
+       {
+       case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
+               if (r_shadow_shadowmap2dtexture) return;
+               r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
+               qglGenFramebuffersEXT(1, &r_shadow_fbo2d);CHECKGLERROR
+               qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbo2d);CHECKGLERROR
+               qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_shadowmap2dtexture), 0);CHECKGLERROR
+               break;
+       case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
+               if (r_shadow_shadowmaprectangletexture) return;
+               r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", size*2, size*3, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
+               qglGenFramebuffersEXT(1, &r_shadow_fborectangle);CHECKGLERROR
+               qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
+               qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, R_GetTexture(r_shadow_shadowmaprectangletexture), 0);CHECKGLERROR
+               break;
+       case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
+               if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]) return;
+               r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", size, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
+               qglGenFramebuffersEXT(1, &r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
+               qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
+               qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
+               break;
+       default:
+               return;
+       }
+       // render depth into the fbo, do not render color at all
+       qglDrawBuffer(GL_NONE);CHECKGLERROR
+       qglReadBuffer(GL_NONE);CHECKGLERROR
+       status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
+       if (status != GL_FRAMEBUFFER_COMPLETE_EXT && (r_shadow_shadowmapping.integer || r_shadow_deferred.integer))
+       {
+               Con_Printf("R_Shadow_MakeShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
+               Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
+               Cvar_SetValueQuick(&r_shadow_deferred, 0);
+       }
+}
+       
+void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size)
+{
        float nearclip, farclip, bias;
        r_viewport_t viewport;
+       int flipped;
        GLuint fbo = 0;
        CHECKGLERROR
-       maxsize = r_shadow_shadowmapmaxsize;
        nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
        farclip = 1.0f;
        bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
-       r_shadow_shadowmap_parameters[2] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip);
-       r_shadow_shadowmap_parameters[3] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
+       r_shadow_shadowmap_parameters[1] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
+       r_shadow_shadowmap_parameters[3] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip);
        r_shadow_shadowmapside = side;
        r_shadow_shadowmapsize = size;
-       if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
+       switch (r_shadow_shadowmode)
        {
+       case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
                r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
-               r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
+               r_shadow_shadowmap_parameters[2] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
                R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
                if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D) goto init_done;
 
@@ -2059,34 +2153,16 @@ void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size)
                if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
                        R_Shadow_MakeVSDCT();
                if (!r_shadow_shadowmap2dtexture)
-               {
-#if 1
-                       int w = maxsize*2, h = vid.support.arb_texture_non_power_of_two ? maxsize*3 : maxsize*4;
-                       r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", w, h, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
-                       qglGenFramebuffersEXT(1, &r_shadow_fbo2d);CHECKGLERROR
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbo2d);CHECKGLERROR
-                       qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_shadowmap2dtexture), 0);CHECKGLERROR
-            // render depth into the fbo, do not render color at all
-                       qglDrawBuffer(GL_NONE);CHECKGLERROR
-                       qglReadBuffer(GL_NONE);CHECKGLERROR
-                       status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
-                       if (status != GL_FRAMEBUFFER_COMPLETE_EXT && r_shadow_shadowmapping.integer)
-                       {
-                               Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
-                               Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
-                       }
-#endif
-               }
+                       R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize);
                CHECKGLERROR
                if (r_shadow_shadowmap2dtexture) fbo = r_shadow_fbo2d;
                r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture);
                r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture);
                r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
-       }
-       else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE)
-       {
+               break;
+       case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
                r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
-               r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
+               r_shadow_shadowmap_parameters[2] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
                R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
                if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE) goto init_done;
 
@@ -2094,71 +2170,41 @@ void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size)
                if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
                        R_Shadow_MakeVSDCT();
                if (!r_shadow_shadowmaprectangletexture)
-               {
-#if 1
-                       r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*3, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
-                       qglGenFramebuffersEXT(1, &r_shadow_fborectangle);CHECKGLERROR
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
-                       qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, R_GetTexture(r_shadow_shadowmaprectangletexture), 0);CHECKGLERROR
-                       // render depth into the fbo, do not render color at all
-                       qglDrawBuffer(GL_NONE);CHECKGLERROR
-                       qglReadBuffer(GL_NONE);CHECKGLERROR
-                       status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
-                       if (status != GL_FRAMEBUFFER_COMPLETE_EXT && r_shadow_shadowmapping.integer)
-                       {
-                               Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
-                               Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
-                       }
-#endif
-               }
+                       R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize);
                CHECKGLERROR
                if(r_shadow_shadowmaprectangletexture) fbo = r_shadow_fborectangle;
                r_shadow_shadowmap_texturescale[0] = 1.0f;
                r_shadow_shadowmap_texturescale[1] = 1.0f;
                r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE;
-       }
-       else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
-       {
+               break;
+       case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
                r_shadow_shadowmap_parameters[0] = 1.0f;
-               r_shadow_shadowmap_parameters[1] = 1.0f;
+               r_shadow_shadowmap_parameters[2] = 1.0f;
                R_Viewport_InitCubeSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, nearclip, farclip, NULL);
                if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE) goto init_done;
 
                // simple cube approach
                if (!r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod])
-               {
- #if 1
-                       r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", size, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
-                       qglGenFramebuffersEXT(1, &r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
-                       qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
-                       // render depth into the fbo, do not render color at all
-                       qglDrawBuffer(GL_NONE);CHECKGLERROR
-                       qglReadBuffer(GL_NONE);CHECKGLERROR
-                       status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
-                       if (status != GL_FRAMEBUFFER_COMPLETE_EXT && r_shadow_shadowmapping.integer)
-                       {
-                               Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
-                               Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
-                       }
- #endif
-               }
+                       R_Shadow_MakeShadowMap(side, size);
                CHECKGLERROR
                if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]) fbo = r_shadow_fbocubeside[r_shadow_shadowmaplod];
                r_shadow_shadowmap_texturescale[0] = 0.0f;
                r_shadow_shadowmap_texturescale[1] = 0.0f;
                r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE;
+               break;
+       default:
+               break;
        }
 
        R_Shadow_RenderMode_Reset();
        if (fbo)
        {
                qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);CHECKGLERROR
-               R_SetupDepthOrShadowShader();
+               R_SetupShader_DepthOrShadow();
        }
        else
        {
-               R_SetupShowDepthShader();
+               R_SetupShader_ShowDepth();
                qglClearColor(1,1,1,1);CHECKGLERROR
        }
        CHECKGLERROR
@@ -2170,20 +2216,35 @@ void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size)
 
 init_done:
        R_SetViewport(&viewport);
-       GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
-       if(r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D || r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE)
+       switch (r_shadow_rendermode)
        {
-               int flipped = (side&1)^(side>>2);
+       case R_SHADOW_RENDERMODE_SHADOWMAP2D:
+       case R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE:
+               flipped = (side & 1) ^ (side >> 2);
                r_refdef.view.cullface_front = flipped ? r_shadow_cullface_back : r_shadow_cullface_front;
                r_refdef.view.cullface_back = flipped ? r_shadow_cullface_front : r_shadow_cullface_back;
                GL_CullFace(r_refdef.view.cullface_back);
-       }
-       else if(r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE)
-       {
+               if ((clear & ((2 << side) - 1)) == (1 << side)) // only clear if the side is the first in the mask
+               {
+                       // get tightest scissor rectangle that encloses all viewports in the clear mask
+                       int x1 = clear & 0x15 ? 0 : size;
+                       int x2 = clear & 0x2A ? 2 * size : size;
+                       int y1 = clear & 0x03 ? 0 : (clear & 0xC ? size : 2 * size);
+                       int y2 = clear & 0x30 ? 3 * size : (clear & 0xC ? 2 * size : size);
+                       GL_Scissor(x1, y1, x2 - x1, y2 - y1);
+                       GL_Clear(GL_DEPTH_BUFFER_BIT);
+               }
+               GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
+               break;
+       case R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE:
                qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
+               GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
+               if (clear)
+                       GL_Clear(GL_DEPTH_BUFFER_BIT);
+               break;
+       default:
+               break;
        }
-       if (clear)
-               qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |  GL_STENCIL_BUFFER_BIT);
        CHECKGLERROR
 }
 
@@ -2208,46 +2269,112 @@ void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qb
                qglEnable(GL_STENCIL_TEST);CHECKGLERROR
                // only draw light where this geometry was already rendered AND the
                // stencil is 128 (values other than this mean shadow)
-               qglStencilFunc(GL_EQUAL, 128, ~0);CHECKGLERROR
+               qglStencilFunc(GL_EQUAL, 128, 255);CHECKGLERROR
        }
        r_shadow_rendermode = r_shadow_lightingrendermode;
        // do global setup needed for the chosen lighting mode
        if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL)
        {
-               R_Mesh_TexBindAll(GL20TU_CUBE, 0, 0, R_GetTexture(rsurface.rtlight->currentcubemap), 0); // light filter
                GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 0);
                CHECKGLERROR
+       }
+       if (shadowmapping)
+       {
+               switch (r_shadow_shadowmode)
+               {
+               case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
+                       r_shadow_usingshadowmap2d = true;
+                       break;
+               case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
+                       r_shadow_usingshadowmaprect = true;
+                       break;
+               case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
+                       r_shadow_usingshadowmapcube = true;
+                       break;
+               default:
+                       break;
+               }
+       }
+       R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
+       CHECKGLERROR
+}
+
+static const unsigned short bboxelements[36] =
+{
+       5, 1, 3, 5, 3, 7,
+       6, 2, 0, 6, 0, 4,
+       7, 3, 2, 7, 2, 6,
+       4, 0, 1, 4, 1, 5,
+       4, 5, 7, 4, 7, 6,
+       1, 0, 2, 1, 2, 3,
+};
+
+static const float bboxpoints[8][3] =
+{
+       {-1,-1,-1},
+       { 1,-1,-1},
+       {-1, 1,-1},
+       { 1, 1,-1},
+       {-1,-1, 1},
+       { 1,-1, 1},
+       {-1, 1, 1},
+       { 1, 1, 1},
+};
+
+void R_Shadow_RenderMode_DrawDeferredLight(qboolean stenciltest, qboolean shadowmapping)
+{
+       int i;
+       float vertex3f[8*3];
+       const matrix4x4_t *matrix = &rsurface.rtlight->matrix_lighttoworld;
+       CHECKGLERROR
+       R_Shadow_RenderMode_Reset();
+       r_shadow_rendermode = r_shadow_lightingrendermode;
+       // do global setup needed for the chosen lighting mode
+       {
+               R_EntityMatrix(&identitymatrix);
+               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+               if (stenciltest)
+               {
+                       qglEnable(GL_STENCIL_TEST);CHECKGLERROR
+                       // only draw light where this geometry was already rendered AND the
+                       // stencil is 128 (values other than this mean shadow)
+                       qglStencilFunc(GL_EQUAL, 128, 255);CHECKGLERROR
+               }
+               qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_prepasslightingfbo);CHECKGLERROR
                if (shadowmapping)
                {
-                       if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
+                       switch (r_shadow_shadowmode)
                        {
+                       case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
                                r_shadow_usingshadowmap2d = true;
-                               R_Mesh_TexBind(GL20TU_SHADOWMAP2D, R_GetTexture(r_shadow_shadowmap2dtexture));
-                               CHECKGLERROR
-                       }
-                       else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE)
-                       {
+                               break;
+                       case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
                                r_shadow_usingshadowmaprect = true;
-                               R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT, 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture));
-                               CHECKGLERROR
-                       }
-                       else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
-                       {
+                               break;
+                       case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
                                r_shadow_usingshadowmapcube = true;
-                               R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE, 0, 0, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
-                               CHECKGLERROR
-                       }
-
-                       if (r_shadow_shadowmapvsdct && (r_shadow_usingshadowmap2d || r_shadow_usingshadowmaprect))
-                       {
-                               R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION, 0, 0, R_GetTexture(r_shadow_shadowmapvsdcttexture), 0);
-                               CHECKGLERROR
+                               break;
+                       default:
+                               break;
                        }
                }
+
+               // render the lighting
+               R_SetupShader_DeferredLight(rsurface.rtlight);
+               for (i = 0;i < 8;i++)
+                       Matrix4x4_Transform(matrix, bboxpoints[i], vertex3f + i*3);
+               CHECKGLERROR
+               R_Mesh_VertexPointer(vertex3f, 0, 0);
+               R_Mesh_ColorPointer(NULL, 0, 0);
+               GL_ColorMask(1,1,1,1);
+               GL_DepthMask(false);
+               GL_DepthRange(0, 1);
+               GL_PolygonOffset(0, 0);
+               GL_DepthTest(true);
+               qglDepthFunc(GL_GREATER);CHECKGLERROR
+               GL_CullFace(r_refdef.view.cullface_back);
+               R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
        }
-       R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
-       //GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-       CHECKGLERROR
 }
 
 void R_Shadow_RenderMode_VisibleShadowVolumes(void)
@@ -2278,7 +2405,7 @@ void R_Shadow_RenderMode_VisibleLighting(qboolean stenciltest, qboolean transpar
        if (stenciltest)
        {
                qglEnable(GL_STENCIL_TEST);CHECKGLERROR
-               qglStencilFunc(GL_EQUAL, 128, ~0);CHECKGLERROR
+               qglStencilFunc(GL_EQUAL, 128, 255);CHECKGLERROR
        }
        r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLELIGHTING;
 }
@@ -2596,44 +2723,16 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
        }
 }
 
-static void R_Shadow_RenderLighting_VisibleLighting(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject, 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 ambientscale, float diffusescale, float specularscale, qboolean dopants, qboolean doshirt)
+static void R_Shadow_RenderLighting_VisibleLighting(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject)
 {
        // used to display how many times a surface is lit for level design purposes
        R_Mesh_Draw(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject);
 }
 
-static void R_Shadow_RenderLighting_Light_GLSL(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject, 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 ambientscale, float diffusescale, float specularscale, qboolean dopants, qboolean doshirt)
+static void R_Shadow_RenderLighting_Light_GLSL(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject, const vec3_t lightcolor, float ambientscale, float diffusescale, float specularscale)
 {
        // ARB2 GLSL shader path (GFFX5200, Radeon 9500)
-       R_SetupSurfaceShader(lightcolorbase, false, ambientscale, diffusescale, specularscale, RSURFPASS_RTLIGHT);
-       if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
-               R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
-       else
-               R_Mesh_ColorPointer(NULL, 0, 0);
-       R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
-       R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
-       R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
-       R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
-       R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
-       if (rsurface.texture->backgroundcurrentskinframe)
-       {
-               R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
-               R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
-               R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
-               R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
-       }
-       //R_Mesh_TexBindAll(GL20TU_CUBE, 0, 0, R_GetTexture(rsurface.rtlight->currentcubemap), 0);
-       R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
-       if(rsurface.texture->colormapping)
-       {
-               R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
-               R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
-       }
-       R_Mesh_TexBind(GL20TU_ATTENUATION, R_GetTexture(r_shadow_attenuationgradienttexture));
-       R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
-       R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
-       R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
-       R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
+       R_SetupShader_Surface(lightcolor, false, ambientscale, diffusescale, specularscale, RSURFPASS_RTLIGHT);
        if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
        {
                qglDepthFunc(GL_EQUAL);CHECKGLERROR
@@ -2657,9 +2756,9 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve
        const int *e;
        float *c;
        int maxtriangles = 4096;
-       int newelements[4096*3];
+       static int newelements[4096*3];
        R_Shadow_RenderLighting_Light_Vertex_Shading(firstvertex, numvertices, numtriangles, element3i, diffusecolor2, ambientcolor2);
-       for (renders = 0;renders < 64;renders++)
+       for (renders = 0;renders < 4;renders++)
        {
                stop = true;
                newfirstvertex = 0;
@@ -2734,90 +2833,67 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve
        }
 }
 
-static void R_Shadow_RenderLighting_Light_Vertex(int firstvertex, int numvertices, int numtriangles, const int *element3i, 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 ambientscale, float diffusescale, float specularscale, qboolean dopants, qboolean doshirt)
+static void R_Shadow_RenderLighting_Light_Vertex(int firstvertex, int numvertices, int numtriangles, const int *element3i, const vec3_t lightcolor, float ambientscale, float diffusescale)
 {
        // OpenGL 1.1 path (anything)
        float ambientcolorbase[3], diffusecolorbase[3];
        float ambientcolorpants[3], diffusecolorpants[3];
        float ambientcolorshirt[3], diffusecolorshirt[3];
-       rmeshstate_t m;
-       VectorScale(lightcolorbase, ambientscale * 2 * r_refdef.view.colorscale, ambientcolorbase);
-       VectorScale(lightcolorbase, diffusescale * 2 * r_refdef.view.colorscale, diffusecolorbase);
-       VectorScale(lightcolorpants, ambientscale * 2 * r_refdef.view.colorscale, ambientcolorpants);
-       VectorScale(lightcolorpants, diffusescale * 2 * r_refdef.view.colorscale, diffusecolorpants);
-       VectorScale(lightcolorshirt, ambientscale * 2 * r_refdef.view.colorscale, ambientcolorshirt);
-       VectorScale(lightcolorshirt, diffusescale * 2 * r_refdef.view.colorscale, diffusecolorshirt);
+       const float *surfacecolor = rsurface.texture->dlightcolor;
+       const float *surfacepants = rsurface.colormap_pantscolor;
+       const float *surfaceshirt = rsurface.colormap_shirtcolor;
+       rtexture_t *basetexture = rsurface.texture->basetexture;
+       rtexture_t *pantstexture = rsurface.texture->pantstexture;
+       rtexture_t *shirttexture = rsurface.texture->shirttexture;
+       qboolean dopants = pantstexture && VectorLength2(surfacepants) >= (1.0f / 1048576.0f);
+       qboolean doshirt = shirttexture && VectorLength2(surfaceshirt) >= (1.0f / 1048576.0f);
+       ambientscale *= 2 * r_refdef.view.colorscale;
+       diffusescale *= 2 * r_refdef.view.colorscale;
+       ambientcolorbase[0] = lightcolor[0] * ambientscale * surfacecolor[0];ambientcolorbase[1] = lightcolor[1] * ambientscale * surfacecolor[1];ambientcolorbase[2] = lightcolor[2] * ambientscale * surfacecolor[2];
+       diffusecolorbase[0] = lightcolor[0] * diffusescale * surfacecolor[0];diffusecolorbase[1] = lightcolor[1] * diffusescale * surfacecolor[1];diffusecolorbase[2] = lightcolor[2] * diffusescale * surfacecolor[2];
+       ambientcolorpants[0] = ambientcolorbase[0] * surfacepants[0];ambientcolorpants[1] = ambientcolorbase[1] * surfacepants[1];ambientcolorpants[2] = ambientcolorbase[2] * surfacepants[2];
+       diffusecolorpants[0] = diffusecolorbase[0] * surfacepants[0];diffusecolorpants[1] = diffusecolorbase[1] * surfacepants[1];diffusecolorpants[2] = diffusecolorbase[2] * surfacepants[2];
+       ambientcolorshirt[0] = ambientcolorbase[0] * surfaceshirt[0];ambientcolorshirt[1] = ambientcolorbase[1] * surfaceshirt[1];ambientcolorshirt[2] = ambientcolorbase[2] * surfaceshirt[2];
+       diffusecolorshirt[0] = diffusecolorbase[0] * surfaceshirt[0];diffusecolorshirt[1] = diffusecolorbase[1] * surfaceshirt[1];diffusecolorshirt[2] = diffusecolorbase[2] * surfaceshirt[2];
+       R_Mesh_TexBind(0, basetexture);
+       R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
+       R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
+       R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
        switch(r_shadow_rendermode)
        {
        case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
-               memset(&m, 0, sizeof(m));
-               m.tex[0] = R_GetTexture(basetexture);
-               m.texmatrix[0] = rsurface.texture->currenttexmatrix;
-               m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
-               m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
-               m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
-               m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
-               m.texmatrix[1] = rsurface.entitytoattenuationxyz;
-               m.pointer_texcoord3f[1] = rsurface.vertex3f;
-               m.pointer_texcoord_bufferobject[1] = rsurface.vertex3f_bufferobject;
-               m.pointer_texcoord_bufferoffset[1] = rsurface.vertex3f_bufferoffset;
-               R_Mesh_TextureState(&m);
+               R_Mesh_TexBind(1, r_shadow_attenuation3dtexture);
+               R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz);
+               R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1);
+               R_Mesh_TexCoordPointer(1, 3, rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
                break;
        case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
-               memset(&m, 0, sizeof(m));
-               m.tex[0] = R_GetTexture(basetexture);
-               m.texmatrix[0] = rsurface.texture->currenttexmatrix;
-               m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
-               m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
-               m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
-               m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
-               m.texmatrix[1] = rsurface.entitytoattenuationxyz;
-               m.pointer_texcoord3f[1] = rsurface.vertex3f;
-               m.pointer_texcoord_bufferobject[1] = rsurface.vertex3f_bufferobject;
-               m.pointer_texcoord_bufferoffset[1] = rsurface.vertex3f_bufferoffset;
-               m.tex[2] = R_GetTexture(r_shadow_attenuation2dtexture);
-               m.texmatrix[2] = rsurface.entitytoattenuationz;
-               m.pointer_texcoord3f[2] = rsurface.vertex3f;
-               m.pointer_texcoord_bufferobject[2] = rsurface.vertex3f_bufferobject;
-               m.pointer_texcoord_bufferoffset[2] = rsurface.vertex3f_bufferoffset;
-               R_Mesh_TextureState(&m);
-               break;
+               R_Mesh_TexBind(2, r_shadow_attenuation2dtexture);
+               R_Mesh_TexMatrix(2, &rsurface.entitytoattenuationz);
+               R_Mesh_TexCombine(2, GL_MODULATE, GL_MODULATE, 1, 1);
+               R_Mesh_TexCoordPointer(2, 3, rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
+               // fall through
        case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
-               memset(&m, 0, sizeof(m));
-               m.tex[0] = R_GetTexture(basetexture);
-               m.texmatrix[0] = rsurface.texture->currenttexmatrix;
-               m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
-               m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
-               m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
-               m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
-               m.texmatrix[1] = rsurface.entitytoattenuationxyz;
-               m.pointer_texcoord3f[1] = rsurface.vertex3f;
-               m.pointer_texcoord_bufferobject[1] = rsurface.vertex3f_bufferobject;
-               m.pointer_texcoord_bufferoffset[1] = rsurface.vertex3f_bufferoffset;
-               R_Mesh_TextureState(&m);
+               R_Mesh_TexBind(1, r_shadow_attenuation2dtexture);
+               R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz);
+               R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1);
+               R_Mesh_TexCoordPointer(1, 3, rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
                break;
        case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
-               memset(&m, 0, sizeof(m));
-               m.tex[0] = R_GetTexture(basetexture);
-               m.texmatrix[0] = rsurface.texture->currenttexmatrix;
-               m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
-               m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
-               m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
-               R_Mesh_TextureState(&m);
                break;
        default:
                break;
        }
-       //R_Mesh_TexBind(0, R_GetTexture(basetexture));
+       //R_Mesh_TexBind(0, basetexture);
        R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorbase, ambientcolorbase);
        if (dopants)
        {
-               R_Mesh_TexBind(0, R_GetTexture(pantstexture));
+               R_Mesh_TexBind(0, pantstexture);
                R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorpants, ambientcolorpants);
        }
        if (doshirt)
        {
-               R_Mesh_TexBind(0, R_GetTexture(shirttexture));
+               R_Mesh_TexBind(0, shirttexture);
                R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorshirt, ambientcolorshirt);
        }
 }
@@ -2827,12 +2903,8 @@ void R_Shadow_RenderLighting(int firstvertex, int numvertices, int firsttriangle
 {
        float ambientscale, diffusescale, specularscale;
        qboolean negated;
-       vec3_t lightcolorbase, lightcolorpants, lightcolorshirt;
-       rtexture_t *nmap;
-       // calculate colors to render this texture with
-       lightcolorbase[0] = rsurface.rtlight->currentcolor[0] * rsurface.texture->dlightcolor[0];
-       lightcolorbase[1] = rsurface.rtlight->currentcolor[1] * rsurface.texture->dlightcolor[1];
-       lightcolorbase[2] = rsurface.rtlight->currentcolor[2] * rsurface.texture->dlightcolor[2];
+       float lightcolor[3];
+       VectorCopy(rsurface.rtlight->currentcolor, lightcolor);
        ambientscale = rsurface.rtlight->ambientscale;
        diffusescale = rsurface.rtlight->diffusescale;
        specularscale = rsurface.rtlight->specularscale * rsurface.texture->specularscale;
@@ -2842,79 +2914,33 @@ void R_Shadow_RenderLighting(int firstvertex, int numvertices, int firsttriangle
                diffusescale = 0;
                specularscale = 0;
        }
-       if ((ambientscale + diffusescale) * VectorLength2(lightcolorbase) + specularscale * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
+       if ((ambientscale + diffusescale) * VectorLength2(lightcolor) + specularscale * VectorLength2(lightcolor) < (1.0f / 1048576.0f))
                return;
-       negated = (lightcolorbase[0] + lightcolorbase[1] + lightcolorbase[2] < 0) && vid.support.ext_blend_subtract;
+       negated = (lightcolor[0] + lightcolor[1] + lightcolor[2] < 0) && vid.support.ext_blend_subtract;
        if(negated)
        {
-               VectorNegate(lightcolorbase, lightcolorbase);
+               VectorNegate(lightcolor, lightcolor);
                qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
        }
        RSurf_SetupDepthAndCulling();
-       nmap = rsurface.texture->currentskinframe->nmap;
-       if (gl_lightmaps.integer)
-               nmap = r_texture_blanknormalmap;
-       if (rsurface.texture->colormapping && !gl_lightmaps.integer)
-       {
-               qboolean dopants = rsurface.texture->currentskinframe->pants != NULL && VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f);
-               qboolean doshirt = rsurface.texture->currentskinframe->shirt != NULL && VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
-               if (dopants)
-               {
-                       lightcolorpants[0] = lightcolorbase[0] * rsurface.colormap_pantscolor[0];
-                       lightcolorpants[1] = lightcolorbase[1] * rsurface.colormap_pantscolor[1];
-                       lightcolorpants[2] = lightcolorbase[2] * rsurface.colormap_pantscolor[2];
-               }
-               else
-                       VectorClear(lightcolorpants);
-               if (doshirt)
-               {
-                       lightcolorshirt[0] = lightcolorbase[0] * rsurface.colormap_shirtcolor[0];
-                       lightcolorshirt[1] = lightcolorbase[1] * rsurface.colormap_shirtcolor[1];
-                       lightcolorshirt[2] = lightcolorbase[2] * rsurface.colormap_shirtcolor[2];
-               }
-               else
-                       VectorClear(lightcolorshirt);
-               switch (r_shadow_rendermode)
-               {
-               case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
-                       GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) && !r_showdisabledepthtest.integer);
-                       R_Shadow_RenderLighting_VisibleLighting(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject, lightcolorbase, lightcolorpants, lightcolorshirt, rsurface.texture->basetexture, rsurface.texture->currentskinframe->pants, rsurface.texture->currentskinframe->shirt, nmap, rsurface.texture->glosstexture, ambientscale, diffusescale, specularscale, dopants, doshirt);
-                       break;
-               case R_SHADOW_RENDERMODE_LIGHT_GLSL:
-                       R_Shadow_RenderLighting_Light_GLSL(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject, lightcolorbase, lightcolorpants, lightcolorshirt, rsurface.texture->basetexture, rsurface.texture->currentskinframe->pants, rsurface.texture->currentskinframe->shirt, nmap, rsurface.texture->glosstexture, ambientscale, diffusescale, specularscale, dopants, doshirt);
-                       break;
-               case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
-               case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
-               case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
-               case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
-                       R_Shadow_RenderLighting_Light_Vertex(firstvertex, numvertices, numtriangles, element3i + firsttriangle * 3, lightcolorbase, lightcolorpants, lightcolorshirt, rsurface.texture->basetexture, rsurface.texture->currentskinframe->pants, rsurface.texture->currentskinframe->shirt, nmap, rsurface.texture->glosstexture, ambientscale, diffusescale, specularscale, dopants, doshirt);
-                       break;
-               default:
-                       Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
-                       break;
-               }
-       }
-       else
+       switch (r_shadow_rendermode)
        {
-               switch (r_shadow_rendermode)
-               {
-               case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
-                       GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) && !r_showdisabledepthtest.integer);
-                       R_Shadow_RenderLighting_VisibleLighting(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject, lightcolorbase, vec3_origin, vec3_origin, rsurface.texture->basetexture, r_texture_black, r_texture_black, nmap, rsurface.texture->glosstexture, ambientscale, diffusescale, specularscale, false, false);
-                       break;
-               case R_SHADOW_RENDERMODE_LIGHT_GLSL:
-                       R_Shadow_RenderLighting_Light_GLSL(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject, lightcolorbase, vec3_origin, vec3_origin, rsurface.texture->basetexture, r_texture_black, r_texture_black, nmap, rsurface.texture->glosstexture, ambientscale, diffusescale, specularscale, false, false);
-                       break;
-               case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
-               case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
-               case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
-               case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
-                       R_Shadow_RenderLighting_Light_Vertex(firstvertex, numvertices, numtriangles, element3i + firsttriangle * 3, lightcolorbase, vec3_origin, vec3_origin, rsurface.texture->basetexture, r_texture_black, r_texture_black, nmap, rsurface.texture->glosstexture, ambientscale, diffusescale, specularscale, false, false);
-                       break;
-               default:
-                       Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
-                       break;
-               }
+       case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
+               GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) && !r_showdisabledepthtest.integer);
+               R_Shadow_RenderLighting_VisibleLighting(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject);
+               break;
+       case R_SHADOW_RENDERMODE_LIGHT_GLSL:
+               R_Shadow_RenderLighting_Light_GLSL(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject, lightcolor, ambientscale, diffusescale, specularscale);
+               break;
+       case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
+       case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
+       case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
+       case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
+               R_Shadow_RenderLighting_Light_Vertex(firstvertex, numvertices, numtriangles, element3i + firsttriangle * 3, lightcolor, ambientscale, diffusescale);
+               break;
+       default:
+               Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
+               break;
        }
        if(negated)
                qglBlendEquationEXT(GL_FUNC_ADD_EXT);
@@ -3064,8 +3090,8 @@ void R_RTLight_Compile(rtlight_t *rtlight)
                        if (CHECKPVSBIT(rtlight->static_shadowtrispvs, i))
                                shadowtris++;
 
-       if (developer.integer >= 10)
-               Con_Printf("static light built: %f %f %f : %f %f %f box, %i light triangles, %i shadow triangles, %i zpass/%i zfail compiled shadow volume triangles\n", rtlight->cullmins[0], rtlight->cullmins[1], rtlight->cullmins[2], rtlight->cullmaxs[0], rtlight->cullmaxs[1], rtlight->cullmaxs[2], lighttris, shadowtris, shadowzpasstris, shadowzfailtris);
+       if (developer_extra.integer)
+               Con_DPrintf("static light built: %f %f %f : %f %f %f box, %i light triangles, %i shadow triangles, %i zpass/%i zfail compiled shadow volume triangles\n", rtlight->cullmins[0], rtlight->cullmins[1], rtlight->cullmins[2], rtlight->cullmaxs[0], rtlight->cullmaxs[1], rtlight->cullmaxs[2], lighttris, shadowtris, shadowzpasstris, shadowzfailtris);
 }
 
 void R_RTLight_Uncompile(rtlight_t *rtlight)
@@ -3328,7 +3354,6 @@ void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, co
                {
                        r_refdef.stats.lights_shadowtriangles += mesh->numtriangles;
                        R_Mesh_VertexPointer(mesh->vertex3f, mesh->vbo, mesh->vbooffset_vertex3f);
-                       GL_LockArrays(0, mesh->numverts);
                        if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
                        {
                                // increment stencil if frontface is infront of depthbuffer
@@ -3350,12 +3375,12 @@ void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, co
                                qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
                        }
                        R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s);
-                       GL_LockArrays(0, 0);
                }
                CHECKGLERROR
        }
-       else if (numsurfaces && r_refdef.scene.worldmodel->brush.shadowmesh && r_shadow_culltriangles.integer)
+       else if (numsurfaces && r_refdef.scene.worldmodel->brush.shadowmesh)
        {
+               // use the shadow trispvs calculated earlier by GetLightInfo to cull world triangles on this dynamic light
                R_Shadow_PrepareShadowMark(r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles);
                for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
                {
@@ -3376,8 +3401,9 @@ void R_Shadow_DrawEntityShadow(entity_render_t *ent)
 {
        vec3_t relativeshadoworigin, relativeshadowmins, relativeshadowmaxs;
        vec_t relativeshadowradius;
-       RSurf_ActiveModelEntity(ent, false, false);
+       RSurf_ActiveModelEntity(ent, false, false, false);
        Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, relativeshadoworigin);
+       // we need to re-init the shader for each entity because the matrix changed
        relativeshadowradius = rsurface.rtlight->radius / ent->scale;
        relativeshadowmins[0] = relativeshadoworigin[0] - relativeshadowradius;
        relativeshadowmins[1] = relativeshadoworigin[1] - relativeshadowradius;
@@ -3385,35 +3411,32 @@ void R_Shadow_DrawEntityShadow(entity_render_t *ent)
        relativeshadowmaxs[0] = relativeshadoworigin[0] + relativeshadowradius;
        relativeshadowmaxs[1] = relativeshadoworigin[1] + relativeshadowradius;
        relativeshadowmaxs[2] = relativeshadoworigin[2] + relativeshadowradius;
-       if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE || r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE || r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D)
+       switch (r_shadow_rendermode)
        {
+       case R_SHADOW_RENDERMODE_SHADOWMAP2D:
+       case R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE:
+       case R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE:
                ent->model->DrawShadowMap(r_shadow_shadowmapside, ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
-       }
-       else
+               break;
+       default:
                ent->model->DrawShadowVolume(ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
+               break;
+       }
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
 }
 
 void R_Shadow_SetupEntityLight(const entity_render_t *ent)
 {
        // set up properties for rendering light onto this entity
-       RSurf_ActiveModelEntity(ent, true, true);
+       RSurf_ActiveModelEntity(ent, true, true, false);
        GL_AlphaTest(false);
        Matrix4x4_Concat(&rsurface.entitytolight, &rsurface.rtlight->matrix_worldtolight, &ent->matrix);
        Matrix4x4_Concat(&rsurface.entitytoattenuationxyz, &matrix_attenuationxyz, &rsurface.entitytolight);
        Matrix4x4_Concat(&rsurface.entitytoattenuationz, &matrix_attenuationz, &rsurface.entitytolight);
        Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, rsurface.entitylightorigin);
-       switch(r_shadow_lightingrendermode)
-       {
-       case R_SHADOW_RENDERMODE_LIGHT_GLSL:
-               R_Mesh_TexMatrix(3, &rsurface.entitytolight);
-               break;
-       default:
-               break;
-       }
 }
 
-void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const unsigned char *trispvs)
+void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const unsigned char *lighttrispvs)
 {
        if (!r_refdef.scene.worldmodel->DrawLight)
                return;
@@ -3425,16 +3448,8 @@ void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const unsigned c
        Matrix4x4_Concat(&rsurface.entitytoattenuationxyz, &matrix_attenuationxyz, &rsurface.entitytolight);
        Matrix4x4_Concat(&rsurface.entitytoattenuationz, &matrix_attenuationz, &rsurface.entitytolight);
        VectorCopy(rsurface.rtlight->shadoworigin, rsurface.entitylightorigin);
-       switch(r_shadow_lightingrendermode)
-       {
-       case R_SHADOW_RENDERMODE_LIGHT_GLSL:
-               R_Mesh_TexMatrix(3, &rsurface.entitytolight);
-               break;
-       default:
-               break;
-       }
 
-       r_refdef.scene.worldmodel->DrawLight(r_refdef.scene.worldentity, numsurfaces, surfacelist, trispvs);
+       r_refdef.scene.worldmodel->DrawLight(r_refdef.scene.worldentity, numsurfaces, surfacelist, lighttrispvs);
 
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
 }
@@ -3452,13 +3467,16 @@ void R_Shadow_DrawEntityLight(entity_render_t *ent)
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
 }
 
-void R_CacheRTLight(rtlight_t *rtlight)
+void R_Shadow_PrepareLight(rtlight_t *rtlight)
 {
        int i;
        float f;
        int numleafs, numsurfaces;
        int *leaflist, *surfacelist;
-       unsigned char *leafpvs, *shadowtrispvs, *lighttrispvs, *surfacesides;
+       unsigned char *leafpvs;
+       unsigned char *shadowtrispvs;
+       unsigned char *lighttrispvs;
+       //unsigned char *surfacesides;
        int numlightentities;
        int numlightentities_noselfshadow;
        int numshadowentities;
@@ -3487,7 +3505,7 @@ void R_CacheRTLight(rtlight_t *rtlight)
        }
 
        // load cubemap
-       rtlight->currentcubemap = rtlight->cubemapname[0] ? R_Shadow_Cubemap(rtlight->cubemapname) : r_texture_whitecube;
+       rtlight->currentcubemap = rtlight->cubemapname[0] ? R_GetCubemap(rtlight->cubemapname) : r_texture_whitecube;
 
        // look up the light style value at this time
        f = (rtlight->style >= 0 ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
@@ -3522,7 +3540,7 @@ void R_CacheRTLight(rtlight_t *rtlight)
                leafpvs = rtlight->static_leafpvs;
                numsurfaces = rtlight->static_numsurfaces;
                surfacelist = rtlight->static_surfacelist;
-               surfacesides = NULL;
+               //surfacesides = NULL;
                shadowtrispvs = rtlight->static_shadowtrispvs;
                lighttrispvs = rtlight->static_lighttrispvs;
        }
@@ -3535,7 +3553,7 @@ void R_CacheRTLight(rtlight_t *rtlight)
                leaflist = r_shadow_buffer_leaflist;
                leafpvs = r_shadow_buffer_leafpvs;
                surfacelist = r_shadow_buffer_surfacelist;
-               surfacesides = r_shadow_buffer_surfacesides;
+               //surfacesides = r_shadow_buffer_surfacesides;
                shadowtrispvs = r_shadow_buffer_shadowtrispvs;
                lighttrispvs = r_shadow_buffer_lighttrispvs;
                // if the reduced leaf bounds are offscreen, skip it
@@ -3550,7 +3568,7 @@ void R_CacheRTLight(rtlight_t *rtlight)
                leafpvs = NULL;
                numsurfaces = 0;
                surfacelist = NULL;
-               surfacesides = NULL;
+               //surfacesides = NULL;
                shadowtrispvs = NULL;
                lighttrispvs = NULL;
        }
@@ -3571,67 +3589,64 @@ void R_CacheRTLight(rtlight_t *rtlight)
        numshadowentities_noselfshadow = 0;
 
        // add dynamic entities that are lit by the light
-       if (r_drawentities.integer)
+       for (i = 0;i < r_refdef.scene.numentities;i++)
        {
-               for (i = 0;i < r_refdef.scene.numentities;i++)
+               dp_model_t *model;
+               entity_render_t *ent = r_refdef.scene.entities[i];
+               vec3_t org;
+               if (!BoxesOverlap(ent->mins, ent->maxs, rtlight->cached_cullmins, rtlight->cached_cullmaxs))
+                       continue;
+               // skip the object entirely if it is not within the valid
+               // shadow-casting region (which includes the lit region)
+               if (R_CullBoxCustomPlanes(ent->mins, ent->maxs, rtlight->cached_numfrustumplanes, rtlight->cached_frustumplanes))
+                       continue;
+               if (!(model = ent->model))
+                       continue;
+               if (r_refdef.viewcache.entityvisible[i] && model->DrawLight && (ent->flags & RENDER_LIGHT))
                {
-                       dp_model_t *model;
-                       entity_render_t *ent = r_refdef.scene.entities[i];
-                       vec3_t org;
-                       if (!BoxesOverlap(ent->mins, ent->maxs, rtlight->cached_cullmins, rtlight->cached_cullmaxs))
-                               continue;
-                       // skip the object entirely if it is not within the valid
-                       // shadow-casting region (which includes the lit region)
-                       if (R_CullBoxCustomPlanes(ent->mins, ent->maxs, rtlight->cached_numfrustumplanes, rtlight->cached_frustumplanes))
+                       // this entity wants to receive light, is visible, and is
+                       // inside the light box
+                       // TODO: check if the surfaces in the model can receive light
+                       // so now check if it's in a leaf seen by the light
+                       if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingLeafPVS && !r_refdef.scene.worldmodel->brush.BoxTouchingLeafPVS(r_refdef.scene.worldmodel, leafpvs, ent->mins, ent->maxs))
                                continue;
-                       if (!(model = ent->model))
-                               continue;
-                       if (r_refdef.viewcache.entityvisible[i] && model->DrawLight && (ent->flags & RENDER_LIGHT))
+                       if (ent->flags & RENDER_NOSELFSHADOW)
+                               lightentities_noselfshadow[numlightentities_noselfshadow++] = ent;
+                       else
+                               lightentities[numlightentities++] = ent;
+                       // since it is lit, it probably also casts a shadow...
+                       // about the VectorDistance2 - light emitting entities should not cast their own shadow
+                       Matrix4x4_OriginFromMatrix(&ent->matrix, org);
+                       if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
                        {
-                               // this entity wants to receive light, is visible, and is
-                               // inside the light box
-                               // TODO: check if the surfaces in the model can receive light
-                               // so now check if it's in a leaf seen by the light
-                               if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingLeafPVS && !r_refdef.scene.worldmodel->brush.BoxTouchingLeafPVS(r_refdef.scene.worldmodel, leafpvs, ent->mins, ent->maxs))
-                                       continue;
-                               if (ent->flags & RENDER_NOSELFSHADOW)
-                                       lightentities_noselfshadow[numlightentities_noselfshadow++] = ent;
+                               // note: exterior models without the RENDER_NOSELFSHADOW
+                               // flag still create a RENDER_NOSELFSHADOW shadow but
+                               // are lit normally, this means that they are
+                               // self-shadowing but do not shadow other
+                               // RENDER_NOSELFSHADOW entities such as the gun
+                               // (very weird, but keeps the player shadow off the gun)
+                               if (ent->flags & (RENDER_NOSELFSHADOW | RENDER_EXTERIORMODEL))
+                                       shadowentities_noselfshadow[numshadowentities_noselfshadow++] = ent;
                                else
-                                       lightentities[numlightentities++] = ent;
-                               // since it is lit, it probably also casts a shadow...
-                               // about the VectorDistance2 - light emitting entities should not cast their own shadow
-                               Matrix4x4_OriginFromMatrix(&ent->matrix, org);
-                               if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
-                               {
-                                       // note: exterior models without the RENDER_NOSELFSHADOW
-                                       // flag still create a RENDER_NOSELFSHADOW shadow but
-                                       // are lit normally, this means that they are
-                                       // self-shadowing but do not shadow other
-                                       // RENDER_NOSELFSHADOW entities such as the gun
-                                       // (very weird, but keeps the player shadow off the gun)
-                                       if (ent->flags & (RENDER_NOSELFSHADOW | RENDER_EXTERIORMODEL))
-                                               shadowentities_noselfshadow[numshadowentities_noselfshadow++] = ent;
-                                       else
-                                               shadowentities[numshadowentities++] = ent;
-                               }
+                                       shadowentities[numshadowentities++] = ent;
                        }
-                       else if (ent->flags & RENDER_SHADOW)
+               }
+               else if (ent->flags & RENDER_SHADOW)
+               {
+                       // this entity is not receiving light, but may still need to
+                       // cast a shadow...
+                       // TODO: check if the surfaces in the model can cast shadow
+                       // now check if it is in a leaf seen by the light
+                       if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingLeafPVS && !r_refdef.scene.worldmodel->brush.BoxTouchingLeafPVS(r_refdef.scene.worldmodel, leafpvs, ent->mins, ent->maxs))
+                               continue;
+                       // about the VectorDistance2 - light emitting entities should not cast their own shadow
+                       Matrix4x4_OriginFromMatrix(&ent->matrix, org);
+                       if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
                        {
-                               // this entity is not receiving light, but may still need to
-                               // cast a shadow...
-                               // TODO: check if the surfaces in the model can cast shadow
-                               // now check if it is in a leaf seen by the light
-                               if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingLeafPVS && !r_refdef.scene.worldmodel->brush.BoxTouchingLeafPVS(r_refdef.scene.worldmodel, leafpvs, ent->mins, ent->maxs))
-                                       continue;
-                               // about the VectorDistance2 - light emitting entities should not cast their own shadow
-                               Matrix4x4_OriginFromMatrix(&ent->matrix, org);
-                               if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
-                               {
-                                       if (ent->flags & (RENDER_NOSELFSHADOW | RENDER_EXTERIORMODEL))
-                                               shadowentities_noselfshadow[numshadowentities_noselfshadow++] = ent;
-                                       else
-                                               shadowentities[numshadowentities++] = ent;
-                               }
+                               if (ent->flags & (RENDER_NOSELFSHADOW | RENDER_EXTERIORMODEL))
+                                       shadowentities_noselfshadow[numshadowentities_noselfshadow++] = ent;
+                               else
+                                       shadowentities[numshadowentities++] = ent;
                        }
                }
        }
@@ -3667,8 +3682,10 @@ void R_CacheRTLight(rtlight_t *rtlight)
        rtlight->cached_shadowentities_noselfshadow    = (entity_render_t**)R_FrameData_Store(numshadowentities_noselfshadow*sizeof(entity_render_t *), (void*)shadowentities_noselfshadow);
        if (shadowtrispvs == r_shadow_buffer_shadowtrispvs)
        {
-               rtlight->cached_shadowtrispvs                  =   (unsigned char *)R_FrameData_Store(r_refdef.scene.worldmodel->brush.shadowmesh ? r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles : r_refdef.scene.worldmodel->surfmesh.num_triangles, shadowtrispvs);
-               rtlight->cached_lighttrispvs                   =   (unsigned char *)R_FrameData_Store(r_refdef.scene.worldmodel->surfmesh.num_triangles, lighttrispvs);
+               int numshadowtrispvsbytes = (((r_refdef.scene.worldmodel->brush.shadowmesh ? r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles : r_refdef.scene.worldmodel->surfmesh.num_triangles) + 7) >> 3);
+               int numlighttrispvsbytes = ((r_refdef.scene.worldmodel->surfmesh.num_triangles + 7) >> 3);
+               rtlight->cached_shadowtrispvs                  =   (unsigned char *)R_FrameData_Store(numshadowtrispvsbytes, shadowtrispvs);
+               rtlight->cached_lighttrispvs                   =   (unsigned char *)R_FrameData_Store(numlighttrispvsbytes, lighttrispvs);
                rtlight->cached_surfacelist                    =              (int*)R_FrameData_Store(numsurfaces*sizeof(int), (void*)surfacelist);
        }
        else
@@ -3680,7 +3697,7 @@ void R_CacheRTLight(rtlight_t *rtlight)
        }
 }
 
-void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
+void R_Shadow_DrawLight(rtlight_t *rtlight)
 {
        int i;
        int numsurfaces;
@@ -3837,7 +3854,7 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
                // render shadow casters into 6 sided depth texture
                for (side = 0;side < 6;side++) if (receivermask & (1 << side))
                {
-                       R_Shadow_RenderMode_ShadowMap(side, true, size);
+                       R_Shadow_RenderMode_ShadowMap(side, receivermask, size);
                        if (! (castermask & (1 << side))) continue;
                        if (numsurfaces)
                                R_Shadow_DrawWorldShadow_ShadowMap(numsurfaces, surfacelist, shadowtrispvs, surfacesides);
@@ -3855,11 +3872,11 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
                }
 
                // render shadow casters into 6 sided depth texture
-               if (numshadowentities_noselfshadow) 
+               if (numshadowentities_noselfshadow)
                {
                        for (side = 0;side < 6;side++) if ((receivermask & castermask) & (1 << side))
                        {
-                               R_Shadow_RenderMode_ShadowMap(side, false, size);
+                               R_Shadow_RenderMode_ShadowMap(side, 0, size);
                                for (i = 0;i < numshadowentities_noselfshadow;i++) if (entitysides_noselfshadow[i] & (1 << side))
                                        R_Shadow_DrawEntityShadow(shadowentities_noselfshadow[i]);
                        }
@@ -3912,18 +3929,96 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
                for (i = 0;i < numlightentities_noselfshadow;i++)
                        R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
        }
+
+       if (r_shadow_usingdeferredprepass)
+       {
+               // when rendering deferred lighting, we simply rasterize the box
+               if (castshadows && (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE))
+                       R_Shadow_RenderMode_DrawDeferredLight(false, true);
+               else if (castshadows && vid.stencil)
+                       R_Shadow_RenderMode_DrawDeferredLight(true, false);
+               else
+                       R_Shadow_RenderMode_DrawDeferredLight(false, false);
+       }
 }
 
-void R_PrepareRTLights(void)
+static void R_Shadow_FreeDeferred(void)
 {
+       if (r_shadow_prepassgeometryfbo)
+               qglDeleteFramebuffersEXT(1, &r_shadow_prepassgeometryfbo);CHECKGLERROR
+       r_shadow_prepassgeometryfbo = 0;
+
+       if (r_shadow_prepasslightingfbo)
+               qglDeleteFramebuffersEXT(1, &r_shadow_prepasslightingfbo);CHECKGLERROR
+       r_shadow_prepasslightingfbo = 0;
+
+       if (r_shadow_prepassgeometrydepthtexture)
+               R_FreeTexture(r_shadow_prepassgeometrydepthtexture);
+       r_shadow_prepassgeometrydepthtexture = NULL;
+
+       if (r_shadow_prepassgeometrynormalmaptexture)
+               R_FreeTexture(r_shadow_prepassgeometrynormalmaptexture);
+       r_shadow_prepassgeometrynormalmaptexture = NULL;
+
+       if (r_shadow_prepasslightingdiffusetexture)
+               R_FreeTexture(r_shadow_prepasslightingdiffusetexture);
+       r_shadow_prepasslightingdiffusetexture = NULL;
+
+       if (r_shadow_prepasslightingspeculartexture)
+               R_FreeTexture(r_shadow_prepasslightingspeculartexture);
+       r_shadow_prepasslightingspeculartexture = NULL;
+}
+
+void R_Shadow_DrawPrepass(void)
+{
+       int i;
        int flag;
        int lnum;
        size_t lightindex;
        dlight_t *light;
        size_t range;
-       float f;
+       entity_render_t *ent;
 
-       R_Shadow_EnlargeLeafSurfaceTrisBuffer(r_refdef.scene.worldmodel->brush.num_leafs, r_refdef.scene.worldmodel->num_surfaces, r_refdef.scene.worldmodel->brush.shadowmesh ? r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles : r_refdef.scene.worldmodel->surfmesh.num_triangles, r_refdef.scene.worldmodel->surfmesh.num_triangles);
+       GL_AlphaTest(false);
+       R_Mesh_ColorPointer(NULL, 0, 0);
+       R_Mesh_ResetTextureState();
+       GL_DepthMask(true);
+       GL_ColorMask(1,1,1,1);
+       GL_BlendFunc(GL_ONE, GL_ZERO);
+       GL_Color(1,1,1,1);
+       GL_DepthTest(true);
+       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_prepassgeometryfbo);CHECKGLERROR
+       qglClearColor(0.5f,0.5f,0.5f,1.0f);CHECKGLERROR
+       GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);CHECKGLERROR
+
+       if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawPrepass)
+               r_refdef.scene.worldmodel->DrawPrepass(r_refdef.scene.worldentity);
+       if (r_timereport_active)
+               R_TimeReport("prepassworld");
+
+       for (i = 0;i < r_refdef.scene.numentities;i++)
+       {
+               if (!r_refdef.viewcache.entityvisible[i])
+                       continue;
+               ent = r_refdef.scene.entities[i];
+               if (ent->model && ent->model->DrawPrepass != NULL)
+                       ent->model->DrawPrepass(ent);
+       }
+
+       if (r_timereport_active)
+               R_TimeReport("prepassmodels");
+
+       GL_DepthMask(false);
+       GL_ColorMask(1,1,1,1);
+       GL_Color(1,1,1,1);
+       GL_DepthTest(true);
+       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_prepasslightingfbo);CHECKGLERROR
+       qglClearColor(0.0f,0.0f,0.0f,0.0f);CHECKGLERROR
+       GL_Clear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
+       if (r_refdef.fogenabled)
+               qglClearColor(r_refdef.fogcolor[0],r_refdef.fogcolor[1],r_refdef.fogcolor[2],0);CHECKGLERROR
+
+       R_Shadow_RenderMode_Begin();
 
        flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
        if (r_shadow_debuglight.integer >= 0)
@@ -3931,7 +4026,7 @@ void R_PrepareRTLights(void)
                lightindex = r_shadow_debuglight.integer;
                light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
                if (light && (light->flags & flag))
-                       R_CacheRTLight(&light->rtlight);
+                       R_Shadow_DrawLight(&light->rtlight);
        }
        else
        {
@@ -3940,27 +4035,25 @@ void R_PrepareRTLights(void)
                {
                        light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
                        if (light && (light->flags & flag))
-                               R_CacheRTLight(&light->rtlight);
+                               R_Shadow_DrawLight(&light->rtlight);
                }
        }
        if (r_refdef.scene.rtdlight)
-       {
-               for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
-                       R_CacheRTLight(r_refdef.scene.lights[lnum]);
-       }
-       else if(gl_flashblend.integer)
-       {
                for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
-               {
-                       rtlight_t *rtlight = r_refdef.scene.lights[lnum];
-                       f = (rtlight->style >= 0 ? r_refdef.scene.lightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
-                       VectorScale(rtlight->color, f, rtlight->currentcolor);
-               }
-       }
+                       R_Shadow_DrawLight(r_refdef.scene.lights[lnum]);
+
+       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);CHECKGLERROR
+       if (r_refdef.fogenabled)
+               qglClearColor(r_refdef.fogcolor[0],r_refdef.fogcolor[1],r_refdef.fogcolor[2],0);CHECKGLERROR
+
+       R_Shadow_RenderMode_End();
+
+       if (r_timereport_active)
+               R_TimeReport("prepasslights");
 }
 
 void R_Shadow_DrawLightSprites(void);
-void R_ShadowVolumeLighting(qboolean visible)
+void R_Shadow_PrepareLights(void)
 {
        int flag;
        int lnum;
@@ -3968,9 +4061,10 @@ void R_ShadowVolumeLighting(qboolean visible)
        dlight_t *light;
        size_t range;
        float f;
+       GLenum status;
 
        if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, (int)vid.maxtexturesize_2d / 4) ||
-               (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL) != r_shadow_shadowmapping.integer ||
+               (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL) != (r_shadow_shadowmapping.integer || r_shadow_deferred.integer) ||
                r_shadow_shadowmapvsdct != (r_shadow_shadowmapping_vsdct.integer != 0) || 
                r_shadow_shadowmaptexturetype != r_shadow_shadowmapping_texturetype.integer ||
                r_shadow_shadowmapfilterquality != r_shadow_shadowmapping_filterquality.integer || 
@@ -3978,10 +4072,82 @@ void R_ShadowVolumeLighting(qboolean visible)
                r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16))
                R_Shadow_FreeShadowMaps();
 
-       if (r_editlights.integer)
-               R_Shadow_DrawLightSprites();
+       r_shadow_usingshadowmaportho = false;
 
-       R_Shadow_RenderMode_Begin();
+       switch (vid.renderpath)
+       {
+       case RENDERPATH_GL20:
+       case RENDERPATH_CGGL:
+               if (!r_shadow_deferred.integer || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_STENCIL || !vid.support.ext_framebuffer_object || vid.maxdrawbuffers < 2)
+               {
+                       r_shadow_usingdeferredprepass = false;
+                       if (r_shadow_prepass_width)
+                               R_Shadow_FreeDeferred();
+                       r_shadow_prepass_width = r_shadow_prepass_height = 0;
+                       break;
+               }
+
+               if (r_shadow_prepass_width != vid.width || r_shadow_prepass_height != vid.height)
+               {
+                       R_Shadow_FreeDeferred();
+
+                       r_shadow_usingdeferredprepass = true;
+                       r_shadow_prepass_width = vid.width;
+                       r_shadow_prepass_height = vid.height;
+                       r_shadow_prepassgeometrydepthtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "prepassgeometrydepthmap", vid.width, vid.height, 24, false);
+                       r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, NULL);
+                       r_shadow_prepasslightingdiffusetexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingdiffuse", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, NULL);
+                       r_shadow_prepasslightingspeculartexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingspecular", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, NULL);
+
+                       // set up the geometry pass fbo (depth + normalmap)
+                       qglGenFramebuffersEXT(1, &r_shadow_prepassgeometryfbo);CHECKGLERROR
+                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_prepassgeometryfbo);CHECKGLERROR
+                       qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_prepassgeometrydepthtexture), 0);CHECKGLERROR
+                       qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture), 0);CHECKGLERROR
+                       // render depth into one texture and normalmap into the other
+                       if (qglDrawBuffersARB)
+                       {
+                               qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
+                               qglReadBuffer(GL_NONE);CHECKGLERROR
+                       }
+                       status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
+                       if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+                       {
+                               Con_Printf("R_PrepareRTLights: glCheckFramebufferStatusEXT returned %i\n", status);
+                               Cvar_SetValueQuick(&r_shadow_deferred, 0);
+                               r_shadow_usingdeferredprepass = false;
+                       }
+
+                       // set up the lighting pass fbo (diffuse + specular)
+                       qglGenFramebuffersEXT(1, &r_shadow_prepasslightingfbo);CHECKGLERROR
+                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_prepasslightingfbo);CHECKGLERROR
+                       qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_prepassgeometrydepthtexture), 0);CHECKGLERROR
+                       qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_prepasslightingdiffusetexture), 0);CHECKGLERROR
+                       qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_prepasslightingspeculartexture), 0);CHECKGLERROR
+                       // render diffuse into one texture and specular into another,
+                       // with depth and normalmap bound as textures,
+                       // with depth bound as attachment as well
+                       if (qglDrawBuffersARB)
+                       {
+                               qglDrawBuffersARB(2, r_shadow_prepasslightingdrawbuffers);CHECKGLERROR
+                               qglReadBuffer(GL_NONE);CHECKGLERROR
+                       }
+                       status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
+                       if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+                       {
+                               Con_Printf("R_PrepareRTLights: glCheckFramebufferStatusEXT returned %i\n", status);
+                               Cvar_SetValueQuick(&r_shadow_deferred, 0);
+                               r_shadow_usingdeferredprepass = false;
+                       }
+               }
+               break;
+       case RENDERPATH_GL13:
+       case RENDERPATH_GL11:
+               r_shadow_usingdeferredprepass = false;
+               break;
+       }
+
+       R_Shadow_EnlargeLeafSurfaceTrisBuffer(r_refdef.scene.worldmodel->brush.num_leafs, r_refdef.scene.worldmodel->num_surfaces, r_refdef.scene.worldmodel->brush.shadowmesh ? r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles : r_refdef.scene.worldmodel->surfmesh.num_triangles, r_refdef.scene.worldmodel->surfmesh.num_triangles);
 
        flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
        if (r_shadow_debuglight.integer >= 0)
@@ -3989,7 +4155,7 @@ void R_ShadowVolumeLighting(qboolean visible)
                lightindex = r_shadow_debuglight.integer;
                light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
                if (light && (light->flags & flag))
-                       R_DrawRTLight(&light->rtlight, visible);
+                       R_Shadow_PrepareLight(&light->rtlight);
        }
        else
        {
@@ -3998,13 +4164,13 @@ void R_ShadowVolumeLighting(qboolean visible)
                {
                        light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
                        if (light && (light->flags & flag))
-                               R_DrawRTLight(&light->rtlight, visible);
+                               R_Shadow_PrepareLight(&light->rtlight);
                }
        }
        if (r_refdef.scene.rtdlight)
        {
                for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
-                       R_DrawRTLight(r_refdef.scene.lights[lnum], visible);
+                       R_Shadow_PrepareLight(r_refdef.scene.lights[lnum]);
        }
        else if(gl_flashblend.integer)
        {
@@ -4016,6 +4182,42 @@ void R_ShadowVolumeLighting(qboolean visible)
                }
        }
 
+       if (r_editlights.integer)
+               R_Shadow_DrawLightSprites();
+}
+
+void R_Shadow_DrawLights(void)
+{
+       int flag;
+       int lnum;
+       size_t lightindex;
+       dlight_t *light;
+       size_t range;
+
+       R_Shadow_RenderMode_Begin();
+
+       flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
+       if (r_shadow_debuglight.integer >= 0)
+       {
+               lightindex = r_shadow_debuglight.integer;
+               light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
+               if (light && (light->flags & flag))
+                       R_Shadow_DrawLight(&light->rtlight);
+       }
+       else
+       {
+               range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
+               for (lightindex = 0;lightindex < range;lightindex++)
+               {
+                       light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
+                       if (light && (light->flags & flag))
+                               R_Shadow_DrawLight(&light->rtlight);
+               }
+       }
+       if (r_refdef.scene.rtdlight)
+               for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
+                       R_Shadow_DrawLight(r_refdef.scene.lights[lnum]);
+
        R_Shadow_RenderMode_End();
 }
 
@@ -4029,6 +4231,241 @@ extern cvar_t r_shadows_drawafterrtlighting;
 extern cvar_t r_shadows_castfrombmodels;
 extern cvar_t r_shadows_throwdistance;
 extern cvar_t r_shadows_throwdirection;
+extern cvar_t r_shadows_focus;
+extern cvar_t r_shadows_shadowmapscale;
+
+void R_Shadow_PrepareModelShadows(void)
+{
+       int i;
+       float scale, size, radius, dot1, dot2;
+       vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus, shadowmins, shadowmaxs;
+       entity_render_t *ent;
+
+       if (!r_refdef.scene.numentities)
+               return;
+
+       switch (r_shadow_shadowmode)
+       {
+       case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
+       case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
+               break;
+       case R_SHADOW_SHADOWMODE_STENCIL:
+               for (i = 0;i < r_refdef.scene.numentities;i++)
+               {
+                       ent = r_refdef.scene.entities[i];
+                       if (!ent->animcache_vertex3f && ent->model && ent->model->DrawShadowVolume != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
+                               R_AnimCache_GetEntity(ent, false, false);
+               }
+               return;
+       default:
+               return;
+       }
+
+       size = 2*r_shadow_shadowmapmaxsize;
+       scale = r_shadow_shadowmapping_precision.value * r_shadows_shadowmapscale.value;
+       radius = 0.5f * size / scale;
+
+       Math_atov(r_shadows_throwdirection.string, shadowdir);
+       VectorNormalize(shadowdir);
+       dot1 = DotProduct(r_refdef.view.forward, shadowdir);
+       dot2 = DotProduct(r_refdef.view.up, shadowdir);
+       if (fabs(dot1) <= fabs(dot2))
+               VectorMA(r_refdef.view.forward, -dot1, shadowdir, shadowforward);
+       else
+               VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
+       VectorNormalize(shadowforward);
+       CrossProduct(shadowdir, shadowforward, shadowright);
+       Math_atov(r_shadows_focus.string, shadowfocus);
+       VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
+       VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
+       VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
+       VectorAdd(shadoworigin, r_refdef.view.origin, shadoworigin);
+       if (shadowfocus[0] || shadowfocus[1] || shadowfocus[2])
+               dot1 = 1;
+       VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
+
+       shadowmins[0] = shadoworigin[0] - r_shadows_throwdistance.value * fabs(shadowdir[0]) - radius * (fabs(shadowforward[0]) + fabs(shadowright[0]));
+       shadowmins[1] = shadoworigin[1] - r_shadows_throwdistance.value * fabs(shadowdir[1]) - radius * (fabs(shadowforward[1]) + fabs(shadowright[1]));
+       shadowmins[2] = shadoworigin[2] - r_shadows_throwdistance.value * fabs(shadowdir[2]) - radius * (fabs(shadowforward[2]) + fabs(shadowright[2]));
+       shadowmaxs[0] = shadoworigin[0] + r_shadows_throwdistance.value * fabs(shadowdir[0]) + radius * (fabs(shadowforward[0]) + fabs(shadowright[0]));
+       shadowmaxs[1] = shadoworigin[1] + r_shadows_throwdistance.value * fabs(shadowdir[1]) + radius * (fabs(shadowforward[1]) + fabs(shadowright[1]));
+       shadowmaxs[2] = shadoworigin[2] + r_shadows_throwdistance.value * fabs(shadowdir[2]) + radius * (fabs(shadowforward[2]) + fabs(shadowright[2]));
+
+       for (i = 0;i < r_refdef.scene.numentities;i++)
+       {
+               ent = r_refdef.scene.entities[i];
+               if (!BoxesOverlap(ent->mins, ent->maxs, shadowmins, shadowmaxs))
+                       continue;
+               // cast shadows from anything of the map (submodels are optional)
+               if (!ent->animcache_vertex3f && ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
+                       R_AnimCache_GetEntity(ent, false, false);
+       }
+}
+
+void R_DrawModelShadowMaps(void)
+{
+       int i;
+       float relativethrowdistance, scale, size, radius, nearclip, farclip, bias, dot1, dot2;
+       entity_render_t *ent;
+       vec3_t relativelightorigin;
+       vec3_t relativelightdirection, relativeforward, relativeright;
+       vec3_t relativeshadowmins, relativeshadowmaxs;
+       vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus;
+       float m[12];
+       matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix, scalematrix, texmatrix;
+       r_viewport_t viewport;
+       GLuint fbo = 0;
+
+       if (!r_refdef.scene.numentities)
+               return;
+
+       switch (r_shadow_shadowmode)
+       {
+       case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
+       case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
+               break;
+       default:
+               return;
+       }
+
+       CHECKGLERROR
+       R_ResetViewRendering3D();
+       R_Shadow_RenderMode_Begin();
+       R_Shadow_RenderMode_ActiveLight(NULL);
+
+       switch (r_shadow_shadowmode)
+       {
+       case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
+               if (!r_shadow_shadowmap2dtexture)
+                       R_Shadow_MakeShadowMap(0, r_shadow_shadowmapmaxsize);
+               fbo = r_shadow_fbo2d;
+               r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture);
+               r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture);
+               r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
+               break;
+       case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
+               if (!r_shadow_shadowmaprectangletexture)
+                       R_Shadow_MakeShadowMap(0, r_shadow_shadowmapmaxsize);
+               fbo = r_shadow_fborectangle;
+               r_shadow_shadowmap_texturescale[0] = 1.0f;
+               r_shadow_shadowmap_texturescale[1] = 1.0f;
+               r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE;
+               break;
+       default:
+               break;
+       }
+
+       size = 2*r_shadow_shadowmapmaxsize;
+       scale = (r_shadow_shadowmapping_precision.value * r_shadows_shadowmapscale.value) / size;
+       radius = 0.5f / scale;
+       nearclip = -r_shadows_throwdistance.value;
+       farclip = r_shadows_throwdistance.value;
+       bias = r_shadow_shadowmapping_bias.value * r_shadow_shadowmapping_nearclip.value / (2 * r_shadows_throwdistance.value) * (1024.0f / size);
+
+       r_shadow_shadowmap_parameters[0] = size;
+       r_shadow_shadowmap_parameters[1] = size;
+       r_shadow_shadowmap_parameters[2] = 1.0;
+       r_shadow_shadowmap_parameters[3] = bound(0.0f, 1.0f - r_shadows_darken.value, 1.0f);
+
+       Math_atov(r_shadows_throwdirection.string, shadowdir);
+       VectorNormalize(shadowdir);
+       Math_atov(r_shadows_focus.string, shadowfocus);
+       VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
+       VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
+       VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
+       VectorAdd(shadoworigin, r_refdef.view.origin, shadoworigin);
+       dot1 = DotProduct(r_refdef.view.forward, shadowdir);
+       dot2 = DotProduct(r_refdef.view.up, shadowdir);
+       if (fabs(dot1) <= fabs(dot2)) 
+               VectorMA(r_refdef.view.forward, -dot1, shadowdir, shadowforward);
+       else
+               VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
+       VectorNormalize(shadowforward);
+       VectorM(scale, shadowforward, &m[0]);
+       if (shadowfocus[0] || shadowfocus[1] || shadowfocus[2])
+               dot1 = 1;
+       m[3] = fabs(dot1) * 0.5f - DotProduct(shadoworigin, &m[0]);
+       CrossProduct(shadowdir, shadowforward, shadowright);
+       VectorM(scale, shadowright, &m[4]);
+       m[7] = 0.5f - DotProduct(shadoworigin, &m[4]);
+       VectorM(1.0f / (farclip - nearclip), shadowdir, &m[8]);
+       m[11] = 0.5f - DotProduct(shadoworigin, &m[8]);
+       Matrix4x4_FromArray12FloatD3D(&shadowmatrix, m);
+       Matrix4x4_Invert_Full(&cameramatrix, &shadowmatrix);
+       R_Viewport_InitOrtho(&viewport, &cameramatrix, 0, 0, size, size, 0, 0, 1, 1, 0, -1, NULL); 
+
+       VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
+#if 0
+       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);CHECKGLERROR
+       R_SetupShader_ShowDepth();
+#else
+       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);CHECKGLERROR
+       R_SetupShader_DepthOrShadow();
+#endif
+       CHECKGLERROR
+       GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
+       GL_DepthMask(true);
+       GL_DepthTest(true);
+       R_SetViewport(&viewport);
+       GL_Scissor(viewport.x, viewport.y, min(viewport.width + r_shadow_shadowmapborder, 2*r_shadow_shadowmapmaxsize), viewport.height + r_shadow_shadowmapborder);
+       qglClearDepth(1);
+#if 0
+       qglClearColor(1,1,1,1);
+       GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+#else
+       GL_Clear(GL_DEPTH_BUFFER_BIT);
+#endif
+       GL_Scissor(viewport.x + r_shadow_shadowmapborder, viewport.y + r_shadow_shadowmapborder, viewport.width - 2*r_shadow_shadowmapborder, viewport.height - 2*r_shadow_shadowmapborder);
+       CHECKGLERROR
+
+       for (i = 0;i < r_refdef.scene.numentities;i++)
+       {
+               ent = r_refdef.scene.entities[i];
+
+               // cast shadows from anything of the map (submodels are optional)
+               if (ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
+               {
+                       relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
+                       Matrix4x4_Transform(&ent->inversematrix, shadoworigin, relativelightorigin);
+                       Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
+                       Matrix4x4_Transform3x3(&ent->inversematrix, shadowforward, relativeforward);
+                       Matrix4x4_Transform3x3(&ent->inversematrix, shadowright, relativeright);
+                       relativeshadowmins[0] = relativelightorigin[0] - r_shadows_throwdistance.value * fabs(relativelightdirection[0]) - radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
+                       relativeshadowmins[1] = relativelightorigin[1] - r_shadows_throwdistance.value * fabs(relativelightdirection[1]) - radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
+                       relativeshadowmins[2] = relativelightorigin[2] - r_shadows_throwdistance.value * fabs(relativelightdirection[2]) - radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
+                       relativeshadowmaxs[0] = relativelightorigin[0] + r_shadows_throwdistance.value * fabs(relativelightdirection[0]) + radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
+                       relativeshadowmaxs[1] = relativelightorigin[1] + r_shadows_throwdistance.value * fabs(relativelightdirection[1]) + radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
+                       relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
+                       RSurf_ActiveModelEntity(ent, false, false, false);
+                       ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
+                       rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
+               }
+       }
+
+       R_Shadow_RenderMode_End();
+
+       Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
+       Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
+       Matrix4x4_CreateScale3(&scalematrix, size, -size, 1); 
+       Matrix4x4_AdjustOrigin(&scalematrix, 0, size, -0.5f * bias);
+       Matrix4x4_Concat(&texmatrix, &scalematrix, &shadowmatrix);
+       Matrix4x4_Concat(&r_shadow_shadowmapmatrix, &texmatrix, &invmvpmatrix);
+
+       r_shadow_usingshadowmaportho = true;
+       switch (r_shadow_shadowmode)
+       {
+       case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
+               r_shadow_usingshadowmap2d = true;
+               break;
+       case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
+               r_shadow_usingshadowmaprect = true;
+               break;
+       default:
+               break;
+       }
+}
+
 void R_DrawModelShadows(void)
 {
        int i;
@@ -4039,7 +4476,7 @@ void R_DrawModelShadows(void)
        vec3_t relativeshadowmins, relativeshadowmaxs;
        vec3_t tmp, shadowdir;
 
-       if (!r_drawentities.integer || !vid.stencil)
+       if (!r_refdef.scene.numentities || !vid.stencil || r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL)
                return;
 
        CHECKGLERROR
@@ -4105,7 +4542,7 @@ void R_DrawModelShadows(void)
                        }
 
                        VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin);
-                       RSurf_ActiveModelEntity(ent, false, false);
+                       RSurf_ActiveModelEntity(ent, false, false, false);
                        ent->model->DrawShadowVolume(ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
                        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
                }
@@ -4118,12 +4555,12 @@ void R_DrawModelShadows(void)
        //GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
        //GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
        //GL_ScissorTest(true);
-       //R_Mesh_Matrix(&identitymatrix);
+       //R_EntityMatrix(&identitymatrix);
        //R_Mesh_ResetTextureState();
        R_ResetViewRendering2D();
        R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
        R_Mesh_ColorPointer(NULL, 0, 0);
-       R_SetupGenericShader(false);
+       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
 
        // set up a darkening blend on shadowed areas
        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -4135,9 +4572,9 @@ void R_DrawModelShadows(void)
        //GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
        //qglDepthFunc(GL_ALWAYS);CHECKGLERROR
        qglEnable(GL_STENCIL_TEST);CHECKGLERROR
-       qglStencilMask(~0);CHECKGLERROR
+       qglStencilMask(255);CHECKGLERROR
        qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
-       qglStencilFunc(GL_NOTEQUAL, 128, ~0);CHECKGLERROR
+       qglStencilFunc(GL_NOTEQUAL, 128, 255);CHECKGLERROR
 
        // apply the blend to the shadowed areas
        R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
@@ -4223,13 +4660,13 @@ void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
                }
                R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
                RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, RENDER_NODEPTHTEST, 0, color[0], color[1], color[2], 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
-               R_DrawCustomSurface(r_shadow_lightcorona, &identitymatrix, MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false);
+               R_DrawCustomSurface(r_shadow_lightcorona, &identitymatrix, MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
                if(negated)
                        qglBlendEquationEXT(GL_FUNC_ADD_EXT);
        }
 }
 
-void R_DrawCoronas(void)
+void R_Shadow_DrawCoronas(void)
 {
        int i, flag;
        qboolean usequery;
@@ -4242,7 +4679,7 @@ void R_DrawCoronas(void)
        if (r_waterstate.renderingscene)
                return;
        flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
-       R_Mesh_Matrix(&identitymatrix);
+       R_EntityMatrix(&identitymatrix);
 
        range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
 
@@ -4273,7 +4710,7 @@ void R_DrawCoronas(void)
                GL_DepthTest(true);
                R_Mesh_ColorPointer(NULL, 0, 0);
                R_Mesh_ResetTextureState();
-               R_SetupGenericShader(false);
+               R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
        }
        for (lightindex = 0;lightindex < range;lightindex++)
        {
@@ -4332,140 +4769,6 @@ void R_DrawCoronas(void)
 
 
 
-//static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
-typedef struct suffixinfo_s
-{
-       char *suffix;
-       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},
-               {"posy", false, false, false},
-               {"negy", false, false, false},
-               {"posz", false, false, false},
-               {"negz", 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}
-       }
-};
-
-static int componentorder[4] = {0, 1, 2, 3};
-
-rtexture_t *R_Shadow_LoadCubemap(const char *basename)
-{
-       int i, j, cubemapsize;
-       unsigned char *cubemappixels, *image_buffer;
-       rtexture_t *cubemaptexture;
-       char name[256];
-       // must start 0 so the first loadimagepixels has no requested width/height
-       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
-                       dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
-                       // load it
-                       if ((image_buffer = loadimagepixelsbgra(name, false, false)))
-                       {
-                               // an image loaded, make sure width and height are equal
-                               if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
-                               {
-                                       // 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 sides are black
-                                               cubemappixels = (unsigned char *)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_buffer, 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_buffer);
-                       }
-               }
-       }
-       // if a cubemap loaded, upload it
-       if (cubemappixels)
-       {
-               if (developer_loading.integer)
-                       Con_Printf("loading cubemap \"%s\"\n", basename);
-
-               if (!r_shadow_filters_texturepool)
-                       r_shadow_filters_texturepool = R_AllocTexturePool();
-               cubemaptexture = R_LoadTextureCubeMap(r_shadow_filters_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, TEXF_PRECACHE | (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
-               Mem_Free(cubemappixels);
-       }
-       else
-       {
-               Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
-               if (developer_loading.integer)
-               {
-                       Con_Printf("(tried tried images ");
-                       for (j = 0;j < 3;j++)
-                               for (i = 0;i < 6;i++)
-                                       Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
-                       Con_Print(" and was unable to find any of them).\n");
-               }
-       }
-       return cubemaptexture;
-}
-
-rtexture_t *R_Shadow_Cubemap(const char *basename)
-{
-       int i;
-       for (i = 0;i < numcubemaps;i++)
-               if (!strcasecmp(cubemaps[i].basename, basename))
-                       return cubemaps[i].texture ? cubemaps[i].texture : r_texture_whitecube;
-       if (i >= MAX_CUBEMAPS)
-               return r_texture_whitecube;
-       numcubemaps++;
-       strlcpy(cubemaps[i].basename, basename, sizeof(cubemaps[i].basename));
-       cubemaps[i].texture = R_Shadow_LoadCubemap(cubemaps[i].basename);
-       return cubemaps[i].texture;
-}
-
-void R_Shadow_FreeCubemaps(void)
-{
-       int i;
-       for (i = 0;i < numcubemaps;i++)
-       {
-               if (developer_loading.integer)
-                       Con_Printf("unloading cubemap \"%s\"\n", cubemaps[i].basename);
-               if (cubemaps[i].texture)
-                       R_FreeTexture(cubemaps[i].texture);
-       }
-
-       numcubemaps = 0;
-       R_FreeTexturePool(&r_shadow_filters_texturepool);
-}
-
 dlight_t *R_Shadow_NewWorldLight(void)
 {
        return (dlight_t *)Mem_ExpandableArray_AllocRecord(&r_shadow_worldlightsarray);
@@ -4532,7 +4835,6 @@ void R_Shadow_ClearWorldLights(void)
                        R_Shadow_FreeWorldLight(light);
        }
        r_shadow_selectedlight = NULL;
-       R_Shadow_FreeCubemaps();
 }
 
 void R_Shadow_SelectLight(dlight_t *light)
@@ -4550,7 +4852,7 @@ void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const r
        float vertex3f[12];
        R_CalcSprite_Vertex3f(vertex3f, r_editlights_cursorlocation, r_refdef.view.right, r_refdef.view.up, EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, EDLIGHTSPRSIZE);
        RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, 1, 1, 1, 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
-       R_DrawCustomSurface(r_editlights_sprcursor, &identitymatrix, MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false);
+       R_DrawCustomSurface(r_editlights_sprcursor, &identitymatrix, MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
 }
 
 void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
@@ -4586,13 +4888,13 @@ void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, co
                skinframe = r_editlights_sprlight;
 
        RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, spritecolor[0], spritecolor[1], spritecolor[2], 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
-       R_DrawCustomSurface(skinframe, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false);
+       R_DrawCustomSurface(skinframe, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
 
        // draw selection sprite if light is selected
        if (light->selected)
        {
                RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, 1, 1, 1, 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
-               R_DrawCustomSurface(r_editlights_sprselection, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false);
+               R_DrawCustomSurface(r_editlights_sprselection, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
                // VorteX todo: add normalmode/realtime mode light overlay sprites?
        }
 }
@@ -4874,7 +5176,14 @@ typedef enum lighttype_e {LIGHTTYPE_MINUSX, LIGHTTYPE_RECIPX, LIGHTTYPE_RECIPXX,
 
 void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
 {
-       int entnum, style, islight, skin, pflags, effects, type, n;
+       int entnum;
+       int style;
+       int islight;
+       int skin;
+       int pflags;
+       //int effects;
+       int type;
+       int n;
        char *entfiledata;
        const char *data;
        float origin[3], angles[3], radius, color[3], light[4], fadescale, lightscale, originhack[3], overridecolor[3], vec[4];
@@ -4908,7 +5217,7 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
                style = 0;
                skin = 0;
                pflags = 0;
-               effects = 0;
+               //effects = 0;
                islight = false;
                while (1)
                {
@@ -5035,8 +5344,8 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
                                skin = (int)atof(value);
                        else if (!strcmp("pflags", key))
                                pflags = (int)atof(value);
-                       else if (!strcmp("effects", key))
-                               effects = (int)atof(value);
+                       //else if (!strcmp("effects", key))
+                       //      effects = (int)atof(value);
                        else if (cl.worldmodel->type == mod_brushq3)
                        {
                                if (!strcmp("scale", key))
@@ -5546,26 +5855,26 @@ void R_Shadow_EditLights_DrawSelectedLightProperties(void)
                        lightnumber = lightindex;
                lightcount++;
        }
-       dpsnprintf(temp, sizeof(temp), "Cursor origin: %.0f %.0f %.0f", r_editlights_cursorlocation[0], r_editlights_cursorlocation[1], r_editlights_cursorlocation[2]); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, false);y += 8;
-       dpsnprintf(temp, sizeof(temp), "Total lights : %i active (%i total)", lightcount, (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray)); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, false);y += 8;
+       dpsnprintf(temp, sizeof(temp), "Cursor origin: %.0f %.0f %.0f", r_editlights_cursorlocation[0], r_editlights_cursorlocation[1], r_editlights_cursorlocation[2]); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, false, FONT_DEFAULT);y += 8;
+       dpsnprintf(temp, sizeof(temp), "Total lights : %i active (%i total)", lightcount, (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray)); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, false, FONT_DEFAULT);y += 8;
        y += 8;
        if (r_shadow_selectedlight == NULL)
                return;
-       dpsnprintf(temp, sizeof(temp), "Light #%i properties:", lightnumber);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
-       dpsnprintf(temp, sizeof(temp), "Origin       : %.0f %.0f %.0f\n", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
-       dpsnprintf(temp, sizeof(temp), "Angles       : %.0f %.0f %.0f\n", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
-       dpsnprintf(temp, sizeof(temp), "Color        : %.2f %.2f %.2f\n", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
-       dpsnprintf(temp, sizeof(temp), "Radius       : %.0f\n", r_shadow_selectedlight->radius);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
-       dpsnprintf(temp, sizeof(temp), "Corona       : %.0f\n", r_shadow_selectedlight->corona);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
-       dpsnprintf(temp, sizeof(temp), "Style        : %i\n", r_shadow_selectedlight->style);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
-       dpsnprintf(temp, sizeof(temp), "Shadows      : %s\n", r_shadow_selectedlight->shadow ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
-       dpsnprintf(temp, sizeof(temp), "Cubemap      : %s\n", r_shadow_selectedlight->cubemapname);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
-       dpsnprintf(temp, sizeof(temp), "CoronaSize   : %.2f\n", r_shadow_selectedlight->coronasizescale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
-       dpsnprintf(temp, sizeof(temp), "Ambient      : %.2f\n", r_shadow_selectedlight->ambientscale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
-       dpsnprintf(temp, sizeof(temp), "Diffuse      : %.2f\n", r_shadow_selectedlight->diffusescale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
-       dpsnprintf(temp, sizeof(temp), "Specular     : %.2f\n", r_shadow_selectedlight->specularscale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
-       dpsnprintf(temp, sizeof(temp), "NormalMode   : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
-       dpsnprintf(temp, sizeof(temp), "RealTimeMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
+       dpsnprintf(temp, sizeof(temp), "Light #%i properties:", lightnumber);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
+       dpsnprintf(temp, sizeof(temp), "Origin       : %.0f %.0f %.0f\n", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
+       dpsnprintf(temp, sizeof(temp), "Angles       : %.0f %.0f %.0f\n", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
+       dpsnprintf(temp, sizeof(temp), "Color        : %.2f %.2f %.2f\n", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
+       dpsnprintf(temp, sizeof(temp), "Radius       : %.0f\n", r_shadow_selectedlight->radius);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
+       dpsnprintf(temp, sizeof(temp), "Corona       : %.0f\n", r_shadow_selectedlight->corona);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
+       dpsnprintf(temp, sizeof(temp), "Style        : %i\n", r_shadow_selectedlight->style);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
+       dpsnprintf(temp, sizeof(temp), "Shadows      : %s\n", r_shadow_selectedlight->shadow ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
+       dpsnprintf(temp, sizeof(temp), "Cubemap      : %s\n", r_shadow_selectedlight->cubemapname);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
+       dpsnprintf(temp, sizeof(temp), "CoronaSize   : %.2f\n", r_shadow_selectedlight->coronasizescale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
+       dpsnprintf(temp, sizeof(temp), "Ambient      : %.2f\n", r_shadow_selectedlight->ambientscale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
+       dpsnprintf(temp, sizeof(temp), "Diffuse      : %.2f\n", r_shadow_selectedlight->diffusescale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
+       dpsnprintf(temp, sizeof(temp), "Specular     : %.2f\n", r_shadow_selectedlight->specularscale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
+       dpsnprintf(temp, sizeof(temp), "NormalMode   : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
+       dpsnprintf(temp, sizeof(temp), "RealTimeMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
 }
 
 void R_Shadow_EditLights_ToggleShadow_f(void)
@@ -5754,7 +6063,7 @@ void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffu
 
        if (!r_fullbright.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
        {
-               ambientcolor[0] = ambientcolor[1] = ambientcolor[2] = r_refdef.scene.ambient * (2.0f / 128.0f);
+               ambientcolor[0] = ambientcolor[1] = ambientcolor[2] = r_refdef.scene.ambient;
                r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
        }
        else