This is an automated email from the git hooks/post-receive script.

smcv pushed a commit to annotated tag 1.42d
in repository iortcw.

commit d17523d351ec3d55a576cd3c64532d662b5e157c
Author: m4n4t4...@gmail.com 
<m4n4t4...@gmail.com@e65d2741-a53d-b2dc-ae96-bb75fa5e4c4a>
Date:   Fri Aug 1 19:23:06 2014 +0000

    All: Rend2: Add fourth cascade for sun shadows and adjust sun shadow cvar 
defaults
---
 MP/code/rend2/glsl/shadowmask_fp.glsl |  91 ++++++++++--------
 MP/code/rend2/tr_backend.c            |  25 +++--
 MP/code/rend2/tr_bsp.c                |   3 +
 MP/code/rend2/tr_fbo.c                |   2 +-
 MP/code/rend2/tr_glsl.c               |   6 +-
 MP/code/rend2/tr_image.c              |   7 +-
 MP/code/rend2/tr_init.c               |   6 +-
 MP/code/rend2/tr_local.h              |  11 ++-
 MP/code/rend2/tr_main.c               | 175 +++++++++++++++++++++++-----------
 MP/code/rend2/tr_scene.c              |  27 +++++-
 SP/code/rend2/glsl/shadowmask_fp.glsl |  91 ++++++++++--------
 SP/code/rend2/tr_backend.c            |  25 +++--
 SP/code/rend2/tr_bsp.c                |   3 +
 SP/code/rend2/tr_fbo.c                |   2 +-
 SP/code/rend2/tr_glsl.c               |   6 +-
 SP/code/rend2/tr_image.c              |   7 +-
 SP/code/rend2/tr_init.c               |   6 +-
 SP/code/rend2/tr_local.h              |  11 ++-
 SP/code/rend2/tr_main.c               | 175 +++++++++++++++++++++++-----------
 SP/code/rend2/tr_scene.c              |  27 +++++-
 20 files changed, 478 insertions(+), 228 deletions(-)

diff --git a/MP/code/rend2/glsl/shadowmask_fp.glsl 
b/MP/code/rend2/glsl/shadowmask_fp.glsl
index b489fef..8a5597a 100644
--- a/MP/code/rend2/glsl/shadowmask_fp.glsl
+++ b/MP/code/rend2/glsl/shadowmask_fp.glsl
@@ -1,15 +1,17 @@
 uniform sampler2D u_ScreenDepthMap;
 
-uniform sampler2D u_ShadowMap;
+uniform sampler2DShadow u_ShadowMap;
 #if defined(USE_SHADOW_CASCADE)
-uniform sampler2D u_ShadowMap2;
-uniform sampler2D u_ShadowMap3;
+uniform sampler2DShadow u_ShadowMap2;
+uniform sampler2DShadow u_ShadowMap3;
+uniform sampler2DShadow u_ShadowMap4;
 #endif
 
 uniform mat4      u_ShadowMvp;
 #if defined(USE_SHADOW_CASCADE)
 uniform mat4      u_ShadowMvp2;
 uniform mat4      u_ShadowMvp3;
+uniform mat4      u_ShadowMvp4;
 #endif
 
 uniform vec3   u_ViewOrigin;
@@ -39,94 +41,103 @@ float random( const vec2 p )
   return mod( 123456789., 1e-7 + 256. * dot(p,r) );  
 }
 
-float PCF(const sampler2D shadowmap, const vec2 st, const float dist)
+float PCF(const sampler2DShadow shadowmap, const vec2 st, const float dist)
 {
        float mult;
        float scale = 2.0 / r_shadowMapSize;
 
+#if 0
+       // from http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+       vec2 offset = vec2(greaterThan(fract(var_DepthTex.xy * r_FBufScale * 
0.5), vec2(0.25)));
+       offset.y += offset.x;
+       if (offset.y > 1.1) offset.y = 0.0;
+       
+       mult = shadow2D(shadowmap, vec3(st + (offset + vec2(-1.5,  0.5)) * 
scale, dist)).r
+            + shadow2D(shadowmap, vec3(st + (offset + vec2( 0.5,  0.5)) * 
scale, dist)).r
+            + shadow2D(shadowmap, vec3(st + (offset + vec2(-1.5, -1.5)) * 
scale, dist)).r
+            + shadow2D(shadowmap, vec3(st + (offset + vec2( 0.5, -1.5)) * 
scale, dist)).r;
+        
+       mult *= 0.25;
+#endif
+
 #if defined(USE_SHADOW_FILTER)
        float r = random(var_DepthTex.xy);
        float sinr = sin(r) * scale;
        float cosr = cos(r) * scale;
        mat2 rmat = mat2(cosr, sinr, -sinr, cosr);
 
-       mult =  step(dist, texture2D(shadowmap, st + rmat * vec2(-0.7055767, 
0.196515)).r);
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.3524343, 
-0.7791386)).r);
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.2391056, 
0.9189604)).r);
+       mult =  shadow2D(shadowmap, vec3(st + rmat * vec2(-0.7055767, 
0.196515), dist)).r;
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.3524343, 
-0.7791386), dist)).r;
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.2391056, 
0.9189604), dist)).r;
   #if defined(USE_SHADOW_FILTER2)
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(-0.07580382, 
-0.09224417)).r);
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.5784913, 
-0.002528916)).r);
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.192888, 
0.4064181)).r);
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(-0.6335801, 
-0.5247476)).r);
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(-0.5579782, 
0.7491854)).r);
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.7320465, 
0.6317794)).r);
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(-0.07580382, 
-0.09224417), dist)).r;
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.5784913, 
-0.002528916), dist)).r;
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.192888, 0.4064181), 
dist)).r;
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(-0.6335801, 
-0.5247476), dist)).r;
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(-0.5579782, 
0.7491854), dist)).r;
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.7320465, 
0.6317794), dist)).r;
 
        mult *= 0.11111;
   #else
     mult *= 0.33333;
   #endif
 #else
-       mult = step(dist, texture2D(shadowmap, st).r);
+       mult = shadow2D(shadowmap, vec3(st, dist));
 #endif
-               
+
        return mult;
 }
 
 float getLinearDepth(sampler2D depthMap, vec2 tex, float zFarDivZNear)
 {
-               float sampleZDivW = texture2D(depthMap, tex).r;
-               sampleZDivW -= DEPTH_MAX_ERROR;
-               return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW);
+       float sampleZDivW = texture2D(depthMap, tex).r - DEPTH_MAX_ERROR;
+       return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW);
 }
 
 void main()
 {
        float result;
-       
-       float depth = getLinearDepth(u_ScreenDepthMap, var_DepthTex, 
u_ViewInfo.x);
-       float sampleZ = u_ViewInfo.y * depth;
 
+       float depth = getLinearDepth(u_ScreenDepthMap, var_DepthTex, 
u_ViewInfo.x);
        vec4 biasPos = vec4(u_ViewOrigin + var_ViewDir * (depth - 0.5 / 
u_ViewInfo.x), 1.0);
-       
+
        vec4 shadowpos = u_ShadowMvp * biasPos;
-       
-#if defined(USE_SHADOW_CASCADE)
-       const float fadeTo = 1.0;
-       result = fadeTo;
-#else
-       result = 0.0;
-#endif
 
-       if (all(lessThanEqual(abs(shadowpos.xyz), vec3(abs(shadowpos.w)))))
+#if defined(USE_SHADOW_CASCADE)
+       if (all(lessThan(abs(shadowpos.xyz), vec3(abs(shadowpos.w)))))
        {
-               shadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5;
+#endif
+               shadowpos.xyz = shadowpos.xyz * (0.5 / shadowpos.w) + vec3(0.5);
                result = PCF(u_ShadowMap, shadowpos.xy, shadowpos.z);
-       }
 #if defined(USE_SHADOW_CASCADE)
+       }
        else
        {
                shadowpos = u_ShadowMvp2 * biasPos;
 
-               if (all(lessThanEqual(abs(shadowpos.xyz), 
vec3(abs(shadowpos.w)))))
+               if (all(lessThan(abs(shadowpos.xyz), vec3(abs(shadowpos.w)))))
                {
-                       shadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5;
+                       shadowpos.xyz = shadowpos.xyz * (0.5 / shadowpos.w) + 
vec3(0.5);
                        result = PCF(u_ShadowMap2, shadowpos.xy, shadowpos.z);
                }
                else
                {
                        shadowpos = u_ShadowMvp3 * biasPos;
 
-                       if (all(lessThanEqual(abs(shadowpos.xyz), 
vec3(abs(shadowpos.w)))))
+                       if (all(lessThan(abs(shadowpos.xyz), 
vec3(abs(shadowpos.w)))))
                        {
-                               shadowpos.xyz = shadowpos.xyz / shadowpos.w * 
0.5 + 0.5;
+                               shadowpos.xyz = shadowpos.xyz * (0.5 / 
shadowpos.w) + vec3(0.5);
                                result = PCF(u_ShadowMap3, shadowpos.xy, 
shadowpos.z);
-
-                               float fade = clamp(sampleZ / 
r_shadowCascadeZFar * 10.0 - 9.0, 0.0, 1.0);
-                               result = mix(result, fadeTo, fade);
+                       }
+                       else
+                       {
+                               shadowpos = u_ShadowMvp4 * biasPos;
+                               shadowpos.xyz = shadowpos.xyz * (0.5 / 
shadowpos.w) + vec3(0.5);
+                               result = PCF(u_ShadowMap4, shadowpos.xy, 
shadowpos.z);
                        }
                }
        }
 #endif
-               
+
        gl_FragColor = vec4(vec3(result), 1.0);
 }
diff --git a/MP/code/rend2/tr_backend.c b/MP/code/rend2/tr_backend.c
index a0f9eb5..812aa66 100644
--- a/MP/code/rend2/tr_backend.c
+++ b/MP/code/rend2/tr_backend.c
@@ -1379,13 +1379,24 @@ const void  *RB_DrawSurfs( const void *data ) {
                        GLSL_BindProgram(&tr.shadowmaskShader);
 
                        GL_BindToTMU(tr.renderDepthImage, TB_COLORMAP);
-                       GL_BindToTMU(tr.sunShadowDepthImage[0], TB_SHADOWMAP);
-                       GL_BindToTMU(tr.sunShadowDepthImage[1], TB_SHADOWMAP2);
-                       GL_BindToTMU(tr.sunShadowDepthImage[2], TB_SHADOWMAP3);
 
-                       GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP,  backEnd.refdef.sunShadowMvp[0]);
-                       GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP2, backEnd.refdef.sunShadowMvp[1]);
-                       GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP3, backEnd.refdef.sunShadowMvp[2]);
+                       if (r_shadowCascadeZFar->integer != 0)
+                       {
+                               GL_BindToTMU(tr.sunShadowDepthImage[0], 
TB_SHADOWMAP);
+                               GL_BindToTMU(tr.sunShadowDepthImage[1], 
TB_SHADOWMAP2);
+                               GL_BindToTMU(tr.sunShadowDepthImage[2], 
TB_SHADOWMAP3);
+                               GL_BindToTMU(tr.sunShadowDepthImage[3], 
TB_SHADOWMAP4);
+
+                               GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP,  backEnd.refdef.sunShadowMvp[0]);
+                               GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP2, backEnd.refdef.sunShadowMvp[1]);
+                               GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP3, backEnd.refdef.sunShadowMvp[2]);
+                               GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP4, backEnd.refdef.sunShadowMvp[3]);
+                       }
+                       else
+                       {
+                               GL_BindToTMU(tr.sunShadowDepthImage[3], 
TB_SHADOWMAP);
+                               GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP, backEnd.refdef.sunShadowMvp[3]);
+                       }
                        
                        GLSL_SetUniformVec3(&tr.shadowmaskShader, 
UNIFORM_VIEWORIGIN,  backEnd.refdef.vieworg);
                        {
@@ -1939,6 +1950,8 @@ const void *RB_PostProcess(const void *data)
                FBO_BlitFromTexture(tr.sunShadowDepthImage[1], NULL, NULL, 
NULL, dstBox, NULL, NULL, 0);
                VectorSet4(dstBox, 256, 0, 128, 128);
                FBO_BlitFromTexture(tr.sunShadowDepthImage[2], NULL, NULL, 
NULL, dstBox, NULL, NULL, 0);
+               VectorSet4(dstBox, 384, 0, 128, 128);
+               FBO_BlitFromTexture(tr.sunShadowDepthImage[3], NULL, NULL, 
NULL, dstBox, NULL, NULL, 0);
        }
 
        if (0)
diff --git a/MP/code/rend2/tr_bsp.c b/MP/code/rend2/tr_bsp.c
index db88eb1..e903b15 100644
--- a/MP/code/rend2/tr_bsp.c
+++ b/MP/code/rend2/tr_bsp.c
@@ -3681,6 +3681,9 @@ void RE_LoadWorldMap( const char *name ) {
        tr.toneMinAvgMaxLevel[1] = -2.0f;
        tr.toneMinAvgMaxLevel[2] = 0.0f;
 
+       // reset last cascade sun direction so last shadow cascade is rerendered
+       VectorClear(tr.lastCascadeSunDirection);
+
        tr.worldMapLoaded = qtrue;
 
        // load it
diff --git a/MP/code/rend2/tr_fbo.c b/MP/code/rend2/tr_fbo.c
index c642b73..4070c6e 100644
--- a/MP/code/rend2/tr_fbo.c
+++ b/MP/code/rend2/tr_fbo.c
@@ -484,7 +484,7 @@ void FBO_Init(void)
 
        if (tr.sunShadowDepthImage[0])
        {
-               for ( i = 0; i < 3; i++)
+               for ( i = 0; i < 4; i++)
                {
                        tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", 
tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height);
                        FBO_Bind(tr.sunShadowFbo[i]);
diff --git a/MP/code/rend2/tr_glsl.c b/MP/code/rend2/tr_glsl.c
index c304f2b..ba75215 100644
--- a/MP/code/rend2/tr_glsl.c
+++ b/MP/code/rend2/tr_glsl.c
@@ -79,10 +79,12 @@ static uniformInfo_t uniformsInfo[] =
        { "u_ShadowMap",  GLSL_INT },
        { "u_ShadowMap2", GLSL_INT },
        { "u_ShadowMap3", GLSL_INT },
+       { "u_ShadowMap4", GLSL_INT },
 
        { "u_ShadowMvp",  GLSL_MAT16 },
        { "u_ShadowMvp2", GLSL_MAT16 },
        { "u_ShadowMvp3", GLSL_MAT16 },
+       { "u_ShadowMvp4", GLSL_MAT16 },
 
        { "u_EnableTextures", GLSL_VEC4 },
 
@@ -1308,7 +1310,8 @@ void GLSL_InitGPUShaders(void)
        if (r_shadowFilter->integer >= 2)
                Q_strcat(extradefines, 1024, "#define USE_SHADOW_FILTER2\n");
 
-       Q_strcat(extradefines, 1024, "#define USE_SHADOW_CASCADE\n");
+       if (r_shadowCascadeZFar->integer != 0)
+               Q_strcat(extradefines, 1024, "#define USE_SHADOW_CASCADE\n");
 
        Q_strcat(extradefines, 1024, va("#define r_shadowMapSize %d\n", 
r_shadowMapSize->integer));
        Q_strcat(extradefines, 1024, va("#define r_shadowCascadeZFar %f\n", 
r_shadowCascadeZFar->value));
@@ -1326,6 +1329,7 @@ void GLSL_InitGPUShaders(void)
        GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP,  
TB_SHADOWMAP);
        GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP2, 
TB_SHADOWMAP2);
        GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP3, 
TB_SHADOWMAP3);
+       GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP4, 
TB_SHADOWMAP4);
        qglUseProgramObjectARB(0);
 
        GLSL_FinishGPUShader(&tr.shadowmaskShader);
diff --git a/MP/code/rend2/tr_image.c b/MP/code/rend2/tr_image.c
index b04226c..1eb06bc 100644
--- a/MP/code/rend2/tr_image.c
+++ b/MP/code/rend2/tr_image.c
@@ -3168,9 +3168,14 @@ void R_CreateBuiltinImages( void ) {
 
                if (r_sunlightMode->integer)
                {
-                       for ( x = 0; x < 3; x++)
+                       for ( x = 0; x < 4; x++)
                        {
                                tr.sunShadowDepthImage[x] = 
R_CreateImage(va("*sunshadowdepth%i", x), NULL, r_shadowMapSize->integer, 
r_shadowMapSize->integer, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | 
IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB);
+                               GL_Bind(tr.sunShadowDepthImage[x]);
+                               qglTexParameterf(GL_TEXTURE_2D, 
GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+                               qglTexParameterf(GL_TEXTURE_2D, 
GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+                               qglTexParameterf(GL_TEXTURE_2D, 
GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+                               qglTexParameterf(GL_TEXTURE_2D, 
GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
                        }
 
                        tr.screenShadowImage = R_CreateImage("*screenShadow", 
NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | 
IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
diff --git a/MP/code/rend2/tr_init.c b/MP/code/rend2/tr_init.c
index 2500e56..b4c2670 100644
--- a/MP/code/rend2/tr_init.c
+++ b/MP/code/rend2/tr_init.c
@@ -1340,9 +1340,9 @@ void R_Register( void ) {
        r_sunShadows = ri.Cvar_Get( "r_sunShadows", "1", CVAR_ARCHIVE | 
CVAR_LATCH );
        r_shadowFilter = ri.Cvar_Get( "r_shadowFilter", "1", CVAR_ARCHIVE | 
CVAR_LATCH );
        r_shadowMapSize = ri.Cvar_Get( "r_shadowMapSize", "1024", CVAR_ARCHIVE 
| CVAR_LATCH );
-       r_shadowCascadeZNear = ri.Cvar_Get( "r_shadowCascadeZNear", "4", 
CVAR_ARCHIVE | CVAR_LATCH );
-       r_shadowCascadeZFar = ri.Cvar_Get( "r_shadowCascadeZFar", "3072", 
CVAR_ARCHIVE | CVAR_LATCH );
-       r_shadowCascadeZBias = ri.Cvar_Get( "r_shadowCascadeZBias", "-320", 
CVAR_ARCHIVE | CVAR_LATCH );
+       r_shadowCascadeZNear = ri.Cvar_Get( "r_shadowCascadeZNear", "8", 
CVAR_ARCHIVE | CVAR_LATCH );
+       r_shadowCascadeZFar = ri.Cvar_Get( "r_shadowCascadeZFar", "1024", 
CVAR_ARCHIVE | CVAR_LATCH );
+       r_shadowCascadeZBias = ri.Cvar_Get( "r_shadowCascadeZBias", "0", 
CVAR_ARCHIVE | CVAR_LATCH );
        r_ignoreDstAlpha = ri.Cvar_Get( "r_ignoreDstAlpha", "1", CVAR_ARCHIVE | 
CVAR_LATCH );
 
        //
diff --git a/MP/code/rend2/tr_local.h b/MP/code/rend2/tr_local.h
index ce82ea3..6b3cf59 100644
--- a/MP/code/rend2/tr_local.h
+++ b/MP/code/rend2/tr_local.h
@@ -406,6 +406,7 @@ enum
        TB_SPECULARMAP = 4,
        TB_SHADOWMAP  = 5,
        TB_CUBEMAP     = 6,
+       TB_SHADOWMAP4  = 6,
        NUM_TEXTURE_BUNDLES = 7
 };
 
@@ -718,10 +719,12 @@ typedef enum
        UNIFORM_SHADOWMAP,
        UNIFORM_SHADOWMAP2,
        UNIFORM_SHADOWMAP3,
+       UNIFORM_SHADOWMAP4,
 
        UNIFORM_SHADOWMVP,
        UNIFORM_SHADOWMVP2,
        UNIFORM_SHADOWMVP3,
+       UNIFORM_SHADOWMVP4,
 
        UNIFORM_ENABLETEXTURES,
 
@@ -849,7 +852,7 @@ typedef struct {
        int         num_pshadows;
        struct pshadow_s *pshadows;
 
-       float       sunShadowMvp[3][16];
+       float       sunShadowMvp[4][16];
        float       sunDir[4];
        float       sunCol[4];
        float       sunAmbCol[4];
@@ -1659,7 +1662,7 @@ typedef struct {
        image_t                                 *calcLevelsImage;
        image_t                                 *targetLevelsImage;
        image_t                                 *fixedLevelsImage;
-       image_t                                 *sunShadowDepthImage[3];
+       image_t                                 *sunShadowDepthImage[4];
        image_t                 *screenShadowImage;
        image_t                 *screenSsaoImage;
        image_t                                 *hdrDepthImage;
@@ -1676,7 +1679,7 @@ typedef struct {
        FBO_t                   *quarterFbo[2];
        FBO_t                                   *calcLevelsFbo;
        FBO_t                                   *targetLevelsFbo;
-       FBO_t                                   *sunShadowFbo[3];
+       FBO_t                                   *sunShadowFbo[4];
        FBO_t                                   *screenShadowFbo;
        FBO_t                                   *screenSsaoFbo;
        FBO_t                                   *hdrDepthFbo;
@@ -1752,6 +1755,8 @@ typedef struct {
 
        vec3_t sunLight;                            // from the sky shader for 
this level
        vec3_t sunDirection;
+       vec3_t                  lastCascadeSunDirection;
+       float                   lastCascadeSunMvp[16];
 
 //----(SA)     added
        float lightGridMulAmbient;          // lightgrid multipliers specified 
in sky shader
diff --git a/MP/code/rend2/tr_main.c b/MP/code/rend2/tr_main.c
index 881c031..2c6798d 100644
--- a/MP/code/rend2/tr_main.c
+++ b/MP/code/rend2/tr_main.c
@@ -2853,13 +2853,15 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int 
level)
                        break;
        }
                        
-       VectorCopy(fd->vieworg, lightOrigin);
-
+       if (level != 3)
+               VectorCopy(fd->vieworg, lightOrigin);
+       else
+               VectorCopy(tr.world->lightGridOrigin, lightOrigin);
 
        // Make up a projection
        VectorScale(lightDir, -1.0f, lightViewAxis[0]);
 
-       if (lightViewIndependentOfCameraView)
+       if (level == 3 || lightViewIndependentOfCameraView)
        {
                // Use world up as light view up
                VectorSet(lightViewAxis[2], 0, 0, 1);
@@ -2879,7 +2881,7 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level)
        // Check if too close to parallel to light direction
        if (abs(DotProduct(lightViewAxis[2], lightViewAxis[0])) > 0.9f)
        {
-               if (lightViewIndependentOfCameraView)
+               if (level == 3 || lightViewIndependentOfCameraView)
                {
                        // Use world left as light view up
                        VectorSet(lightViewAxis[2], 0, 1, 0);
@@ -2916,56 +2918,116 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int 
level)
 
                ClearBounds(lightviewBounds[0], lightviewBounds[1]);
 
-               // add view near plane
-               lx = splitZNear * tan(fd->fov_x * M_PI / 360.0f);
-               ly = splitZNear * tan(fd->fov_y * M_PI / 360.0f);
-               VectorMA(fd->vieworg, splitZNear, fd->viewaxis[0], base);
-
-               VectorMA(base,   lx, fd->viewaxis[1], point);
-               VectorMA(point,  ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
-
-               VectorMA(base,  -lx, fd->viewaxis[1], point);
-               VectorMA(point,  ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
-
-               VectorMA(base,   lx, fd->viewaxis[1], point);
-               VectorMA(point, -ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
-
-               VectorMA(base,  -lx, fd->viewaxis[1], point);
-               VectorMA(point, -ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
-               
-
-               // add view far plane
-               lx = splitZFar * tan(fd->fov_x * M_PI / 360.0f);
-               ly = splitZFar * tan(fd->fov_y * M_PI / 360.0f);
-               VectorMA(fd->vieworg, splitZFar, fd->viewaxis[0], base);
-
-               VectorMA(base,   lx, fd->viewaxis[1], point);
-               VectorMA(point,  ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
-
-               VectorMA(base,  -lx, fd->viewaxis[1], point);
-               VectorMA(point,  ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
-
-               VectorMA(base,   lx, fd->viewaxis[1], point);
-               VectorMA(point, -ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
-
-               VectorMA(base,  -lx, fd->viewaxis[1], point);
-               VectorMA(point, -ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+               if (level != 3)
+               {
+                       // add view near plane
+                       lx = splitZNear * tan(fd->fov_x * M_PI / 360.0f);
+                       ly = splitZNear * tan(fd->fov_y * M_PI / 360.0f);
+                       VectorMA(fd->vieworg, splitZNear, fd->viewaxis[0], 
base);
+
+                       VectorMA(base,   lx, fd->viewaxis[1], point);
+                       VectorMA(point,  ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       VectorMA(base,  -lx, fd->viewaxis[1], point);
+                       VectorMA(point,  ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       VectorMA(base,   lx, fd->viewaxis[1], point);
+                       VectorMA(point, -ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       VectorMA(base,  -lx, fd->viewaxis[1], point);
+                       VectorMA(point, -ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+ 
+                       // add view far plane
+                       lx = splitZFar * tan(fd->fov_x * M_PI / 360.0f);
+                       ly = splitZFar * tan(fd->fov_y * M_PI / 360.0f);
+                       VectorMA(fd->vieworg, splitZFar, fd->viewaxis[0], base);
+
+                       VectorMA(base,   lx, fd->viewaxis[1], point);
+                       VectorMA(point,  ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       VectorMA(base,  -lx, fd->viewaxis[1], point);
+                       VectorMA(point,  ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       VectorMA(base,   lx, fd->viewaxis[1], point);
+                       VectorMA(point, -ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       VectorMA(base,  -lx, fd->viewaxis[1], point);
+                       VectorMA(point, -ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+               }
+               else
+               {
+                       // use light grid size as level size
+                       // FIXME: could be tighter
+                       vec3_t bounds;
+
+                       bounds[0] = tr.world->lightGridSize[0] * 
tr.world->lightGridBounds[0];
+                       bounds[1] = tr.world->lightGridSize[1] * 
tr.world->lightGridBounds[1];
+                       bounds[2] = tr.world->lightGridSize[2] * 
tr.world->lightGridBounds[2];
+
+                       point[0] = tr.world->lightGridOrigin[0];
+                       point[1] = tr.world->lightGridOrigin[1];
+                       point[2] = tr.world->lightGridOrigin[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       point[0] = tr.world->lightGridOrigin[0] + bounds[0];
+                       point[1] = tr.world->lightGridOrigin[1];
+                       point[2] = tr.world->lightGridOrigin[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       point[0] = tr.world->lightGridOrigin[0];
+                       point[1] = tr.world->lightGridOrigin[1] + bounds[1];
+                       point[2] = tr.world->lightGridOrigin[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       point[0] = tr.world->lightGridOrigin[0] + bounds[0];
+                       point[1] = tr.world->lightGridOrigin[1] + bounds[1];
+                       point[2] = tr.world->lightGridOrigin[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       point[0] = tr.world->lightGridOrigin[0];
+                       point[1] = tr.world->lightGridOrigin[1];
+                       point[2] = tr.world->lightGridOrigin[2] + bounds[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       point[0] = tr.world->lightGridOrigin[0] + bounds[0];
+                       point[1] = tr.world->lightGridOrigin[1];
+                       point[2] = tr.world->lightGridOrigin[2] + bounds[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       point[0] = tr.world->lightGridOrigin[0];
+                       point[1] = tr.world->lightGridOrigin[1] + bounds[1];
+                       point[2] = tr.world->lightGridOrigin[2] + bounds[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       point[0] = tr.world->lightGridOrigin[0] + bounds[0];
+                       point[1] = tr.world->lightGridOrigin[1] + bounds[1];
+                       point[2] = tr.world->lightGridOrigin[2] + bounds[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+               }
 
                if (!glRefConfig.depthClamp)
                        lightviewBounds[0][0] = lightviewBounds[1][0] - 8192;
@@ -2995,8 +3057,8 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level)
                        VectorScale(lightviewBounds[1], worldUnitsPerTexel, 
lightviewBounds[1]);
                }
 
-               //ri.Printf(PRINT_ALL, "znear %f zfar %f\n", 
lightviewBounds[0][0], lightviewBounds[1][0]);             
-               //ri.Printf(PRINT_ALL, "fovx %f fovy %f xmin %f xmax %f ymin %f 
ymax %f\n", fd->fov_x, fd->fov_y, xmin, xmax, ymin, ymax);
+               //ri.Printf(PRINT_ALL, "level %d znear %f zfar %f\n", level, 
lightviewBounds[0][0], lightviewBounds[1][0]);
+               //ri.Printf(PRINT_ALL, "xmin %f xmax %f ymin %f ymax %f\n", 
lightviewBounds[0][1], lightviewBounds[1][1], -lightviewBounds[1][2], 
-lightviewBounds[0][2]);
        }
 
 
@@ -3137,6 +3199,7 @@ void R_RenderCubemapSide( int cubemapIndex, int 
cubemapSide, qboolean subscene )
                        R_RenderSunShadowMaps(&refdef, 0);
                        R_RenderSunShadowMaps(&refdef, 1);
                        R_RenderSunShadowMaps(&refdef, 2);
+                       R_RenderSunShadowMaps(&refdef, 3);
                }
        }
 
diff --git a/MP/code/rend2/tr_scene.c b/MP/code/rend2/tr_scene.c
index 8d87c8d..68cd57c 100644
--- a/MP/code/rend2/tr_scene.c
+++ b/MP/code/rend2/tr_scene.c
@@ -616,9 +616,30 @@ void RE_RenderScene( const refdef_t *fd ) {
        // playing with even more shadows
        if(glRefConfig.framebufferObject && r_sunlightMode->integer && !( 
fd->rdflags & RDF_NOWORLDMODEL ) && (r_forceSun->integer || tr.sunShadows))
        {
-               R_RenderSunShadowMaps(fd, 0);
-               R_RenderSunShadowMaps(fd, 1);
-               R_RenderSunShadowMaps(fd, 2);
+               if (r_shadowCascadeZFar != 0)
+               {
+                       R_RenderSunShadowMaps(fd, 0);
+                       R_RenderSunShadowMaps(fd, 1);
+                       R_RenderSunShadowMaps(fd, 2);
+               }
+               else
+               {
+                       Mat4Zero(tr.refdef.sunShadowMvp[0]);
+                       Mat4Zero(tr.refdef.sunShadowMvp[1]);
+                       Mat4Zero(tr.refdef.sunShadowMvp[2]);
+               }
+
+               // only rerender last cascade if sun has changed position
+               if (r_forceSun->integer == 2 || 
!VectorCompare(tr.refdef.sunDir, tr.lastCascadeSunDirection))
+               {
+                       VectorCopy(tr.refdef.sunDir, 
tr.lastCascadeSunDirection);
+                       R_RenderSunShadowMaps(fd, 3);
+                       Mat4Copy(tr.refdef.sunShadowMvp[3], 
tr.lastCascadeSunMvp);
+               }
+               else
+               {
+                       Mat4Copy(tr.lastCascadeSunMvp, 
tr.refdef.sunShadowMvp[3]);
+               }
        }
 
        // playing with cube maps
diff --git a/SP/code/rend2/glsl/shadowmask_fp.glsl 
b/SP/code/rend2/glsl/shadowmask_fp.glsl
index b489fef..8a5597a 100644
--- a/SP/code/rend2/glsl/shadowmask_fp.glsl
+++ b/SP/code/rend2/glsl/shadowmask_fp.glsl
@@ -1,15 +1,17 @@
 uniform sampler2D u_ScreenDepthMap;
 
-uniform sampler2D u_ShadowMap;
+uniform sampler2DShadow u_ShadowMap;
 #if defined(USE_SHADOW_CASCADE)
-uniform sampler2D u_ShadowMap2;
-uniform sampler2D u_ShadowMap3;
+uniform sampler2DShadow u_ShadowMap2;
+uniform sampler2DShadow u_ShadowMap3;
+uniform sampler2DShadow u_ShadowMap4;
 #endif
 
 uniform mat4      u_ShadowMvp;
 #if defined(USE_SHADOW_CASCADE)
 uniform mat4      u_ShadowMvp2;
 uniform mat4      u_ShadowMvp3;
+uniform mat4      u_ShadowMvp4;
 #endif
 
 uniform vec3   u_ViewOrigin;
@@ -39,94 +41,103 @@ float random( const vec2 p )
   return mod( 123456789., 1e-7 + 256. * dot(p,r) );  
 }
 
-float PCF(const sampler2D shadowmap, const vec2 st, const float dist)
+float PCF(const sampler2DShadow shadowmap, const vec2 st, const float dist)
 {
        float mult;
        float scale = 2.0 / r_shadowMapSize;
 
+#if 0
+       // from http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
+       vec2 offset = vec2(greaterThan(fract(var_DepthTex.xy * r_FBufScale * 
0.5), vec2(0.25)));
+       offset.y += offset.x;
+       if (offset.y > 1.1) offset.y = 0.0;
+       
+       mult = shadow2D(shadowmap, vec3(st + (offset + vec2(-1.5,  0.5)) * 
scale, dist)).r
+            + shadow2D(shadowmap, vec3(st + (offset + vec2( 0.5,  0.5)) * 
scale, dist)).r
+            + shadow2D(shadowmap, vec3(st + (offset + vec2(-1.5, -1.5)) * 
scale, dist)).r
+            + shadow2D(shadowmap, vec3(st + (offset + vec2( 0.5, -1.5)) * 
scale, dist)).r;
+        
+       mult *= 0.25;
+#endif
+
 #if defined(USE_SHADOW_FILTER)
        float r = random(var_DepthTex.xy);
        float sinr = sin(r) * scale;
        float cosr = cos(r) * scale;
        mat2 rmat = mat2(cosr, sinr, -sinr, cosr);
 
-       mult =  step(dist, texture2D(shadowmap, st + rmat * vec2(-0.7055767, 
0.196515)).r);
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.3524343, 
-0.7791386)).r);
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.2391056, 
0.9189604)).r);
+       mult =  shadow2D(shadowmap, vec3(st + rmat * vec2(-0.7055767, 
0.196515), dist)).r;
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.3524343, 
-0.7791386), dist)).r;
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.2391056, 
0.9189604), dist)).r;
   #if defined(USE_SHADOW_FILTER2)
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(-0.07580382, 
-0.09224417)).r);
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.5784913, 
-0.002528916)).r);
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.192888, 
0.4064181)).r);
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(-0.6335801, 
-0.5247476)).r);
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(-0.5579782, 
0.7491854)).r);
-       mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.7320465, 
0.6317794)).r);
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(-0.07580382, 
-0.09224417), dist)).r;
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.5784913, 
-0.002528916), dist)).r;
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.192888, 0.4064181), 
dist)).r;
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(-0.6335801, 
-0.5247476), dist)).r;
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(-0.5579782, 
0.7491854), dist)).r;
+       mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.7320465, 
0.6317794), dist)).r;
 
        mult *= 0.11111;
   #else
     mult *= 0.33333;
   #endif
 #else
-       mult = step(dist, texture2D(shadowmap, st).r);
+       mult = shadow2D(shadowmap, vec3(st, dist));
 #endif
-               
+
        return mult;
 }
 
 float getLinearDepth(sampler2D depthMap, vec2 tex, float zFarDivZNear)
 {
-               float sampleZDivW = texture2D(depthMap, tex).r;
-               sampleZDivW -= DEPTH_MAX_ERROR;
-               return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW);
+       float sampleZDivW = texture2D(depthMap, tex).r - DEPTH_MAX_ERROR;
+       return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW);
 }
 
 void main()
 {
        float result;
-       
-       float depth = getLinearDepth(u_ScreenDepthMap, var_DepthTex, 
u_ViewInfo.x);
-       float sampleZ = u_ViewInfo.y * depth;
 
+       float depth = getLinearDepth(u_ScreenDepthMap, var_DepthTex, 
u_ViewInfo.x);
        vec4 biasPos = vec4(u_ViewOrigin + var_ViewDir * (depth - 0.5 / 
u_ViewInfo.x), 1.0);
-       
+
        vec4 shadowpos = u_ShadowMvp * biasPos;
-       
-#if defined(USE_SHADOW_CASCADE)
-       const float fadeTo = 1.0;
-       result = fadeTo;
-#else
-       result = 0.0;
-#endif
 
-       if (all(lessThanEqual(abs(shadowpos.xyz), vec3(abs(shadowpos.w)))))
+#if defined(USE_SHADOW_CASCADE)
+       if (all(lessThan(abs(shadowpos.xyz), vec3(abs(shadowpos.w)))))
        {
-               shadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5;
+#endif
+               shadowpos.xyz = shadowpos.xyz * (0.5 / shadowpos.w) + vec3(0.5);
                result = PCF(u_ShadowMap, shadowpos.xy, shadowpos.z);
-       }
 #if defined(USE_SHADOW_CASCADE)
+       }
        else
        {
                shadowpos = u_ShadowMvp2 * biasPos;
 
-               if (all(lessThanEqual(abs(shadowpos.xyz), 
vec3(abs(shadowpos.w)))))
+               if (all(lessThan(abs(shadowpos.xyz), vec3(abs(shadowpos.w)))))
                {
-                       shadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5;
+                       shadowpos.xyz = shadowpos.xyz * (0.5 / shadowpos.w) + 
vec3(0.5);
                        result = PCF(u_ShadowMap2, shadowpos.xy, shadowpos.z);
                }
                else
                {
                        shadowpos = u_ShadowMvp3 * biasPos;
 
-                       if (all(lessThanEqual(abs(shadowpos.xyz), 
vec3(abs(shadowpos.w)))))
+                       if (all(lessThan(abs(shadowpos.xyz), 
vec3(abs(shadowpos.w)))))
                        {
-                               shadowpos.xyz = shadowpos.xyz / shadowpos.w * 
0.5 + 0.5;
+                               shadowpos.xyz = shadowpos.xyz * (0.5 / 
shadowpos.w) + vec3(0.5);
                                result = PCF(u_ShadowMap3, shadowpos.xy, 
shadowpos.z);
-
-                               float fade = clamp(sampleZ / 
r_shadowCascadeZFar * 10.0 - 9.0, 0.0, 1.0);
-                               result = mix(result, fadeTo, fade);
+                       }
+                       else
+                       {
+                               shadowpos = u_ShadowMvp4 * biasPos;
+                               shadowpos.xyz = shadowpos.xyz * (0.5 / 
shadowpos.w) + vec3(0.5);
+                               result = PCF(u_ShadowMap4, shadowpos.xy, 
shadowpos.z);
                        }
                }
        }
 #endif
-               
+
        gl_FragColor = vec4(vec3(result), 1.0);
 }
diff --git a/SP/code/rend2/tr_backend.c b/SP/code/rend2/tr_backend.c
index b038784..3fcb7d9 100644
--- a/SP/code/rend2/tr_backend.c
+++ b/SP/code/rend2/tr_backend.c
@@ -1617,13 +1617,24 @@ const void  *RB_DrawSurfs( const void *data ) {
                        GLSL_BindProgram(&tr.shadowmaskShader);
 
                        GL_BindToTMU(tr.renderDepthImage, TB_COLORMAP);
-                       GL_BindToTMU(tr.sunShadowDepthImage[0], TB_SHADOWMAP);
-                       GL_BindToTMU(tr.sunShadowDepthImage[1], TB_SHADOWMAP2);
-                       GL_BindToTMU(tr.sunShadowDepthImage[2], TB_SHADOWMAP3);
 
-                       GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP,  backEnd.refdef.sunShadowMvp[0]);
-                       GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP2, backEnd.refdef.sunShadowMvp[1]);
-                       GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP3, backEnd.refdef.sunShadowMvp[2]);
+                       if (r_shadowCascadeZFar->integer != 0)
+                       {
+                               GL_BindToTMU(tr.sunShadowDepthImage[0], 
TB_SHADOWMAP);
+                               GL_BindToTMU(tr.sunShadowDepthImage[1], 
TB_SHADOWMAP2);
+                               GL_BindToTMU(tr.sunShadowDepthImage[2], 
TB_SHADOWMAP3);
+                               GL_BindToTMU(tr.sunShadowDepthImage[3], 
TB_SHADOWMAP4);
+
+                               GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP,  backEnd.refdef.sunShadowMvp[0]);
+                               GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP2, backEnd.refdef.sunShadowMvp[1]);
+                               GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP3, backEnd.refdef.sunShadowMvp[2]);
+                               GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP4, backEnd.refdef.sunShadowMvp[3]);
+                       }
+                       else
+                       {
+                               GL_BindToTMU(tr.sunShadowDepthImage[3], 
TB_SHADOWMAP);
+                               GLSL_SetUniformMat4(&tr.shadowmaskShader, 
UNIFORM_SHADOWMVP, backEnd.refdef.sunShadowMvp[3]);
+                       }
                        
                        GLSL_SetUniformVec3(&tr.shadowmaskShader, 
UNIFORM_VIEWORIGIN,  backEnd.refdef.vieworg);
                        {
@@ -2177,6 +2188,8 @@ const void *RB_PostProcess(const void *data)
                FBO_BlitFromTexture(tr.sunShadowDepthImage[1], NULL, NULL, 
NULL, dstBox, NULL, NULL, 0);
                VectorSet4(dstBox, 256, 0, 128, 128);
                FBO_BlitFromTexture(tr.sunShadowDepthImage[2], NULL, NULL, 
NULL, dstBox, NULL, NULL, 0);
+               VectorSet4(dstBox, 384, 0, 128, 128);
+               FBO_BlitFromTexture(tr.sunShadowDepthImage[3], NULL, NULL, 
NULL, dstBox, NULL, NULL, 0);
        }
 
        if (0)
diff --git a/SP/code/rend2/tr_bsp.c b/SP/code/rend2/tr_bsp.c
index 3dde8f9..76e8731 100644
--- a/SP/code/rend2/tr_bsp.c
+++ b/SP/code/rend2/tr_bsp.c
@@ -3666,6 +3666,9 @@ void RE_LoadWorldMap( const char *name ) {
        tr.toneMinAvgMaxLevel[1] = -2.0f;
        tr.toneMinAvgMaxLevel[2] = 0.0f;
 
+       // reset last cascade sun direction so last shadow cascade is rerendered
+       VectorClear(tr.lastCascadeSunDirection);
+
        tr.worldMapLoaded = qtrue;
 
        // load it
diff --git a/SP/code/rend2/tr_fbo.c b/SP/code/rend2/tr_fbo.c
index c642b73..4070c6e 100644
--- a/SP/code/rend2/tr_fbo.c
+++ b/SP/code/rend2/tr_fbo.c
@@ -484,7 +484,7 @@ void FBO_Init(void)
 
        if (tr.sunShadowDepthImage[0])
        {
-               for ( i = 0; i < 3; i++)
+               for ( i = 0; i < 4; i++)
                {
                        tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", 
tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height);
                        FBO_Bind(tr.sunShadowFbo[i]);
diff --git a/SP/code/rend2/tr_glsl.c b/SP/code/rend2/tr_glsl.c
index c304f2b..ba75215 100644
--- a/SP/code/rend2/tr_glsl.c
+++ b/SP/code/rend2/tr_glsl.c
@@ -79,10 +79,12 @@ static uniformInfo_t uniformsInfo[] =
        { "u_ShadowMap",  GLSL_INT },
        { "u_ShadowMap2", GLSL_INT },
        { "u_ShadowMap3", GLSL_INT },
+       { "u_ShadowMap4", GLSL_INT },
 
        { "u_ShadowMvp",  GLSL_MAT16 },
        { "u_ShadowMvp2", GLSL_MAT16 },
        { "u_ShadowMvp3", GLSL_MAT16 },
+       { "u_ShadowMvp4", GLSL_MAT16 },
 
        { "u_EnableTextures", GLSL_VEC4 },
 
@@ -1308,7 +1310,8 @@ void GLSL_InitGPUShaders(void)
        if (r_shadowFilter->integer >= 2)
                Q_strcat(extradefines, 1024, "#define USE_SHADOW_FILTER2\n");
 
-       Q_strcat(extradefines, 1024, "#define USE_SHADOW_CASCADE\n");
+       if (r_shadowCascadeZFar->integer != 0)
+               Q_strcat(extradefines, 1024, "#define USE_SHADOW_CASCADE\n");
 
        Q_strcat(extradefines, 1024, va("#define r_shadowMapSize %d\n", 
r_shadowMapSize->integer));
        Q_strcat(extradefines, 1024, va("#define r_shadowCascadeZFar %f\n", 
r_shadowCascadeZFar->value));
@@ -1326,6 +1329,7 @@ void GLSL_InitGPUShaders(void)
        GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP,  
TB_SHADOWMAP);
        GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP2, 
TB_SHADOWMAP2);
        GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP3, 
TB_SHADOWMAP3);
+       GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP4, 
TB_SHADOWMAP4);
        qglUseProgramObjectARB(0);
 
        GLSL_FinishGPUShader(&tr.shadowmaskShader);
diff --git a/SP/code/rend2/tr_image.c b/SP/code/rend2/tr_image.c
index 33803ca..cf51f5d 100644
--- a/SP/code/rend2/tr_image.c
+++ b/SP/code/rend2/tr_image.c
@@ -3179,9 +3179,14 @@ void R_CreateBuiltinImages( void ) {
 
                if (r_sunlightMode->integer)
                {
-                       for ( x = 0; x < 3; x++)
+                       for ( x = 0; x < 4; x++)
                        {
                                tr.sunShadowDepthImage[x] = 
R_CreateImage(va("*sunshadowdepth%i", x), NULL, r_shadowMapSize->integer, 
r_shadowMapSize->integer, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | 
IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB);
+                               GL_Bind(tr.sunShadowDepthImage[x]);
+                               qglTexParameterf(GL_TEXTURE_2D, 
GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+                               qglTexParameterf(GL_TEXTURE_2D, 
GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+                               qglTexParameterf(GL_TEXTURE_2D, 
GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+                               qglTexParameterf(GL_TEXTURE_2D, 
GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
                        }
 
                        tr.screenShadowImage = R_CreateImage("*screenShadow", 
NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | 
IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
diff --git a/SP/code/rend2/tr_init.c b/SP/code/rend2/tr_init.c
index 7642744..1a52d9c 100644
--- a/SP/code/rend2/tr_init.c
+++ b/SP/code/rend2/tr_init.c
@@ -1364,9 +1364,9 @@ void R_Register( void ) {
        r_sunShadows = ri.Cvar_Get( "r_sunShadows", "1", CVAR_ARCHIVE | 
CVAR_LATCH );
        r_shadowFilter = ri.Cvar_Get( "r_shadowFilter", "1", CVAR_ARCHIVE | 
CVAR_LATCH );
        r_shadowMapSize = ri.Cvar_Get( "r_shadowMapSize", "1024", CVAR_ARCHIVE 
| CVAR_LATCH );
-       r_shadowCascadeZNear = ri.Cvar_Get( "r_shadowCascadeZNear", "4", 
CVAR_ARCHIVE | CVAR_LATCH );
-       r_shadowCascadeZFar = ri.Cvar_Get( "r_shadowCascadeZFar", "3072", 
CVAR_ARCHIVE | CVAR_LATCH );
-       r_shadowCascadeZBias = ri.Cvar_Get( "r_shadowCascadeZBias", "-320", 
CVAR_ARCHIVE | CVAR_LATCH );
+       r_shadowCascadeZNear = ri.Cvar_Get( "r_shadowCascadeZNear", "8", 
CVAR_ARCHIVE | CVAR_LATCH );
+       r_shadowCascadeZFar = ri.Cvar_Get( "r_shadowCascadeZFar", "1024", 
CVAR_ARCHIVE | CVAR_LATCH );
+       r_shadowCascadeZBias = ri.Cvar_Get( "r_shadowCascadeZBias", "0", 
CVAR_ARCHIVE | CVAR_LATCH );
        r_ignoreDstAlpha = ri.Cvar_Get( "r_ignoreDstAlpha", "1", CVAR_ARCHIVE | 
CVAR_LATCH );
 
        //
diff --git a/SP/code/rend2/tr_local.h b/SP/code/rend2/tr_local.h
index e6be278..1bf8958 100644
--- a/SP/code/rend2/tr_local.h
+++ b/SP/code/rend2/tr_local.h
@@ -408,6 +408,7 @@ enum
        TB_SPECULARMAP = 4,
        TB_SHADOWMAP  = 5,
        TB_CUBEMAP     = 6,
+       TB_SHADOWMAP4  = 6,
        NUM_TEXTURE_BUNDLES = 7
 };
 
@@ -723,10 +724,12 @@ typedef enum
        UNIFORM_SHADOWMAP,
        UNIFORM_SHADOWMAP2,
        UNIFORM_SHADOWMAP3,
+       UNIFORM_SHADOWMAP4,
 
        UNIFORM_SHADOWMVP,
        UNIFORM_SHADOWMVP2,
        UNIFORM_SHADOWMVP3,
+       UNIFORM_SHADOWMVP4,
 
        UNIFORM_ENABLETEXTURES,
 
@@ -853,7 +856,7 @@ typedef struct {
        int         num_pshadows;
        struct pshadow_s *pshadows;
 
-       float       sunShadowMvp[3][16];
+       float       sunShadowMvp[4][16];
        float       sunDir[4];
        float       sunCol[4];
        float       sunAmbCol[4];
@@ -1672,7 +1675,7 @@ typedef struct {
        image_t                                 *calcLevelsImage;
        image_t                                 *targetLevelsImage;
        image_t                                 *fixedLevelsImage;
-       image_t                                 *sunShadowDepthImage[3];
+       image_t                                 *sunShadowDepthImage[4];
        image_t                 *screenShadowImage;
        image_t                 *screenSsaoImage;
        image_t                                 *hdrDepthImage;
@@ -1689,7 +1692,7 @@ typedef struct {
        FBO_t                   *quarterFbo[2];
        FBO_t                                   *calcLevelsFbo;
        FBO_t                                   *targetLevelsFbo;
-       FBO_t                                   *sunShadowFbo[3];
+       FBO_t                                   *sunShadowFbo[4];
        FBO_t                                   *screenShadowFbo;
        FBO_t                                   *screenSsaoFbo;
        FBO_t                                   *hdrDepthFbo;
@@ -1766,6 +1769,8 @@ typedef struct {
 
        vec3_t sunLight;                            // from the sky shader for 
this level
        vec3_t sunDirection;
+       vec3_t                  lastCascadeSunDirection;
+       float                   lastCascadeSunMvp[16];
 
 //----(SA)     added
        float lightGridMulAmbient;          // lightgrid multipliers specified 
in sky shader
diff --git a/SP/code/rend2/tr_main.c b/SP/code/rend2/tr_main.c
index 815dad1..fcc9db9 100644
--- a/SP/code/rend2/tr_main.c
+++ b/SP/code/rend2/tr_main.c
@@ -2901,13 +2901,15 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int 
level)
                        break;
        }
                        
-       VectorCopy(fd->vieworg, lightOrigin);
-
+       if (level != 3)
+               VectorCopy(fd->vieworg, lightOrigin);
+       else
+               VectorCopy(tr.world->lightGridOrigin, lightOrigin);
 
        // Make up a projection
        VectorScale(lightDir, -1.0f, lightViewAxis[0]);
 
-       if (lightViewIndependentOfCameraView)
+       if (level == 3 || lightViewIndependentOfCameraView)
        {
                // Use world up as light view up
                VectorSet(lightViewAxis[2], 0, 0, 1);
@@ -2927,7 +2929,7 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level)
        // Check if too close to parallel to light direction
        if (abs(DotProduct(lightViewAxis[2], lightViewAxis[0])) > 0.9f)
        {
-               if (lightViewIndependentOfCameraView)
+               if (level == 3 || lightViewIndependentOfCameraView)
                {
                        // Use world left as light view up
                        VectorSet(lightViewAxis[2], 0, 1, 0);
@@ -2964,56 +2966,116 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int 
level)
 
                ClearBounds(lightviewBounds[0], lightviewBounds[1]);
 
-               // add view near plane
-               lx = splitZNear * tan(fd->fov_x * M_PI / 360.0f);
-               ly = splitZNear * tan(fd->fov_y * M_PI / 360.0f);
-               VectorMA(fd->vieworg, splitZNear, fd->viewaxis[0], base);
-
-               VectorMA(base,   lx, fd->viewaxis[1], point);
-               VectorMA(point,  ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
-
-               VectorMA(base,  -lx, fd->viewaxis[1], point);
-               VectorMA(point,  ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
-
-               VectorMA(base,   lx, fd->viewaxis[1], point);
-               VectorMA(point, -ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
-
-               VectorMA(base,  -lx, fd->viewaxis[1], point);
-               VectorMA(point, -ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
-               
-
-               // add view far plane
-               lx = splitZFar * tan(fd->fov_x * M_PI / 360.0f);
-               ly = splitZFar * tan(fd->fov_y * M_PI / 360.0f);
-               VectorMA(fd->vieworg, splitZFar, fd->viewaxis[0], base);
-
-               VectorMA(base,   lx, fd->viewaxis[1], point);
-               VectorMA(point,  ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
-
-               VectorMA(base,  -lx, fd->viewaxis[1], point);
-               VectorMA(point,  ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
-
-               VectorMA(base,   lx, fd->viewaxis[1], point);
-               VectorMA(point, -ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
-
-               VectorMA(base,  -lx, fd->viewaxis[1], point);
-               VectorMA(point, -ly, fd->viewaxis[2], point);
-               Mat4Transform(lightViewMatrix, point, lightViewPoint);
-               AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+               if (level != 3)
+               {
+                       // add view near plane
+                       lx = splitZNear * tan(fd->fov_x * M_PI / 360.0f);
+                       ly = splitZNear * tan(fd->fov_y * M_PI / 360.0f);
+                       VectorMA(fd->vieworg, splitZNear, fd->viewaxis[0], 
base);
+
+                       VectorMA(base,   lx, fd->viewaxis[1], point);
+                       VectorMA(point,  ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       VectorMA(base,  -lx, fd->viewaxis[1], point);
+                       VectorMA(point,  ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       VectorMA(base,   lx, fd->viewaxis[1], point);
+                       VectorMA(point, -ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       VectorMA(base,  -lx, fd->viewaxis[1], point);
+                       VectorMA(point, -ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+                       
+                       // add view far plane
+                       lx = splitZFar * tan(fd->fov_x * M_PI / 360.0f);
+                       ly = splitZFar * tan(fd->fov_y * M_PI / 360.0f);
+                       VectorMA(fd->vieworg, splitZFar, fd->viewaxis[0], base);
+
+                       VectorMA(base,   lx, fd->viewaxis[1], point);
+                       VectorMA(point,  ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       VectorMA(base,  -lx, fd->viewaxis[1], point);
+                       VectorMA(point,  ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       VectorMA(base,   lx, fd->viewaxis[1], point);
+                       VectorMA(point, -ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       VectorMA(base,  -lx, fd->viewaxis[1], point);
+                       VectorMA(point, -ly, fd->viewaxis[2], point);
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+               }
+               else
+               {
+                       // use light grid size as level size
+                       // FIXME: could be tighter
+                       vec3_t bounds;
+
+                       bounds[0] = tr.world->lightGridSize[0] * 
tr.world->lightGridBounds[0];
+                       bounds[1] = tr.world->lightGridSize[1] * 
tr.world->lightGridBounds[1];
+                       bounds[2] = tr.world->lightGridSize[2] * 
tr.world->lightGridBounds[2];
+
+                       point[0] = tr.world->lightGridOrigin[0];
+                       point[1] = tr.world->lightGridOrigin[1];
+                       point[2] = tr.world->lightGridOrigin[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       point[0] = tr.world->lightGridOrigin[0] + bounds[0];
+                       point[1] = tr.world->lightGridOrigin[1];
+                       point[2] = tr.world->lightGridOrigin[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       point[0] = tr.world->lightGridOrigin[0];
+                       point[1] = tr.world->lightGridOrigin[1] + bounds[1];
+                       point[2] = tr.world->lightGridOrigin[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       point[0] = tr.world->lightGridOrigin[0] + bounds[0];
+                       point[1] = tr.world->lightGridOrigin[1] + bounds[1];
+                       point[2] = tr.world->lightGridOrigin[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       point[0] = tr.world->lightGridOrigin[0];
+                       point[1] = tr.world->lightGridOrigin[1];
+                       point[2] = tr.world->lightGridOrigin[2] + bounds[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       point[0] = tr.world->lightGridOrigin[0] + bounds[0];
+                       point[1] = tr.world->lightGridOrigin[1];
+                       point[2] = tr.world->lightGridOrigin[2] + bounds[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       point[0] = tr.world->lightGridOrigin[0];
+                       point[1] = tr.world->lightGridOrigin[1] + bounds[1];
+                       point[2] = tr.world->lightGridOrigin[2] + bounds[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+
+                       point[0] = tr.world->lightGridOrigin[0] + bounds[0];
+                       point[1] = tr.world->lightGridOrigin[1] + bounds[1];
+                       point[2] = tr.world->lightGridOrigin[2] + bounds[2];
+                       Mat4Transform(lightViewMatrix, point, lightViewPoint);
+                       AddPointToBounds(lightViewPoint, lightviewBounds[0], 
lightviewBounds[1]);
+               }
 
                if (!glRefConfig.depthClamp)
                        lightviewBounds[0][0] = lightviewBounds[1][0] - 8192;
@@ -3043,8 +3105,8 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level)
                        VectorScale(lightviewBounds[1], worldUnitsPerTexel, 
lightviewBounds[1]);
                }
 
-               //ri.Printf(PRINT_ALL, "znear %f zfar %f\n", 
lightviewBounds[0][0], lightviewBounds[1][0]);             
-               //ri.Printf(PRINT_ALL, "fovx %f fovy %f xmin %f xmax %f ymin %f 
ymax %f\n", fd->fov_x, fd->fov_y, xmin, xmax, ymin, ymax);
+               //ri.Printf(PRINT_ALL, "level %d znear %f zfar %f\n", level, 
lightviewBounds[0][0], lightviewBounds[1][0]);
+               //ri.Printf(PRINT_ALL, "xmin %f xmax %f ymin %f ymax %f\n", 
lightviewBounds[0][1], lightviewBounds[1][1], -lightviewBounds[1][2], 
-lightviewBounds[0][2]);
        }
 
 
@@ -3185,6 +3247,7 @@ void R_RenderCubemapSide( int cubemapIndex, int 
cubemapSide, qboolean subscene )
                        R_RenderSunShadowMaps(&refdef, 0);
                        R_RenderSunShadowMaps(&refdef, 1);
                        R_RenderSunShadowMaps(&refdef, 2);
+                       R_RenderSunShadowMaps(&refdef, 3);
                }
        }
 
diff --git a/SP/code/rend2/tr_scene.c b/SP/code/rend2/tr_scene.c
index 06e3dc5..72ac184 100644
--- a/SP/code/rend2/tr_scene.c
+++ b/SP/code/rend2/tr_scene.c
@@ -629,9 +629,30 @@ void RE_RenderScene( const refdef_t *fd ) {
        // playing with even more shadows
        if(glRefConfig.framebufferObject && r_sunlightMode->integer && !( 
fd->rdflags & RDF_NOWORLDMODEL ) && (r_forceSun->integer || tr.sunShadows))
        {
-               R_RenderSunShadowMaps(fd, 0);
-               R_RenderSunShadowMaps(fd, 1);
-               R_RenderSunShadowMaps(fd, 2);
+               if (r_shadowCascadeZFar != 0)
+               {
+                       R_RenderSunShadowMaps(fd, 0);
+                       R_RenderSunShadowMaps(fd, 1);
+                       R_RenderSunShadowMaps(fd, 2);
+               }
+               else
+               {
+                       Mat4Zero(tr.refdef.sunShadowMvp[0]);
+                       Mat4Zero(tr.refdef.sunShadowMvp[1]);
+                       Mat4Zero(tr.refdef.sunShadowMvp[2]);
+               }
+
+               // only rerender last cascade if sun has changed position
+               if (r_forceSun->integer == 2 || 
!VectorCompare(tr.refdef.sunDir, tr.lastCascadeSunDirection))
+               {
+                       VectorCopy(tr.refdef.sunDir, 
tr.lastCascadeSunDirection);
+                       R_RenderSunShadowMaps(fd, 3);
+                       Mat4Copy(tr.refdef.sunShadowMvp[3], 
tr.lastCascadeSunMvp);
+               }
+               else
+               {
+                       Mat4Copy(tr.lastCascadeSunMvp, 
tr.refdef.sunShadowMvp[3]);
+               }
        }
 
        // playing with cube maps

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-games/iortcw.git

_______________________________________________
Pkg-games-commits mailing list
Pkg-games-commits@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

Reply via email to