]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
added indirection cube map for shadowmapping and revised filtering modes
[xonotic/darkplaces.git] / r_shadow.c
index 6ecd83c1552ca0202bea6ada73f97d370351d1eb..d992a762555d548d1435095155e104f7b4d4a9bd 100644 (file)
@@ -168,18 +168,15 @@ 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;
-float r_shadow_shadowmap_bias;
-float r_shadow_shadowmap_texturescale[2];
+float r_shadow_shadowmap_texturescale[4];
 float r_shadow_shadowmap_parameters[4];
 int r_shadow_drawbuffer;
 int r_shadow_readbuffer;
 GLuint r_shadow_fborectangle;
-GLuint r_shadow_fbocubeside[R_SHADOW_SHADOWMAP_NUMCUBEMAPS][6];
-GLuint r_shadow_fbo2d;
+int r_shadow_shadowmode;
 int r_shadow_shadowmapmaxsize;
+int r_shadow_shadowmapfilter;
+int r_shadow_shadowmapborder;
 int r_shadow_lightscissor[4];
 
 int maxshadowtriangles;
@@ -219,9 +216,7 @@ rtexture_t *r_shadow_attenuation2dtexture;
 rtexture_t *r_shadow_attenuation3dtexture;
 rtexture_t *r_shadow_lightcorona;
 rtexture_t *r_shadow_shadowmaprectangletexture;
-rtexture_t *r_shadow_shadowmap2dtexture;
-rtexture_t *r_shadow_shadowmapcubeprojectiontexture;
-rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
+rtexture_t *r_shadow_shadowmapcubeprojectiontexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
 int r_shadow_shadowmapsize; // changes for each light based on distance
 int r_shadow_shadowmaplod; // changes for each light based on distance
 
@@ -262,10 +257,10 @@ cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1", "use scissor optimization
 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_filterquality = {CVAR_SAVE, "r_shadow_shadowmapping_filterquality", "0", "shadowmap filter modes: 0 = no filtering, 1 = bilinear, 2 = bilinear small blur (fast), 3 = bilinear large blur (slow)"};
 cvar_t r_shadow_shadowmapping_minsize = {CVAR_SAVE, "r_shadow_shadowmapping_minsize", "32", "shadowmap size limit"};
-cvar_t r_shadow_shadowmapping_maxsize = {CVAR_SAVE, "r_shadow_shadowmapping_maxsize", "1024", "shadowmap size limit"};
-cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "8", "shadowmap size bias"};
-cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "1", "shadowmap size scaling parameter"};
-cvar_t r_shadow_shadowmapping_bordersize = {CVAR_SAVE, "r_shadow_shadowmapping_bordersize", "6", "shadowmap size bias for filtering"};
+cvar_t r_shadow_shadowmapping_maxsize = {CVAR_SAVE, "r_shadow_shadowmapping_maxsize", "512", "shadowmap size limit"};
+cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
+cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"};
+cvar_t r_shadow_shadowmapping_bordersize = {CVAR_SAVE, "r_shadow_shadowmapping_bordersize", "4", "shadowmap size bias for filtering"};
 cvar_t r_shadow_shadowmapping_nearclip = {CVAR_SAVE, "r_shadow_shadowmapping_nearclip", "1", "shadowmap nearclip in world units"};
 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_culltriangles = {0, "r_shadow_culltriangles", "1", "performs more expensive tests to remove unnecessary triangles of lit surfaces"};
@@ -334,6 +329,34 @@ cachepic_t *r_editlights_sprcubemaplight;
 cachepic_t *r_editlights_sprcubemapnoshadowlight;
 cachepic_t *r_editlights_sprselection;
 
+void R_Shadow_FreeShadowMaps(void)
+{
+       int i;
+
+       r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, 2048);
+       r_shadow_shadowmode = r_shadow_shadowmapping.integer;
+    r_shadow_shadowmapfilter = r_shadow_shadowmapping_filterquality.integer;
+    r_shadow_shadowmapborder = bound(0, r_shadow_shadowmapping_bordersize.integer, 16);
+       r_shadow_shadowmaplod = -1;
+
+       CHECKGLERROR
+       if (r_shadow_fborectangle)
+               qglDeleteFramebuffersEXT(1, &r_shadow_fborectangle);
+       r_shadow_fborectangle = 0;
+       CHECKGLERROR
+
+       if (r_shadow_shadowmaprectangletexture)
+               R_FreeTexture(r_shadow_shadowmaprectangletexture);
+       r_shadow_shadowmaprectangletexture = NULL;
+
+    for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
+        if (r_shadow_shadowmapcubeprojectiontexture[i])
+            R_FreeTexture(r_shadow_shadowmapcubeprojectiontexture[i]);
+    memset(r_shadow_shadowmapcubeprojectiontexture, 0, sizeof(r_shadow_shadowmapcubeprojectiontexture));
+
+       CHECKGLERROR
+}
+
 void r_shadow_start(void)
 {
        // allocate vertex processing arrays
@@ -341,16 +364,17 @@ void r_shadow_start(void)
        r_shadow_attenuationgradienttexture = NULL;
        r_shadow_attenuation2dtexture = NULL;
        r_shadow_attenuation3dtexture = NULL;
+       r_shadow_shadowmode = 0;
        r_shadow_shadowmaprectangletexture = NULL;
-       memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture));
-       r_shadow_shadowmapcubeprojectiontexture = NULL;
-       r_shadow_shadowmap2dtexture = NULL;
+    memset(r_shadow_shadowmapcubeprojectiontexture, 0, sizeof(r_shadow_shadowmapcubeprojectiontexture));
        r_shadow_shadowmapmaxsize = 0;
        r_shadow_shadowmapsize = 0;
        r_shadow_shadowmaplod = 0;
+    r_shadow_shadowmapfilter = 0;
        r_shadow_fborectangle = 0;
-       memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside));
-       r_shadow_fbo2d = 0;
+
+       R_Shadow_FreeShadowMaps();
+
        r_shadow_texturepool = NULL;
        r_shadow_filters_texturepool = NULL;
        R_Shadow_ValidateCvars();
@@ -383,35 +407,16 @@ void r_shadow_start(void)
 
 void r_shadow_shutdown(void)
 {
-       int i;
        CHECKGLERROR
        R_Shadow_UncompileWorldLights();
+
+       R_Shadow_FreeShadowMaps();
+
        CHECKGLERROR
        numcubemaps = 0;
        r_shadow_attenuationgradienttexture = NULL;
        r_shadow_attenuation2dtexture = NULL;
        r_shadow_attenuation3dtexture = NULL;
-       r_shadow_shadowmaprectangletexture = NULL;
-       memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture));
-       r_shadow_shadowmapcubeprojectiontexture = NULL;
-       r_shadow_shadowmap2dtexture = NULL;
-       r_shadow_shadowmapmaxsize = 0;
-       r_shadow_shadowmapsize = 0;
-       r_shadow_shadowmaplod = 0;
-       CHECKGLERROR
-       if (r_shadow_fborectangle)
-               qglDeleteFramebuffersEXT(1, &r_shadow_fborectangle);
-       r_shadow_fborectangle = 0;
-       CHECKGLERROR
-       for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
-               if (r_shadow_fbocubeside[i])
-                       qglDeleteFramebuffersEXT(6, r_shadow_fbocubeside[i]);
-       memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside));
-       CHECKGLERROR
-       if (r_shadow_fbo2d)
-               qglDeleteFramebuffersEXT(1, &r_shadow_fbo2d);
-       r_shadow_fbo2d = 0;
-       CHECKGLERROR
        R_FreeTexturePool(&r_shadow_texturepool);
        R_FreeTexturePool(&r_shadow_filters_texturepool);
        maxshadowtriangles = 0;
@@ -1302,7 +1307,7 @@ void R_Shadow_RenderMode_Begin(void)
        GL_DepthTest(true);
        GL_DepthMask(false);
        GL_Color(0, 0, 0, 1);
-       GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.y - r_refdef.view.height, r_refdef.view.width, r_refdef.view.height);
+       GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
 
        r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
 
@@ -1372,9 +1377,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_SetupGenericShader(false);
-       r_shadow_usingshadowmaprect = false;
-       r_shadow_usingshadowmapcube = false;
-       r_shadow_usingshadowmap2d = false;
        CHECKGLERROR
 }
 
@@ -1437,175 +1439,59 @@ void R_Shadow_RenderMode_StencilShadowVolumes(qboolean zpass)
 
 void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size)
 {
-       int i;
        int status;
        int maxsize;
-       float nearclip, farclip;
+       float nearclip, farclip, bias;
        r_viewport_t viewport;
        CHECKGLERROR
-       maxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, 2048);
-       if (r_shadow_shadowmapmaxsize != maxsize)
-       {
-               r_shadow_shadowmapmaxsize = maxsize;
-
-               if (r_shadow_fborectangle)
-                       qglDeleteFramebuffersEXT(1, &r_shadow_fborectangle);
-               r_shadow_fborectangle = 0;
-
-               if (r_shadow_fbo2d)
-                       qglDeleteFramebuffersEXT(1, &r_shadow_fbo2d);
-               r_shadow_fbo2d = 0;
-
-               for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
-                       if (r_shadow_fbocubeside[i])
-                               qglDeleteFramebuffersEXT(6, r_shadow_fbocubeside[i]);
-               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;
-
-               if (r_shadow_shadowmapcubeprojectiontexture)
-                       R_FreeTexture(r_shadow_shadowmapcubeprojectiontexture);
-               r_shadow_shadowmapcubeprojectiontexture = 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));
-
-               CHECKGLERROR
-       }
+       maxsize = r_shadow_shadowmapmaxsize;
        nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
        farclip = 1.0f;
-       r_shadow_shadowmap_bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
-       r_shadow_shadowmap_parameters[0] = 1.0f - r_shadow_shadowmapping_bordersize.value / size;
-       r_shadow_shadowmap_parameters[1] = 1.0f - r_shadow_shadowmapping_bordersize.value / size;
-       r_shadow_shadowmap_parameters[2] = -(farclip + nearclip) / (farclip - nearclip);
-       r_shadow_shadowmap_parameters[3] = -2.0f * nearclip * farclip / (farclip - nearclip);
-       if (!r_shadow_shadowmapcubeprojectiontexture)
-               r_shadow_shadowmapcubeprojectiontexture = R_LoadTextureCubeProjection(r_shadow_texturepool, "shadowmapcubeprojection");
-       if (r_shadow_shadowmapping.integer == 1)
-       {
-               // complex unrolled cube approach (more flexible)
-               if (!r_shadow_shadowmap2dtexture)
-               {
-#if 1
-                       r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", size*2, size*4);
-                       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
-#endif
-               }
-               CHECKGLERROR
-               R_Shadow_RenderMode_Reset();
-               if (r_shadow_shadowmap2dtexture)
-               {
-                       // render depth into the fbo, do not render color at all
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbo2d);CHECKGLERROR
-                       qglDrawBuffer(GL_NONE);CHECKGLERROR
-                       qglReadBuffer(GL_NONE);CHECKGLERROR
-                       status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
-                       if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
-                       {
-                               Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
-                               Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
-                       }
-                       R_SetupDepthOrShadowShader();
-               }
-               else
-               {
-                       R_SetupShowDepthShader();
-                       qglClearColor(1,1,1,1);CHECKGLERROR
-               }
-               R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapping_bordersize.integer, nearclip, farclip, NULL);
-               r_shadow_shadowmap_texturescale[0] = (float)size / R_TextureWidth(r_shadow_shadowmap2dtexture);
-               r_shadow_shadowmap_texturescale[1] = (float)size / R_TextureHeight(r_shadow_shadowmap2dtexture);
-               r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
-       }
-       else if (r_shadow_shadowmapping.integer == 2)
+       bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
+       // complex unrolled cube approach (more flexible)
+       if (!r_shadow_shadowmapcubeprojectiontexture[r_shadow_shadowmaplod])
+               r_shadow_shadowmapcubeprojectiontexture[r_shadow_shadowmaplod] = R_LoadTextureCubeProjection(r_shadow_texturepool, "shadowmapcubeprojection", size, r_shadow_shadowmapborder);
+       if (!r_shadow_shadowmaprectangletexture)
        {
-               // complex unrolled cube approach (more flexible)
-               if (!r_shadow_shadowmaprectangletexture)
-               {
 #if 1
-                       r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", size*2, size*4);
-                       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
+               r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*3, r_shadow_shadowmapfilter == 1 || r_shadow_shadowmapfilter == 2);
+               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
 #endif
-               }
-               CHECKGLERROR
-               R_Shadow_RenderMode_Reset();
-               if (r_shadow_shadowmaprectangletexture)
-               {
-                       // render depth into the fbo, do not render color at all
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
-                       qglDrawBuffer(GL_NONE);CHECKGLERROR
-                       qglReadBuffer(GL_NONE);CHECKGLERROR
-                       status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
-                       if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
-                       {
-                               Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
-                               Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
-                       }
-                       R_SetupDepthOrShadowShader();
-               }
-               else
-               {
-                       R_SetupShowDepthShader();
-                       qglClearColor(1,1,1,1);CHECKGLERROR
-               }
-               R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapping_bordersize.integer, nearclip, farclip, NULL);
-               r_shadow_shadowmap_texturescale[0] = size;
-               r_shadow_shadowmap_texturescale[1] = size;
-               r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE;
        }
-       else if (r_shadow_shadowmapping.integer == 3)
-       {
-               // 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);
-                       qglGenFramebuffersEXT(6, r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
-                       for (i = 0;i < 6;i++)
-                       {
-                               qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod][i]);CHECKGLERROR
-                               qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
-                       }
-#endif
-               }
-               CHECKGLERROR
-               R_Shadow_RenderMode_Reset();
-               if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod])
-               {
-                       // render depth into the fbo, do not render color at all
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod][side]);CHECKGLERROR
-                       qglDrawBuffer(GL_NONE);CHECKGLERROR
-                       qglReadBuffer(GL_NONE);CHECKGLERROR
-                       status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
-                       if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
-                       {
-                               Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
-                               Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
-                       }
-                       R_SetupDepthOrShadowShader();
-               }
-               else
+       CHECKGLERROR
+       R_Shadow_RenderMode_Reset();
+       if (r_shadow_shadowmaprectangletexture)
+       {
+               // render depth into the fbo, do not render color at all
+               qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
+               qglDrawBuffer(GL_NONE);CHECKGLERROR
+               qglReadBuffer(GL_NONE);CHECKGLERROR
+               status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
+               if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
                {
-                       R_SetupShowDepthShader();
-                       qglClearColor(1,1,1,1);CHECKGLERROR
+                       Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
+                       Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
                }
-               R_Viewport_InitCubeSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, nearclip, farclip, NULL);
-               r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
-               r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureWidth(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
-               r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE;
+               R_SetupDepthOrShadowShader();
        }
+       else
+       {
+               R_SetupShowDepthShader();
+               qglClearColor(1,1,1,1);CHECKGLERROR
+       }
+       R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
+       r_shadow_shadowmap_texturescale[0] = 2*size;
+       r_shadow_shadowmap_texturescale[1] = 3*size;
+       r_shadow_shadowmap_texturescale[2] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip);
+       r_shadow_shadowmap_texturescale[3] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
+       // compat for ALU cubemap calcs
+    r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
+       r_shadow_shadowmap_parameters[1] = size;
+       r_shadow_shadowmap_parameters[2] = r_shadow_shadowmap_texturescale[2];
+       r_shadow_shadowmap_parameters[3] = r_shadow_shadowmap_texturescale[3];
+       r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE;
        CHECKGLERROR
        R_SetViewport(&viewport);
        GL_PolygonOffset(0, 0);
@@ -1645,24 +1531,10 @@ void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qb
                CHECKGLERROR
                if (shadowmapping)
                {
-                       if (r_shadow_shadowmapping.integer == 1)
-                       {
-                               r_shadow_usingshadowmap2d = true;
-                               R_Mesh_TexBind(GL20TU_SHADOWMAP2D, R_GetTexture(r_shadow_shadowmap2dtexture));
-                               CHECKGLERROR
-                       }
-                       else if (r_shadow_shadowmapping.integer == 2)
-                       {
-                               r_shadow_usingshadowmaprect = true;
-                               R_Mesh_TexBindRectangle(GL20TU_SHADOWMAPRECT, R_GetTexture(r_shadow_shadowmaprectangletexture));
-                               CHECKGLERROR
-                       }
-                       else if (r_shadow_shadowmapping.integer == 3)
-                       {
-                               r_shadow_usingshadowmapcube = true;
-                               R_Mesh_TexBindCubeMap(GL20TU_SHADOWMAPCUBE, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));
-                               CHECKGLERROR
-                       }
+                       R_Mesh_TexBindRectangle(GL20TU_SHADOWMAPRECT, R_GetTexture(r_shadow_shadowmaprectangletexture));
+                       CHECKGLERROR
+                       R_Mesh_TexBindCubeMap(GL20TU_CUBEPROJECTION, R_GetTexture(r_shadow_shadowmapcubeprojectiontexture[r_shadow_shadowmaplod]));
+                       CHECKGLERROR
                }
        }
        else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_VERTEX)
@@ -1710,7 +1582,7 @@ void R_Shadow_RenderMode_End(void)
        R_Shadow_RenderMode_Reset();
        R_Shadow_RenderMode_ActiveLight(NULL);
        GL_DepthMask(true);
-       GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.y - r_refdef.view.height, r_refdef.view.width, r_refdef.view.height);
+       GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
        r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
 }
 
@@ -1747,10 +1619,10 @@ qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
        int sign[8];
        float f;
 
-       r_shadow_lightscissor[0] = r_refdef.view.x;
-       r_shadow_lightscissor[1] = vid.height - r_refdef.view.y - r_refdef.view.height;
-       r_shadow_lightscissor[2] = r_refdef.view.width;
-       r_shadow_lightscissor[3] = r_refdef.view.height;
+       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;
@@ -1823,16 +1695,16 @@ qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
 
        // now convert the scissor rectangle to integer screen coordinates
        ix1 = (int)(x1 - 1.0f);
-       iy1 = (int)(y1 - 1.0f);
+       iy1 = vid.height - (int)(y2 - 1.0f);
        ix2 = (int)(x2 + 1.0f);
-       iy2 = (int)(y2 + 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.x) ix1 = r_refdef.view.x;
-       if (iy1 < r_refdef.view.y) iy1 = r_refdef.view.y;
-       if (ix2 > r_refdef.view.x + r_refdef.view.width) ix2 = r_refdef.view.x + r_refdef.view.width;
-       if (iy2 > r_refdef.view.y + r_refdef.view.height) iy2 = r_refdef.view.y + r_refdef.view.height;
+       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)
@@ -1840,7 +1712,7 @@ qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
 
        // the light area is visible, set up the scissor rectangle
        r_shadow_lightscissor[0] = ix1;
-       r_shadow_lightscissor[1] = vid.height - iy2;
+       r_shadow_lightscissor[1] = iy1;
        r_shadow_lightscissor[2] = ix2 - ix1;
        r_shadow_lightscissor[3] = iy2 - iy1;
 
@@ -3688,7 +3560,7 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
        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_shadowmapping_maxsize.integer);
 
-       if (castshadows && r_shadow_shadowmapping.integer >= 1 && r_shadow_shadowmapping.integer <= 3 && r_glsl.integer && gl_support_fragment_shader)
+       if (castshadows && r_shadow_shadowmode && r_glsl.integer && gl_support_fragment_shader)
        {
                int side;
                int size;
@@ -3698,10 +3570,7 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
                        if ((r_shadow_shadowmapping_maxsize.integer >> i) > lodlinear)
                                r_shadow_shadowmaplod = i;
 
-               size = lodlinear;
-               if (r_shadow_shadowmapping.integer == 3)
-                       size = bound(1, r_shadow_shadowmapping_maxsize.integer, 2048) >> r_shadow_shadowmaplod;
-               size = bound(1, size, 2048);
+               size = bound(1, r_shadow_shadowmapping_maxsize.integer >> r_shadow_shadowmaplod, 2048);
 
                //Con_Printf("distance %f lodlinear %i (lod %i) size %i\n", distance, lodlinear, r_shadow_shadowmaplod, size);
 
@@ -3730,22 +3599,6 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
                        R_Shadow_RenderMode_ShadowMap(side, false, size);
                        for (i = 0;i < numshadowentities_noselfshadow;i++)
                                R_Shadow_DrawEntityShadow(shadowentities_noselfshadow[i]);
-#if 0
-                       if (r_shadow_shadowmapping.integer == 1)
-                       {
-                               int w = R_TextureWidth(r_shadow_shadowmap2dtexture);
-                               int h = R_TextureHeight(r_shadow_shadowmap2dtexture);
-                               static int once = true;
-                               if (once)
-                               {
-                                       unsigned char *blah = Z_Malloc(w*h*4);
-                                       qglReadPixels(0, 0, w, h, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, blah);CHECKGLERROR
-                                       FS_WriteFile("testshadowmap.bin", blah, w*h*4);
-                                       Z_Free(blah);
-                               }
-                               once = false;
-                       }
-#endif
                }
 
                // render lighting using the depth texture as shadowmap
@@ -3761,6 +3614,7 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
        {
                // draw stencil shadow volumes to mask off pixels that are in shadow
                // so that they won't receive lighting
+               GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]);
                R_Shadow_ClearStencil();
                if (numsurfaces)
                        R_Shadow_DrawWorldShadow(numsurfaces, surfacelist, shadowtrispvs);
@@ -3820,6 +3674,9 @@ void R_ShadowVolumeLighting(qboolean visible)
        dlight_t *light;
        size_t range;
 
+       if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, 2048) || r_shadow_shadowmode != r_shadow_shadowmapping.integer || r_shadow_shadowmapfilter != r_shadow_shadowmapping_filterquality.integer || r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16))
+               R_Shadow_FreeShadowMaps();
+
        if (r_editlights.integer)
                R_Shadow_DrawLightSprites();
 
@@ -3850,10 +3707,13 @@ void R_ShadowVolumeLighting(qboolean visible)
        R_Shadow_RenderMode_End();
 }
 
+extern const float r_screenvertex3f[12];
 extern void R_SetupView(qboolean allowwaterclippingplane);
+extern void R_ResetViewRendering3D(void);
+extern void R_ResetViewRendering2D(void);
 extern cvar_t r_shadows;
 extern cvar_t r_shadows_darken;
-extern cvar_t r_shadows_drawafterrtlightning;
+extern cvar_t r_shadows_drawafterrtlighting;
 extern cvar_t r_shadows_castfrombmodels;
 extern cvar_t r_shadows_throwdistance;
 extern cvar_t r_shadows_throwdirection;
@@ -3866,32 +3726,21 @@ void R_DrawModelShadows(void)
        vec3_t relativelightdirection;
        vec3_t relativeshadowmins, relativeshadowmaxs;
        vec3_t tmp, shadowdir;
-       float vertex3f[12];
-       r_viewport_t viewport;
 
        if (!r_drawentities.integer || !gl_stencil)
                return;
 
        CHECKGLERROR
-       GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.y - r_refdef.view.height, r_refdef.view.width, r_refdef.view.height);
-
-       r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
-
-       if (gl_ext_separatestencil.integer)
-       {
-               r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL;
-               r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL;
-       }
-       else if (gl_ext_stenciltwoside.integer)
-       {
-               r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE;
-               r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE;
-       }
-       else
-       {
-               r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_STENCIL;
-               r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_STENCIL;
-       }
+       R_ResetViewRendering3D();
+       //GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+       //GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
+       R_Shadow_RenderMode_Begin();
+       R_Shadow_RenderMode_ActiveLight(NULL);
+       r_shadow_lightscissor[0] = r_refdef.view.x;
+       r_shadow_lightscissor[1] = vid.height - r_refdef.view.y - r_refdef.view.height;
+       r_shadow_lightscissor[2] = r_refdef.view.width;
+       r_shadow_lightscissor[3] = r_refdef.view.height;
+       R_Shadow_RenderMode_StencilShadowVolumes(false);
 
        // get shadow dir
        if (r_shadows.integer == 2)
@@ -3951,34 +3800,28 @@ void R_DrawModelShadows(void)
        }
 
        // not really the right mode, but this will disable any silly stencil features
-       R_Shadow_RenderMode_VisibleLighting(true, true);
-
-       // vertex coordinates for a quad that covers the screen exactly
-       vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
-       vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
-       vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
-       vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
+       R_Shadow_RenderMode_End();
 
        // set up ortho view for rendering this pass
-       R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
-       R_SetViewport(&viewport);
-       GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.y - r_refdef.view.height, 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_Mesh_ResetTextureState();
-       R_Mesh_VertexPointer(vertex3f, 0, 0);
+       //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_Mesh_ResetTextureState();
+       R_ResetViewRendering2D();
+       R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
        R_Mesh_ColorPointer(NULL, 0, 0);
+       R_SetupGenericShader(false);
 
        // set up a darkening blend on shadowed areas
        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       GL_DepthRange(0, 1);
-       GL_DepthTest(false);
-       GL_DepthMask(false);
-       GL_PolygonOffset(0, 0);CHECKGLERROR
+       //GL_DepthRange(0, 1);
+       //GL_DepthTest(false);
+       //GL_DepthMask(false);
+       //GL_PolygonOffset(0, 0);CHECKGLERROR
        GL_Color(0, 0, 0, r_shadows_darken.value);
-       GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
-       qglDepthFunc(GL_ALWAYS);CHECKGLERROR
+       //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
        qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
@@ -3991,7 +3834,7 @@ void R_DrawModelShadows(void)
        R_SetViewport(&r_refdef.view.viewport);
 
        // restore other state to normal
-       R_Shadow_RenderMode_End();
+       //R_Shadow_RenderMode_End();
 }
 
 void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)