]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rmain.c
try to cache fewer animations for entities when r_shadows is used by using cull box
[xonotic/darkplaces.git] / gl_rmain.c
index d72a3194042eeef3ef743bb9bc33daa4ca5e714e..22c99ef12be07a8a675a41194422d1f1236cd926 100644 (file)
@@ -112,6 +112,12 @@ cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the re
 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
 
+cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
+cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
+cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
+cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
+cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
+
 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
@@ -247,8 +253,6 @@ const float r_screenvertex3f[12] =
        0, 1, 0
 };
 
-extern void R_DrawModelShadows(void);
-
 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
 {
        int i;
@@ -890,6 +894,10 @@ static const char *builtinshaderstring =
 "#endif\n"
 "uniform vec4 FogPlane;\n"
 "\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"varying vec3 ShadowMapTC;\n"
+"#endif\n"
+"\n"
 "\n"
 "\n"
 "\n"
@@ -1010,6 +1018,9 @@ static const char *builtinshaderstring =
 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
 "uniform sampler2D Texture_Attenuation;\n"
 "uniform samplerCube Texture_Cube;\n"
+"#endif\n"
+"\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
 "\n"
 "#ifdef USESHADOWMAPRECT\n"
 "# ifdef USESHADOWSAMPLER\n"
@@ -1045,7 +1056,21 @@ static const char *builtinshaderstring =
 "#endif\n"
 "\n"
 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
-"# ifndef USESHADOWMAPVSDCT\n"
+"# ifdef USESHADOWMAPORTHO\n"
+"#  define GetShadowMapTC2D(dir) (min(dir, vec3(ShadowMap_Parameters.zw, 1.0)))\n"
+"# else\n"
+"#  ifdef USESHADOWMAPVSDCT\n"
+"vec3 GetShadowMapTC2D(vec3 dir)\n"
+"{\n"
+"   vec3 adir = abs(dir);\n"
+"   vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
+"   float ma = max(max(adir.x, adir.y), adir.z);\n"
+"   vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
+"   stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
+"   stc.z += ShadowMap_Parameters.z;\n"
+"   return stc;\n"
+"}\n"
+"#  else\n"
 "vec3 GetShadowMapTC2D(vec3 dir)\n"
 "{\n"
 "      vec3 adir = abs(dir);\n"
@@ -1088,17 +1113,7 @@ static const char *builtinshaderstring =
 "      stc.z += ShadowMap_Parameters.z;\n"
 "      return stc;\n"
 "}\n"
-"# else\n"
-"vec3 GetShadowMapTC2D(vec3 dir)\n"
-"{\n"
-"      vec3 adir = abs(dir);\n"
-"      vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
-"      float ma = max(max(adir.x, adir.y), adir.z);\n"
-"      vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
-"      stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
-"      stc.z += ShadowMap_Parameters.z;\n"
-"      return stc;\n"
-"}\n"
+"#  endif\n"
 "# endif\n"
 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
 "\n"
@@ -1150,7 +1165,11 @@ static const char *builtinshaderstring =
 "#    endif\n"
 "\n"
 "#  endif\n"
+"#  ifdef USESHADOWMAPORTHO\n"
+"      return mix(ShadowMap_Parameters.x, ShadowMap_Parameters.y, f);\n"
+"#  else\n"
 "      return f;\n"
+"#  endif\n"
 "}\n"
 "# endif\n"
 "\n"
@@ -1213,7 +1232,11 @@ static const char *builtinshaderstring =
 "      f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
 "#    endif\n"
 "#  endif\n"
+"#  ifdef USESHADOWMAPORTHO\n"
+"      return mix(ShadowMap_Parameters.x, ShadowMap_Parameters.y, f);\n"
+"#  else\n"
 "      return f;\n"
+"#  endif\n"
 "}\n"
 "# endif\n"
 "\n"
@@ -1231,7 +1254,7 @@ static const char *builtinshaderstring =
 "      return f;\n"
 "}\n"
 "# endif\n"
-"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
+"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
 "#endif // FRAGMENT_SHADER\n"
 "\n"
 "\n"
@@ -1392,6 +1415,9 @@ static const char *builtinshaderstring =
 "#ifdef MODE_LIGHTSOURCE\n"
 "uniform mat4 ModelToLight;\n"
 "#endif\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"uniform mat4 ShadowMapMatrix;\n"
+"#endif\n"
 "void main(void)\n"
 "{\n"
 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
@@ -1450,6 +1476,10 @@ static const char *builtinshaderstring =
 "      // transform vertex to camera space, using ftransform to match non-VS rendering\n"
 "      gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
 "\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"      ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
+"#endif\n"
+"\n"
 "#ifdef USEREFLECTION\n"
 "      ModelViewProjectionPosition = gl_Position;\n"
 "#endif\n"
@@ -1645,6 +1675,10 @@ static const char *builtinshaderstring =
 "# endif\n"
 "#endif\n"
 "\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"      color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
+"#endif\n"
+"\n"
 "#ifdef USEDEFERREDLIGHTMAP\n"
 "      vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
 "      color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
@@ -2178,9 +2212,23 @@ const char *builtincgshaderstring =
 "}\n"
 "#endif // USEOFFSETMAPPING\n"
 "\n"
-"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
-"# ifndef USESHADOWMAPVSDCT\n"
+"# ifdef USESHADOWMAPORTHO\n"
+"#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, float3(ShadowMap_Parameters.zw, 1.0)))\n"
+"# else\n"
+"#  ifdef USESHADOWMAPVSDCT\n"
+"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
+"{\n"
+"   float3 adir = abs(dir);\n"
+"   float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
+"   float ma = max(max(adir.x, adir.y), adir.z);\n"
+"   float3 stc = float3(lerp(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
+"   stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
+"   stc.z += ShadowMap_Parameters.z;\n"
+"   return stc;\n"
+"}\n"
+"#  else\n"
 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
 "{\n"
 "      float3 adir = abs(dir);\n"
@@ -2223,19 +2271,9 @@ const char *builtincgshaderstring =
 "      stc.z += ShadowMap_Parameters.z;\n"
 "      return stc;\n"
 "}\n"
-"# else\n"
-"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
-"{\n"
-"      float3 adir = abs(dir);\n"
-"      float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
-"      float ma = max(max(adir.x, adir.y), adir.z);\n"
-"      float3 stc = float3(lerp(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
-"      stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
-"      stc.z += ShadowMap_Parameters.z;\n"
-"      return stc;\n"
-"}\n"
+"#  endif\n"
 "# endif\n"
-"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
+"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPORTHO)\n"
 "\n"
 "#ifdef USESHADOWMAPCUBE\n"
 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
@@ -2293,7 +2331,11 @@ const char *builtincgshaderstring =
 "#    endif\n"
 "\n"
 "#  endif\n"
+"#  ifdef USESHADOWMAPORTHO\n"
+"      return lerp(ShadowMap_Parameters.x, ShadowMap_Parameters.y, f);\n"
+"#  else\n"
 "      return f;\n"
+"#  endif\n"
 "}\n"
 "# endif\n"
 "\n"
@@ -2360,7 +2402,11 @@ const char *builtincgshaderstring =
 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
 "#    endif\n"
 "#  endif\n"
-"    return f;\n"
+"#  ifdef USESHADOWMAPORTHO\n"
+"      return lerp(ShadowMap_Parameters.x, ShadowMap_Parameters.y, f);\n"
+"#  else\n"
+"      return f;\n"
+"#  endif\n"
 "}\n"
 "# endif\n"
 "\n"
@@ -2672,6 +2718,9 @@ const char *builtincgshaderstring =
 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
 "uniform float3 LightPosition,\n"
 "#endif\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"uniform float4x4 ShadowMapMatrix,\n"
+"#endif\n"
 "\n"
 "out float4 gl_FrontColor : COLOR,\n"
 "out float4 TexCoordBoth : TEXCOORD0,\n"
@@ -2698,6 +2747,9 @@ const char *builtincgshaderstring =
 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
 "#endif\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"out float3 ShadowMapTC : TEXCOORD8,\n"
+"#endif\n"
 "out float4 gl_Position : POSITION\n"
 ")\n"
 "{\n"
@@ -2757,6 +2809,10 @@ const char *builtincgshaderstring =
 "      // transform vertex to camera space, using ftransform to match non-VS rendering\n"
 "      gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
 "\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"      ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
+"#endif\n"
+"\n"
 "#ifdef USEREFLECTION\n"
 "      ModelViewProjectionPosition = gl_Position;\n"
 "#endif\n"
@@ -2800,6 +2856,9 @@ const char *builtincgshaderstring =
 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
 "#endif\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"float3 ShadowMapTC : TEXCOORD8\n"
+"#endif\n"
 "\n"
 "uniform sampler2D Texture_Normal,\n"
 "uniform sampler2D Texture_Color,\n"
@@ -2894,6 +2953,9 @@ const char *builtincgshaderstring =
 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
 "uniform sampler2D Texture_Attenuation,\n"
 "uniform samplerCUBE Texture_Cube,\n"
+"#endif\n"
+"\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
 "\n"
 "#ifdef USESHADOWMAPRECT\n"
 "# ifdef USESHADOWSAMPLER\n"
@@ -2927,7 +2989,7 @@ const char *builtincgshaderstring =
 "uniform float2 ShadowMap_TextureScale,\n"
 "uniform float4 ShadowMap_Parameters,\n"
 "#endif\n"
-"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
+"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
 "\n"
 "out float4 gl_FragColor : COLOR\n"
 ")\n"
@@ -3104,6 +3166,17 @@ const char *builtincgshaderstring =
 "# endif\n"
 "#endif\n"
 "\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"      color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
+"# if defined(USESHADOWMAP2D)\n"
+"Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
+"# endif\n"
+"# if defined(USESHADOWMAPRECT)\n"
+"Texture_ShadowMapRect, ShadowMap_Parameters\n"
+"# endif\n"
+"      );\n"
+"#endif\n"
+"\n"
 "#ifdef USEDEFERREDLIGHTMAP\n"
 "      float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
 "      color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
@@ -3208,11 +3281,12 @@ typedef enum shaderpermutation_e
        SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
        SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
        SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
-       SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
-       SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
-       SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
-       SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
-       SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
+       SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
+       SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
+       SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
+       SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
+       SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
+       SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
 }
 shaderpermutation_t;
 
@@ -3243,6 +3317,7 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
        {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
        {"#define USESHADOWSAMPLER\n", " shadowsampler"},
        {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
+       {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
        {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
        {"#define USEALPHAKILL\n", " alphakill"},
        {"#define USEREFLECTCUBE\n", " reflectcube"},
@@ -3404,6 +3479,7 @@ typedef struct r_glsl_permutation_s
        int loc_ModelViewMatrix;
        int loc_PixelToScreenTexCoord;
        int loc_ModelToReflectCube;
+       int loc_ShadowMapMatrix;        
 }
 r_glsl_permutation_t;
 
@@ -3629,6 +3705,7 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode
                p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
                p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
                p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
+               p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
                // initialize the samplers to refer to the texture units we use
                if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
                if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
@@ -3650,9 +3727,9 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode
                if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
                if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
                if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
-               if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
+               if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
                if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
-               if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
+               if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
                if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
                if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
                if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
@@ -3716,6 +3793,7 @@ void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutatio
        }
        if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
        if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
+       if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
 }
 
 #ifdef SUPPORTCG
@@ -3743,6 +3821,7 @@ typedef struct r_cg_permutation_s
        CGparameter vp_BackgroundTexMatrix;
        CGparameter vp_ModelViewProjectionMatrix;
        CGparameter vp_ModelViewMatrix;
+       CGparameter vp_ShadowMapMatrix;
 
        CGparameter fp_Texture_First;
        CGparameter fp_Texture_Second;
@@ -4034,6 +4113,7 @@ static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, un
                p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
                p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
                p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
+               p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
                CHECKCGERROR
        }
        if (p->fprogram)
@@ -4204,6 +4284,7 @@ void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
        CHECKCGERROR
        if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
        if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
+       if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
 }
 
 void CG_BindTexture(CGparameter param, rtexture_t *tex)
@@ -4394,6 +4475,7 @@ extern rtexture_t *r_shadow_attenuation3dtexture;
 extern qboolean r_shadow_usingshadowmaprect;
 extern qboolean r_shadow_usingshadowmapcube;
 extern qboolean r_shadow_usingshadowmap2d;
+extern qboolean r_shadow_usingshadowmaportho;
 extern float r_shadow_shadowmap_texturescale[2];
 extern float r_shadow_shadowmap_parameters[4];
 extern qboolean r_shadow_shadowmapvsdct;
@@ -4403,6 +4485,7 @@ extern rtexture_t *r_shadow_shadowmaprectangletexture;
 extern rtexture_t *r_shadow_shadowmap2dtexture;
 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
+extern matrix4x4_t r_shadow_shadowmapmatrix;
 extern int r_shadow_shadowmaplod; // changes for each light based on distance
 extern int r_shadow_prepass_width;
 extern int r_shadow_prepass_height;
@@ -4551,6 +4634,21 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
                if (rsurface.texture->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
+               if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
+               {
+                       permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
+                       if (r_shadow_usingshadowmaprect)
+                               permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+                       if (r_shadow_usingshadowmap2d)
+                               permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+
+                       if (r_shadow_shadowmapsampler)
+                               permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
+                       if (r_shadow_shadowmappcf > 1)
+                               permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
+                       else if (r_shadow_shadowmappcf)
+                               permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+               }
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
                        permutation |= SHADERPERMUTATION_REFLECTION;
                if (rsurface.texture->reflectmasktexture)
@@ -4601,6 +4699,21 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
                if (rsurface.texture->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
+               if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
+               {
+                       permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
+                       if (r_shadow_usingshadowmaprect)
+                               permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+                       if (r_shadow_usingshadowmap2d)
+                               permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+
+                       if (r_shadow_shadowmapsampler)
+                               permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
+                       if (r_shadow_shadowmappcf > 1)
+                               permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
+                       else if (r_shadow_shadowmappcf)
+                               permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+               }
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
                        permutation |= SHADERPERMUTATION_REFLECTION;
                if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
@@ -4643,6 +4756,21 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
                if (rsurface.texture->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
+               if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
+               {
+                       permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
+                       if (r_shadow_usingshadowmaprect)
+                               permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+                       if (r_shadow_usingshadowmap2d)
+                               permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+
+                       if (r_shadow_shadowmapsampler)
+                               permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
+                       if (r_shadow_shadowmappcf > 1)
+                               permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
+                       else if (r_shadow_shadowmappcf)
+                               permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+               }
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
                        permutation |= SHADERPERMUTATION_REFLECTION;
                if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
@@ -4684,6 +4812,21 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
                if (rsurface.texture->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
+               if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
+               {
+                       permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
+                       if (r_shadow_usingshadowmaprect)
+                               permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+                       if (r_shadow_usingshadowmap2d)
+                               permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+
+                       if (r_shadow_shadowmapsampler)
+                               permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
+                       if (r_shadow_shadowmappcf > 1)
+                               permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
+                       else if (r_shadow_shadowmappcf)
+                               permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+               }
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
                        permutation |= SHADERPERMUTATION_REFLECTION;
                if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
@@ -4777,8 +4920,6 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        // additive passes are only darkened by fog, not tinted
                        if (r_glsl_permutation->loc_FogColor >= 0)
                                qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
-                       if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
-                       if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
                        if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
                }
                else
@@ -4824,6 +4965,10 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                }
                if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
                if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
+               if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
+               if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
+               if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
+
                if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
                if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
                if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
@@ -4874,14 +5019,17 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
                if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
                if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
-               if (rsurface.rtlight)
+               if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
                {
-                       if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
-                       if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT     , r_shadow_shadowmaprectangletexture                  );
-                       if (r_shadow_usingshadowmapcube)
-                               if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
-                       if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       , r_shadow_shadowmap2dtexture                         );
-                       if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
+                       if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
+                       if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
+                       if (rsurface.rtlight)
+                       {
+                               if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
+                               if (r_shadow_usingshadowmapcube)
+                                       if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
+                               if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
+                       }
                }
                CHECKGLERROR
                break;
@@ -4903,6 +5051,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                }
                if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
                if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
+               if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
                if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
                if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
                CHECKGLERROR
@@ -4917,8 +5066,6 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
 
                        // additive passes are only darkened by fog, not tinted
                        if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
-                       if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
-                       if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
                        if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
                }
                else
@@ -4963,6 +5110,8 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
                        if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
                }
+               if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
+               if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
                if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
                if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
                if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
@@ -5015,14 +5164,17 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
                if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
                if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
-               if (rsurface.rtlight)
+               if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
                {
-                       if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
-                       if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
-                       if (r_shadow_usingshadowmapcube)
-                               if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
                        if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
-                       if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
+                       if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
+                       if (rsurface.rtlight)
+                       {
+                               if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
+                               if (r_shadow_usingshadowmapcube)
+                                       if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
+                               if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
+                       }
                }
 
                CHECKGLERROR
@@ -5329,7 +5481,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        // check for DDS texture file first
        if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
        {
-               basepixels = loadimagepixelsbgra(name, complain, true);
+               basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
                if (basepixels == NULL)
                        return NULL;
        }
@@ -5414,13 +5566,13 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        // _norm is the name used by tenebrae and has been adopted as standard
        if (r_loadnormalmap && skinframe->nmap == NULL)
        {
-               if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
+               if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
                {
                        skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
                        Mem_Free(pixels);
                        pixels = NULL;
                }
-               else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
+               else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
                {
                        pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
                        Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
@@ -5441,7 +5593,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
 
        // _luma is supported only for tenebrae compatibility
        // _glow is the preferred name
-       if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
+       if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer))))
        {
                skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
@@ -5449,7 +5601,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
                Mem_Free(pixels);pixels = NULL;
        }
 
-       if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
+       if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
        {
                skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
@@ -5458,7 +5610,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
                pixels = NULL;
        }
 
-       if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
+       if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
        {
                skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
@@ -5467,7 +5619,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
                pixels = NULL;
        }
 
-       if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
+       if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
        {
                skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
@@ -5476,7 +5628,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
                pixels = NULL;
        }
 
-       if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false)))
+       if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
        {
                skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), NULL);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
@@ -5820,7 +5972,7 @@ rtexture_t *R_LoadCubemap(const char *basename)
                        // generate an image name based on the base and and suffix
                        dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
                        // load it
-                       if ((image_buffer = loadimagepixelsbgra(name, false, false)))
+                       if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
                        {
                                // an image loaded, make sure width and height are equal
                                if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
@@ -6179,6 +6331,11 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_transparentdepthmasking);
        Cvar_RegisterVariable(&r_texture_dds_load);
        Cvar_RegisterVariable(&r_texture_dds_save);
+       Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
+       Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
+       Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
+       Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
+       Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
        Cvar_RegisterVariable(&r_textureunits);
        Cvar_RegisterVariable(&gl_combine);
        Cvar_RegisterVariable(&r_glsl);
@@ -6559,11 +6716,6 @@ void R_AnimCache_CacheVisibleEntities(void)
        for (i = 0;i < r_refdef.scene.numentities;i++)
                if (r_refdef.viewcache.entityvisible[i])
                        R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
-
-       if (r_shadows.integer)
-               for (i = 0;i < r_refdef.scene.numentities;i++)
-                       if (!r_refdef.viewcache.entityvisible[i])
-                               R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
 }
 
 //==================================================================================
@@ -6676,6 +6828,10 @@ static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t en
        boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
        boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
 
+       // return true if eye is inside enlarged box
+       if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
+               return true;
+
        // try center
        VectorCopy(eye, start);
        VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
@@ -7773,7 +7929,6 @@ static void R_BlendView(void)
                        if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
                        if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
                        if (r_glsl_permutation->loc_ViewTintColor      >= 0) qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
-                       if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
                        if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
                        if (r_glsl_permutation->loc_UserVec1           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
                        if (r_glsl_permutation->loc_UserVec2           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
@@ -7789,7 +7944,6 @@ static void R_BlendView(void)
                        if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
                        if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
                        if (r_cg_permutation->fp_ViewTintColor     ) cgGLSetParameter4f(     r_cg_permutation->fp_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);CHECKCGERROR
-                       if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
                        if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
                        if (r_cg_permutation->fp_UserVec1          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);CHECKCGERROR
                        if (r_cg_permutation->fp_UserVec2          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);CHECKCGERROR
@@ -8144,10 +8298,14 @@ extern cvar_t cl_locs_show;
 static void R_DrawLocs(void);
 static void R_DrawEntityBBoxes(void);
 static void R_DrawModelDecals(void);
+extern void R_DrawModelShadows(void);
+extern void R_DrawModelShadowMaps(void);
 extern cvar_t cl_decals_newsystem;
 extern qboolean r_shadow_usingdeferredprepass;
 void R_RenderScene(void)
 {
+       qboolean shadowmapping = false;
+
        r_refdef.stats.renders++;
 
        R_UpdateFogColor();
@@ -8181,11 +8339,8 @@ void R_RenderScene(void)
                if (skyrendermasked && skyrenderlater)
                {
                        // we have to force off the water clipping plane while rendering sky
-                       qboolean save = r_refdef.view.showdebug;
                        R_SetupView(false);
-                       r_refdef.view.showdebug = false;
                        R_Sky();
-                       r_refdef.view.showdebug = save;
                        R_SetupView(true);
                        if (r_timereport_active)
                                R_TimeReport("sky");
@@ -8197,9 +8352,14 @@ void R_RenderScene(void)
                R_TimeReport("animation");
 
        R_Shadow_PrepareLights();
+       if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
+               R_Shadow_PrepareModelShadows();
        if (r_timereport_active)
                R_TimeReport("preparelights");
 
+       if (R_Shadow_ShadowMappingEnabled())
+               shadowmapping = true;
+
        if (r_shadow_usingdeferredprepass)
                R_Shadow_DrawPrepass();
 
@@ -8216,6 +8376,15 @@ void R_RenderScene(void)
                        R_TimeReport("modeldepth");
        }
 
+       if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
+       {
+               R_DrawModelShadowMaps();
+               R_ResetViewRendering3D();
+               // don't let sound skip if going slow
+               if (r_refdef.scene.extraupdate)
+                       S_ExtraUpdate ();
+       }
+
        if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
        {
                r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
@@ -8235,7 +8404,7 @@ void R_RenderScene(void)
        if (r_refdef.scene.extraupdate)
                S_ExtraUpdate ();
 
-       if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
+       if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
        {
                R_DrawModelShadows();
                R_ResetViewRendering3D();
@@ -8255,7 +8424,7 @@ void R_RenderScene(void)
        if (r_refdef.scene.extraupdate)
                S_ExtraUpdate ();
 
-       if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
+       if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
        {
                R_DrawModelShadows();
                R_ResetViewRendering3D();
@@ -8845,7 +9014,7 @@ void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
                f = FS_LoadFile(name, tempmempool, true, &filesize);
                if (f)
                {
-                       if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
+                       if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
                                skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
                        Mem_Free(f);
                }
@@ -10965,7 +11134,7 @@ static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface
 {
        CHECKGLERROR
        RSurf_SetupDepthAndCulling();
-       if (r_showsurfaces.integer == 3 && !prepass)
+       if (r_showsurfaces.integer == 3 && !prepass && (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
        {
                R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
                return;
@@ -10990,7 +11159,7 @@ static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface
 {
        CHECKGLERROR
        RSurf_SetupDepthAndCulling();
-       if (r_showsurfaces.integer == 3 && !prepass)
+       if (r_showsurfaces.integer == 3 && !prepass && (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
        {
                R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
                return;
@@ -11421,7 +11590,6 @@ static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float
        tridecal_t *decal;
        tridecal_t *decals;
        int i;
-       int maxdecals;
 
        // expand or initialize the system
        if (decalsystem->maxdecals <= decalsystem->numdecals)
@@ -11448,7 +11616,6 @@ static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float
        }
 
        // grab a decal and search for another free slot for the next one
-       maxdecals = decalsystem->maxdecals;
        decals = decalsystem->decals;
        decal = decalsystem->decals + (i = decalsystem->freedecal++);
        for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
@@ -11505,13 +11672,11 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor
        const msurface_t *surfaces;
        const int *surfacelist;
        const texture_t *texture;
-       int numvertices;
        int numtriangles;
        int numsurfacelist;
        int surfacelistindex;
        int surfaceindex;
        int triangleindex;
-       int decalsurfaceindex;
        int cornerindex;
        int index;
        int numpoints;
@@ -11521,7 +11686,6 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor
        float localmins[3];
        float localmaxs[3];
        float localsize;
-       float ilocalsize;
        float v[9][3];
        float tc[9][2];
        float c[9][4];
@@ -11557,7 +11721,6 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor
        Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
        VectorNormalize(localnormal);
        localsize = worldsize*rsurface.inversematrixscale;
-       ilocalsize = 1.0f / localsize;
        localmins[0] = localorigin[0] - localsize;
        localmins[1] = localorigin[1] - localsize;
        localmins[2] = localorigin[2] - localsize;
@@ -11627,8 +11790,6 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor
                        continue;
                if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
                        continue;
-               decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
-               numvertices = surface->num_vertices;
                numtriangles = surface->num_triangles;
                for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
                {
@@ -11843,7 +12004,6 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent)
        decalsystem_t *decalsystem = &ent->decalsystem;
        int numdecals;
        tridecal_t *decal;
-       float fadedelay;
        float faderate;
        float alpha;
        float *v3f;
@@ -11877,7 +12037,6 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent)
        decalsystem->lastupdatetime = cl.time;
        decal = decalsystem->decals;
 
-       fadedelay = cl_decals_time.value;
        faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
 
        // update vertex positions for animated models
@@ -12023,7 +12182,6 @@ void R_DrawDebugModel(void)
 {
        entity_render_t *ent = rsurface.entity;
        int i, j, k, l, flagsmask;
-       const int *elements;
        q3mbrush_t *brush;
        const msurface_t *surface;
        dp_model_t *model = ent->model;
@@ -12092,7 +12250,6 @@ void R_DrawDebugModel(void)
                                                GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
                                        else
                                                GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
-                                       elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
                                        R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
                                        R_Mesh_ColorPointer(NULL, 0, 0);
                                        R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
@@ -12167,8 +12324,7 @@ int r_maxsurfacelist = 0;
 const msurface_t **r_surfacelist = NULL;
 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
 {
-       int i, j, endj, f, flagsmask;
-       texture_t *t;
+       int i, j, endj, flagsmask;
        dp_model_t *model = r_refdef.scene.worldmodel;
        msurface_t *surfaces;
        unsigned char *update;
@@ -12214,8 +12370,6 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep
                return;
        }
 
-       f = 0;
-       t = NULL;
        rsurface.uselightmaptexture = false;
        rsurface.texture = NULL;
        rsurface.rtlight = NULL;
@@ -12264,8 +12418,7 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep
 
 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
 {
-       int i, j, endj, f, flagsmask;
-       texture_t *t;
+       int i, j, endj, flagsmask;
        dp_model_t *model = ent->model;
        msurface_t *surfaces;
        unsigned char *update;
@@ -12291,7 +12444,19 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
        else if (prepass)
                RSurf_ActiveModelEntity(ent, true, true, true);
        else if (depthonly)
-               RSurf_ActiveModelEntity(ent, false, false, false);
+       {
+               switch (vid.renderpath)
+               {
+               case RENDERPATH_GL20:
+               case RENDERPATH_CGGL:
+                       RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
+                       break;
+               case RENDERPATH_GL13:
+               case RENDERPATH_GL11:
+                       RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
+                       break;
+               }
+       }
        else
        {
                switch (vid.renderpath)
@@ -12335,8 +12500,6 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
                return;
        }
 
-       f = 0;
-       t = NULL;
        rsurface.uselightmaptexture = false;
        rsurface.texture = NULL;
        rsurface.rtlight = NULL;