]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
new r_stereo modes (horiz and vert split)
[xonotic/darkplaces.git] / r_shadow.c
index 4392b2ed94df92d384d1d51fc2e90a7908dc15cc..fa594fdeda3fe6ea44d07d4ec622c88b88778603 100644 (file)
@@ -163,18 +163,14 @@ typedef enum r_shadow_rendermode_e
        R_SHADOW_RENDERMODE_LIGHT_GLSL,
        R_SHADOW_RENDERMODE_VISIBLEVOLUMES,
        R_SHADOW_RENDERMODE_VISIBLELIGHTING,
-       R_SHADOW_RENDERMODE_SHADOWMAP2D,
-       R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE,
-       R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE,
+       R_SHADOW_RENDERMODE_SHADOWMAP2D
 }
 r_shadow_rendermode_t;
 
 typedef enum r_shadow_shadowmode_e
 {
     R_SHADOW_SHADOWMODE_STENCIL,
-    R_SHADOW_SHADOWMODE_SHADOWMAP2D,
-    R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE,
-    R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE
+    R_SHADOW_SHADOWMODE_SHADOWMAP2D
 }
 r_shadow_shadowmode_t;
 
@@ -182,9 +178,7 @@ r_shadow_rendermode_t r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
 r_shadow_rendermode_t r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_NONE;
 r_shadow_rendermode_t r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_NONE;
 r_shadow_rendermode_t r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_NONE;
-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];
@@ -194,12 +188,9 @@ int r_shadow_drawbuffer;
 int r_shadow_readbuffer;
 #endif
 int r_shadow_cullface_front, r_shadow_cullface_back;
-GLuint r_shadow_fborectangle;
-GLuint r_shadow_fbocubeside[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
 GLuint r_shadow_fbo2d;
 r_shadow_shadowmode_t r_shadow_shadowmode;
 int r_shadow_shadowmapfilterquality;
-int r_shadow_shadowmaptexturetype;
 int r_shadow_shadowmapdepthbits;
 int r_shadow_shadowmapmaxsize;
 qboolean r_shadow_shadowmapvsdct;
@@ -252,9 +243,7 @@ rtexture_t *r_shadow_attenuationgradienttexture;
 rtexture_t *r_shadow_attenuation2dtexture;
 rtexture_t *r_shadow_attenuation3dtexture;
 skinframe_t *r_shadow_lightcorona;
-rtexture_t *r_shadow_shadowmaprectangletexture;
 rtexture_t *r_shadow_shadowmap2dtexture;
-rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
 rtexture_t *r_shadow_shadowmap2dcolortexture;
 rtexture_t *r_shadow_shadowmapvsdcttexture;
 int r_shadow_shadowmapsize; // changes for each light based on distance
@@ -265,6 +254,7 @@ GLuint r_shadow_prepasslightingfbo;
 int r_shadow_prepass_width;
 int r_shadow_prepass_height;
 rtexture_t *r_shadow_prepassgeometrydepthtexture;
+rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
 rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
 rtexture_t *r_shadow_prepasslightingdiffusetexture;
 rtexture_t *r_shadow_prepasslightingspeculartexture;
@@ -309,7 +299,6 @@ cvar_t r_shadow_realtime_world_compilesvbsp = {0, "r_shadow_realtime_world_compi
 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"};
 cvar_t r_shadow_shadowmapping_filterquality = {CVAR_SAVE, "r_shadow_shadowmapping_filterquality", "-1", "shadowmap filter modes: -1 = auto-select, 0 = no filtering, 1 = bilinear, 2 = bilinear 2x2 blur (fast), 3 = 3x3 blur (moderate), 4 = 4x4 blur (slow)"};
 cvar_t r_shadow_shadowmapping_depthbits = {CVAR_SAVE, "r_shadow_shadowmapping_depthbits", "24", "requested minimum shadowmap texture depth bits"};
 cvar_t r_shadow_shadowmapping_vsdct = {CVAR_SAVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"};
@@ -380,9 +369,8 @@ skinframe_t *r_editlights_sprselection;
 void R_Shadow_SetShadowMode(void)
 {
        r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, (int)vid.maxtexturesize_2d / 4);
-       r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0;
+       r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0 && vid.renderpath == RENDERPATH_GL20;
        r_shadow_shadowmapfilterquality = r_shadow_shadowmapping_filterquality.integer;
-       r_shadow_shadowmaptexturetype = r_shadow_shadowmapping_texturetype.integer;
        r_shadow_shadowmapdepthbits = r_shadow_shadowmapping_depthbits.integer;
        r_shadow_shadowmapborder = bound(0, r_shadow_shadowmapping_bordersize.integer, 16);
        r_shadow_shadowmaplod = -1;
@@ -428,32 +416,10 @@ void R_Shadow_SetShadowMode(void)
                                        break;
                                }
                        }
-                       switch (r_shadow_shadowmaptexturetype)
-                       {
-                       case 0:
-                               r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
-                               break;
-                       case 1:
-                               r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE;
-                               break;
-                       case 2:
-                               r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE;
-                               break;
-                       default:
-                               if((vid.support.amd_texture_texture4 || vid.support.arb_texture_gather) && r_shadow_shadowmappcf && !r_shadow_shadowmapsampler)
-                                       r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
-                               else if(vid.support.arb_texture_rectangle) 
-                                       r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE;
-                               else
-                                       r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
-                               break;
-                       }
+                       r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
                        // Cg has very little choice in depth texture sampling
                        if (vid.cgcontext)
-                       {
                                r_shadow_shadowmapsampler = false;
-                               r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
-                       }
                        break;
                case RENDERPATH_CGGL:
                case RENDERPATH_D3D9:
@@ -476,8 +442,6 @@ 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;
@@ -486,33 +450,16 @@ qboolean R_Shadow_ShadowMappingEnabled(void)
 
 void R_Shadow_FreeShadowMaps(void)
 {
-       int i;
-
        R_Shadow_SetShadowMode();
 
-       R_Mesh_DestroyFramebufferObject(r_shadow_fborectangle);
-
        R_Mesh_DestroyFramebufferObject(r_shadow_fbo2d);
-       for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
-               R_Mesh_DestroyFramebufferObject(r_shadow_fbocubeside[i]);
 
-       r_shadow_fborectangle = 0;
        r_shadow_fbo2d = 0;
-       memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside));
-
-       if (r_shadow_shadowmaprectangletexture)
-               R_FreeTexture(r_shadow_shadowmaprectangletexture);
-       r_shadow_shadowmaprectangletexture = NULL;
 
        if (r_shadow_shadowmap2dtexture)
                R_FreeTexture(r_shadow_shadowmap2dtexture);
        r_shadow_shadowmap2dtexture = NULL;
 
-       for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
-               if (r_shadow_shadowmapcubetexture[i])
-                       R_FreeTexture(r_shadow_shadowmapcubetexture[i]);
-       memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture));
-
        if (r_shadow_shadowmap2dcolortexture)
                R_FreeTexture(r_shadow_shadowmap2dcolortexture);
        r_shadow_shadowmap2dcolortexture = NULL;
@@ -529,23 +476,18 @@ void r_shadow_start(void)
        r_shadow_attenuation2dtexture = NULL;
        r_shadow_attenuation3dtexture = NULL;
        r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
-       r_shadow_shadowmaprectangletexture = NULL;
        r_shadow_shadowmap2dtexture = NULL;
-       memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture));
        r_shadow_shadowmap2dcolortexture = NULL;
        r_shadow_shadowmapvsdcttexture = NULL;
        r_shadow_shadowmapmaxsize = 0;
        r_shadow_shadowmapsize = 0;
        r_shadow_shadowmaplod = 0;
        r_shadow_shadowmapfilterquality = -1;
-       r_shadow_shadowmaptexturetype = -1;
        r_shadow_shadowmapdepthbits = 0;
        r_shadow_shadowmapvsdct = false;
        r_shadow_shadowmapsampler = false;
        r_shadow_shadowmappcf = 0;
-       r_shadow_fborectangle = 0;
        r_shadow_fbo2d = 0;
-       memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside));
 
        R_Shadow_FreeShadowMaps();
 
@@ -714,7 +656,6 @@ void R_Shadow_Init(void)
        Cvar_RegisterVariable(&r_shadow_scissor);
        Cvar_RegisterVariable(&r_shadow_shadowmapping);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_vsdct);
-       Cvar_RegisterVariable(&r_shadow_shadowmapping_texturetype);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_filterquality);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_depthbits);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_precision);
@@ -2005,8 +1946,6 @@ void R_Shadow_RenderMode_Reset(void)
        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_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
-       r_shadow_usingshadowmaprect = false;
-       r_shadow_usingshadowmapcube = false;
        r_shadow_usingshadowmap2d = false;
        r_shadow_usingshadowmaportho = false;
        R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
@@ -2086,20 +2025,6 @@ static void R_Shadow_MakeShadowMap(int side, int size)
                        break;
                }
                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);
-               r_shadow_fborectangle = R_Mesh_CreateFramebufferObject(r_shadow_shadowmaprectangletexture, NULL, NULL, NULL, NULL);
-               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);
-               // special trick to get an empty fbo we configure ourselves...
-               r_shadow_fbocubeside[r_shadow_shadowmaplod] = R_Mesh_CreateFramebufferObject(NULL, NULL, NULL, NULL, NULL);
-               R_Mesh_SetRenderTargets(r_shadow_fbocubeside[r_shadow_shadowmaplod], NULL, NULL, NULL, NULL, NULL);
-               if (qglFramebufferTexture2DEXT)
-                       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;
        }
@@ -2121,13 +2046,13 @@ static void R_Shadow_MakeShadowMap(int side, int size)
        }
 }
 
-static float testcolor[4] = {0,1,0,1};
 void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size)
 {
        float nearclip, farclip, bias;
        r_viewport_t viewport;
        int flipped;
        GLuint fbo = 0;
+       float clearcolor[4];
        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;
@@ -2135,58 +2060,24 @@ void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size)
        r_shadow_shadowmap_parameters[3] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip);
        r_shadow_shadowmapside = side;
        r_shadow_shadowmapsize = size;
-       switch (r_shadow_shadowmode)
-       {
-       case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
-               r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
-               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;
-
-               // complex unrolled cube approach (more flexible)
-               if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
-                       R_Shadow_MakeVSDCT();
-               if (!r_shadow_shadowmap2dtexture)
-                       R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize);
-               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;
-               break;
-       case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
-               r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
-               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;
-
-               // complex unrolled cube approach (more flexible)
-               if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
-                       R_Shadow_MakeVSDCT();
-               if (!r_shadow_shadowmaprectangletexture)
-                       R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize);
-               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;
-               break;
-       case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
-               r_shadow_shadowmap_parameters[0] = 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])
-                       R_Shadow_MakeShadowMap(side, size);
-               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_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
+       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;
+
+       // complex unrolled cube approach (more flexible)
+       if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
+               R_Shadow_MakeVSDCT();
+       if (!r_shadow_shadowmap2dtexture)
+               R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize);
+       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;
+
+       R_Mesh_ResetTextureState();
+       R_Mesh_ResetRenderTargets();
        R_Shadow_RenderMode_Reset();
        if (fbo)
        {
@@ -2201,79 +2092,67 @@ void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size)
 
 init_done:
        R_SetViewport(&viewport);
-       switch (r_shadow_rendermode)
+       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;
+       switch(vid.renderpath)
        {
-       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;
-               switch(vid.renderpath)
+       case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GL20:
+       case RENDERPATH_CGGL:
+               GL_CullFace(r_refdef.view.cullface_back);
+               // OpenGL lets us scissor larger than the viewport, so go ahead and clear all views at once
+               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, NULL, 1.0f, 0);
+               }
+               GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
+               break;
+       case RENDERPATH_D3D9:
+               Vector4Set(clearcolor, 1,1,1,1);
+               // completely different meaning than in OpenGL path
+               r_shadow_shadowmap_parameters[1] = 0;
+               r_shadow_shadowmap_parameters[3] = -bias;
+               // we invert the cull mode because we flip the projection matrix
+               // NOTE: this actually does nothing because the DrawShadowMap code sets it to doublesided...
+               GL_CullFace(r_refdef.view.cullface_front);
+               // D3D considers it an error to use a scissor larger than the viewport...  clear just this view
+               GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
+               if (r_shadow_shadowmapsampler)
                {
-               case RENDERPATH_GL11:
-               case RENDERPATH_GL13:
-               case RENDERPATH_GL20:
-               case RENDERPATH_CGGL:
-                       GL_CullFace(r_refdef.view.cullface_back);
-                       // OpenGL lets us scissor larger than the viewport, so go ahead and clear all views at once
-                       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, NULL, 1.0f, 0);
-                       }
-                       GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
-                       break;
-               case RENDERPATH_D3D9:
-                       // completely different meaning than in OpenGL path
-                       r_shadow_shadowmap_parameters[1] = 0;
-                       r_shadow_shadowmap_parameters[3] = -bias;
-                       // we invert the cull mode because we flip the projection matrix
-                       // NOTE: this actually does nothing because the DrawShadowMap code sets it to doublesided...
-                       GL_CullFace(r_refdef.view.cullface_front);
-                       // D3D considers it an error to use a scissor larger than the viewport...  clear just this view
-                       GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
-                       if (r_shadow_shadowmapsampler)
-                       {
-                               GL_ColorMask(0,0,0,0);
-                               if (clear)
-                                       GL_Clear(GL_DEPTH_BUFFER_BIT, testcolor, 1.0f, 0);
-                       }
-                       else
-                       {
-                               GL_ColorMask(1,1,1,1);
-                               if (clear)
-                                       GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, testcolor, 1.0f, 0);
-                       }
-                       break;
-               case RENDERPATH_D3D10:
-               case RENDERPATH_D3D11:
-                       // D3D considers it an error to use a scissor larger than the viewport...  clear just this view
-                       GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
                        GL_ColorMask(0,0,0,0);
                        if (clear)
-                               GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
-                       break;
+                               GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
+               }
+               else
+               {
+                       GL_ColorMask(1,1,1,1);
+                       if (clear)
+                               GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0);
                }
                break;
-       case R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE:
-               if (qglFramebufferTexture2DEXT)
-                       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
+       case RENDERPATH_D3D10:
+       case RENDERPATH_D3D11:
+               // D3D considers it an error to use a scissor larger than the viewport...  clear just this view
                GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
+               GL_ColorMask(0,0,0,0);
                if (clear)
                        GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
                break;
-       default:
-               break;
        }
 }
 
 void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qboolean shadowmapping)
 {
+       R_Mesh_ResetTextureState();
+       R_Mesh_ResetRenderTargets();
        if (transparent)
        {
                r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
@@ -2288,23 +2167,7 @@ void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qb
        // do global setup needed for the chosen lighting mode
        if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL)
                GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 0);
-       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_shadow_usingshadowmap2d = shadowmapping;
        r_shadow_rendermode = r_shadow_lightingrendermode;
        // only draw light where this geometry was already rendered AND the
        // stencil is 128 (values other than this mean shadow)
@@ -2351,23 +2214,7 @@ void R_Shadow_RenderMode_DrawDeferredLight(qboolean stenciltest, qboolean shadow
        R_SetStencil(stenciltest, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255);
        R_Mesh_SetRenderTargets(r_shadow_prepasslightingfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
 
-       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_shadow_usingshadowmap2d = shadowmapping;
 
        // render the lighting
        R_SetupShader_DeferredLight(rsurface.rtlight);
@@ -2439,131 +2286,21 @@ int bboxedges[12][2] =
 
 qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
 {
-       int i, ix1, iy1, ix2, iy2;
-       float x1, y1, x2, y2;
-       vec4_t v, v2;
-       float vertex[20][3];
-       int j, k;
-       vec4_t plane4f;
-       int numvertices;
-       float corner[8][4];
-       float dist[8];
-       int sign[8];
-       float f;
-
-       r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
-       r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
-       r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
-       r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
-
        if (!r_shadow_scissor.integer)
-               return false;
-
-       // if view is inside the light box, just say yes it's visible
-       if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
-               return false;
-
-       x1 = y1 = x2 = y2 = 0;
-
-       // transform all corners that are infront of the nearclip plane
-       VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
-       plane4f[3] = r_refdef.view.frustum[4].dist;
-       numvertices = 0;
-       for (i = 0;i < 8;i++)
-       {
-               Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
-               dist[i] = DotProduct4(corner[i], plane4f);
-               sign[i] = dist[i] > 0;
-               if (!sign[i])
-               {
-                       VectorCopy(corner[i], vertex[numvertices]);
-                       numvertices++;
-               }
-       }
-       // if some points are behind the nearclip, add clipped edge points to make
-       // sure that the scissor boundary is complete
-       if (numvertices > 0 && numvertices < 8)
        {
-               // add clipped edge points
-               for (i = 0;i < 12;i++)
-               {
-                       j = bboxedges[i][0];
-                       k = bboxedges[i][1];
-                       if (sign[j] != sign[k])
-                       {
-                               f = dist[j] / (dist[j] - dist[k]);
-                               VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
-                               numvertices++;
-                       }
-               }
-       }
-
-       // if we have no points to check, the light is behind the view plane
-       if (!numvertices)
-               return true;
-
-       // if we have some points to transform, check what screen area is covered
-       x1 = y1 = x2 = y2 = 0;
-       v[3] = 1.0f;
-       //Con_Printf("%i vertices to transform...\n", numvertices);
-       for (i = 0;i < numvertices;i++)
-       {
-               VectorCopy(vertex[i], v);
-               R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
-               //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]);
-               if (i)
-               {
-                       if (x1 > v2[0]) x1 = v2[0];
-                       if (x2 < v2[0]) x2 = v2[0];
-                       if (y1 > v2[1]) y1 = v2[1];
-                       if (y2 < v2[1]) y2 = v2[1];
-               }
-               else
-               {
-                       x1 = x2 = v2[0];
-                       y1 = y2 = v2[1];
-               }
-       }
-
-       // now convert the scissor rectangle to integer screen coordinates
-       ix1 = (int)(x1 - 1.0f);
-       iy1 = vid.height - (int)(y2 - 1.0f);
-       ix2 = (int)(x2 + 1.0f);
-       iy2 = vid.height - (int)(y1 + 1.0f);
-       //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
-
-       // clamp it to the screen
-       if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
-       if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
-       if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
-       if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
-
-       // if it is inside out, it's not visible
-       if (ix2 <= ix1 || iy2 <= iy1)
-               return true;
-
-       // the light area is visible, set up the scissor rectangle
-       r_shadow_lightscissor[0] = ix1;
-       r_shadow_lightscissor[1] = iy1;
-       r_shadow_lightscissor[2] = ix2 - ix1;
-       r_shadow_lightscissor[3] = iy2 - iy1;
-
-       // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
-       switch(vid.renderpath)
-       {
-       case RENDERPATH_D3D9:
-       case RENDERPATH_D3D10:
-       case RENDERPATH_D3D11:
-               r_shadow_lightscissor[1] = vid.height - r_shadow_lightscissor[1] - r_shadow_lightscissor[3];
-               break;
-       case RENDERPATH_GL11:
-       case RENDERPATH_GL13:
-       case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
-               break;
+               r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
+               r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
+               r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
+               r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
+               return false;
        }
-
-       r_refdef.stats.lights_scissored++;
+       if(R_ScissorForBBox(mins, maxs, r_shadow_lightscissor))
+               return true; // invisible
+       if(r_shadow_lightscissor[0] != r_refdef.view.viewport.x
+       || r_shadow_lightscissor[1] != r_refdef.view.viewport.y
+       || r_shadow_lightscissor[2] != r_refdef.view.viewport.width
+       || r_shadow_lightscissor[3] != r_refdef.view.viewport.height)
+               r_refdef.stats.lights_scissored++;
        return false;
 }
 
@@ -3104,8 +2841,6 @@ void R_RTLight_Compile(rtlight_t *rtlight)
                switch (rtlight->shadowmode)
                {
                case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
-               case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
-               case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
                        if (model->CompileShadowMap && rtlight->shadow)
                                model->CompileShadowMap(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
                        break;
@@ -3469,8 +3204,6 @@ void R_Shadow_DrawEntityShadow(entity_render_t *ent)
        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);
                break;
        default:
@@ -3847,7 +3580,7 @@ void R_Shadow_DrawLight(rtlight_t *rtlight)
        //lodlinear = (int)(r_shadow_shadowmapping_lod_bias.value + r_shadow_shadowmapping_lod_scale.value * rtlight->radius / max(1.0f, distance));
        lodlinear = bound(r_shadow_shadowmapping_minsize.integer, lodlinear, r_shadow_shadowmapmaxsize);
 
-       if (castshadows && (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE))
+       if (castshadows && r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
        {
                float borderbias;
                int side;
@@ -3862,10 +3595,7 @@ void R_Shadow_DrawLight(rtlight_t *rtlight)
                        if ((r_shadow_shadowmapmaxsize >> i) > lodlinear)
                                r_shadow_shadowmaplod = i;
 
-               if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
-                       size = max(1, r_shadow_shadowmapmaxsize >> r_shadow_shadowmaplod);
-               else
-                       size = bound(r_shadow_shadowmapborder, lodlinear, r_shadow_shadowmapmaxsize);
+               size = bound(r_shadow_shadowmapborder, lodlinear, r_shadow_shadowmapmaxsize);
                        
                borderbias = r_shadow_shadowmapborder / (float)(size - r_shadow_shadowmapborder);
 
@@ -3992,7 +3722,7 @@ void R_Shadow_DrawLight(rtlight_t *rtlight)
        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))
+               if (castshadows && r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
                        R_Shadow_RenderMode_DrawDeferredLight(false, true);
                else if (castshadows && vid.stencil)
                        R_Shadow_RenderMode_DrawDeferredLight(true, false);
@@ -4013,6 +3743,10 @@ static void R_Shadow_FreeDeferred(void)
                R_FreeTexture(r_shadow_prepassgeometrydepthtexture);
        r_shadow_prepassgeometrydepthtexture = NULL;
 
+       if (r_shadow_prepassgeometrydepthcolortexture)
+               R_FreeTexture(r_shadow_prepassgeometrydepthcolortexture);
+       r_shadow_prepassgeometrydepthcolortexture = NULL;
+
        if (r_shadow_prepassgeometrynormalmaptexture)
                R_FreeTexture(r_shadow_prepassgeometrynormalmaptexture);
        r_shadow_prepassgeometrynormalmaptexture = NULL;
@@ -4044,9 +3778,9 @@ void R_Shadow_DrawPrepass(void)
        GL_BlendFunc(GL_ONE, GL_ZERO);
        GL_Color(1,1,1,1);
        GL_DepthTest(true);
-       R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
+       R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepassgeometrynormalmaptexture, r_shadow_prepassgeometrydepthcolortexture, NULL, NULL);
        Vector4Set(clearcolor, 0.5f,0.5f,0.5f,1.0f);
-       GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, clearcolor, 1.0f, 0);
+       GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
        if (r_timereport_active)
                R_TimeReport("prepasscleargeom");
 
@@ -4122,8 +3856,7 @@ void R_Shadow_PrepareLights(void)
 
        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_deferred.integer) ||
-               r_shadow_shadowmapvsdct != (r_shadow_shadowmapping_vsdct.integer != 0) || 
-               r_shadow_shadowmaptexturetype != r_shadow_shadowmapping_texturetype.integer ||
+               r_shadow_shadowmapvsdct != (r_shadow_shadowmapping_vsdct.integer != 0 && vid.renderpath == RENDERPATH_GL20) || 
                r_shadow_shadowmapfilterquality != r_shadow_shadowmapping_filterquality.integer || 
                r_shadow_shadowmapdepthbits != r_shadow_shadowmapping_depthbits.integer || 
                r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16))
@@ -4155,13 +3888,21 @@ void R_Shadow_PrepareLights(void)
                        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);
+                       switch (vid.renderpath)
+                       {
+                       case RENDERPATH_D3D9:
+                               r_shadow_prepassgeometrydepthcolortexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrydepthcolormap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
+                               break;
+                       default:
+                               break;
+                       }
                        r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
                        r_shadow_prepasslightingdiffusetexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingdiffuse", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
                        r_shadow_prepasslightingspeculartexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingspecular", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
 
                        // set up the geometry pass fbo (depth + normalmap)
                        r_shadow_prepassgeometryfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthtexture, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
-                       R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
+                       R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepassgeometrynormalmaptexture, r_shadow_prepassgeometrydepthcolortexture, NULL, NULL);
                        // render depth into one texture and normalmap into the other
                        if (qglDrawBuffersARB)
                        {
@@ -4302,7 +4043,6 @@ void R_Shadow_PrepareModelShadows(void)
        switch (r_shadow_shadowmode)
        {
        case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
-       case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
                if (r_shadows.integer >= 2) 
                        break;
                // fall through
@@ -4380,7 +4120,6 @@ void R_DrawModelShadowMaps(void)
        switch (r_shadow_shadowmode)
        {
        case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
-       case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
                break;
        default:
                return;
@@ -4400,14 +4139,6 @@ void R_DrawModelShadowMaps(void)
                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;
        }
@@ -4453,7 +4184,7 @@ void R_DrawModelShadowMaps(void)
 
        VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
 
-       R_Mesh_SetRenderTargets(fbo, r_shadow_shadowmap2dtexture, NULL, NULL, NULL, NULL);
+       R_Mesh_SetRenderTargets(fbo, r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL);
        R_SetupShader_DepthOrShadow();
        GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
        GL_DepthMask(true);
@@ -4526,15 +4257,36 @@ void R_DrawModelShadowMaps(void)
        Matrix4x4_Concat(&texmatrix, &scalematrix, &shadowmatrix);
        Matrix4x4_Concat(&r_shadow_shadowmapmatrix, &texmatrix, &invmvpmatrix);
 
+       switch (vid.renderpath)
+       {
+       case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GL20:
+       case RENDERPATH_CGGL:
+               break;
+       case RENDERPATH_D3D9:
+       case RENDERPATH_D3D10:
+       case RENDERPATH_D3D11:
+#ifdef OPENGL_ORIENTATION
+               r_shadow_shadowmapmatrix.m[0][0]        *= -1.0f;
+               r_shadow_shadowmapmatrix.m[0][1]        *= -1.0f;
+               r_shadow_shadowmapmatrix.m[0][2]        *= -1.0f;
+               r_shadow_shadowmapmatrix.m[0][3]        *= -1.0f;
+#else
+               r_shadow_shadowmapmatrix.m[0][0]        *= -1.0f;
+               r_shadow_shadowmapmatrix.m[1][0]        *= -1.0f;
+               r_shadow_shadowmapmatrix.m[2][0]        *= -1.0f;
+               r_shadow_shadowmapmatrix.m[3][0]        *= -1.0f;
+#endif
+               break;
+       }
+
        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;
        }
@@ -6249,7 +6001,7 @@ LIGHT SAMPLING
 =============================================================================
 */
 
-void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const vec3_t p, int dynamic)
+void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const vec3_t p, qboolean dynamic, qboolean rtworld)
 {
        VectorClear(diffusecolor);
        VectorClear(diffusenormal);
@@ -6264,16 +6016,43 @@ void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffu
 
        if (dynamic)
        {
-               int i;
+               int i, numlights, flag;
                float f, v[3];
                rtlight_t *light;
+               dlight_t *dlight;
+
+               // sample rtlights
+               if (rtworld)
+               {
+                       flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
+                       numlights = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
+                       for (i = 0; i < numlights; i++)
+                       {
+                               dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i);
+                               if (!dlight)
+                                       continue;
+                               light = &dlight->rtlight;
+                               if (!(light->flags & flag))
+                                       continue;
+                               Matrix4x4_Transform(&light->matrix_worldtolight, p, v);
+                               f = 1 - VectorLength2(v);
+                               if (f <= 0)
+                                       continue;
+                               if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1)
+                                       VectorMA(ambientcolor, f, light->currentcolor, ambientcolor);
+                       }
+               }
+
+               // sample dlights
                for (i = 0;i < r_refdef.scene.numlights;i++)
                {
                        light = r_refdef.scene.lights[i];
                        Matrix4x4_Transform(&light->matrix_worldtolight, p, v);
-                       f = 1 - VectorLength2(v);
-                       if (f > 0 && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1)
-                               VectorMA(ambientcolor, f, light->currentcolor, ambientcolor);
+                       f = (1 - VectorLength2(v)) * r_refdef.scene.rtlightstylevalue[light->style];
+                       if (f <= 0)
+                               continue;
+                       if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1)
+                               VectorMA(ambientcolor, f, light->color, ambientcolor);
                }
        }
 }