]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rmain.c
added indirection cube map for shadowmapping and revised filtering modes
[xonotic/darkplaces.git] / gl_rmain.c
index e2f38cde2c52fff67bb452231cba1742d87323d5..473635b204a48e651f197446807736a46743dfd3 100644 (file)
@@ -75,7 +75,7 @@ cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows fro
 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
-cvar_t r_shadows_drawafterrtlightning = {CVAR_SAVE, "r_shadows_drawafterrtlightning", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
+cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
@@ -95,7 +95,6 @@ cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the re
 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
 
 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
 
 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
-cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
@@ -166,6 +165,8 @@ static struct r_bloomstate_s
        float screentexcoord2f[8];
        float bloomtexcoord2f[8];
        float offsettexcoord2f[8];
        float screentexcoord2f[8];
        float bloomtexcoord2f[8];
        float offsettexcoord2f[8];
+
+       r_viewport_t viewport;
 }
 r_bloomstate;
 
 }
 r_bloomstate;
 
@@ -194,7 +195,7 @@ char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
 
 /// vertex coordinates for a quad that covers the screen exactly
 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
 
 /// vertex coordinates for a quad that covers the screen exactly
-const static float r_screenvertex3f[12] =
+const float r_screenvertex3f[12] =
 {
        0, 0, 0,
        1, 0, 0,
 {
        0, 0, 0,
        1, 0, 0,
@@ -446,13 +447,24 @@ static void R_BuildFogTexture(void)
 static const char *builtinshaderstring =
 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
 "// written by Forest 'LordHavoc' Hale\n"
 static const char *builtinshaderstring =
 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
 "// written by Forest 'LordHavoc' Hale\n"
+"#ifdef USESHADOWMAPRECT\n"
+"#extension GL_ARB_texture_rectangle : enable\n"
+"# ifdef HASTEXTUREGATHER\n"
+"#   extension GL_ARB_texture_gather : enable\n"
+"# else\n"
+"#   ifdef HASTEXTURE4\n"
+"#     extension GL_AMD_texture_texture4 : enable\n"
+"#     define textureGather texture4\n"
+"#   endif\n"
+"# endif\n"
+"#endif\n"
 "\n"
 "// common definitions between vertex shader and fragment shader:\n"
 "\n"
 "//#ifdef __GLSL_CG_DATA_TYPES\n"
 "//# define myhalf half\n"
 "//# define myhalf2 half2\n"
 "\n"
 "// common definitions between vertex shader and fragment shader:\n"
 "\n"
 "//#ifdef __GLSL_CG_DATA_TYPES\n"
 "//# define myhalf half\n"
 "//# define myhalf2 half2\n"
-"//# define myhalf3 half3\n"
+"//# define myhalf3half3\n"
 "//# define myhalf4 half4\n"
 "//#else\n"
 "# define myhalf float\n"
 "//# define myhalf4 half4\n"
 "//#else\n"
 "# define myhalf float\n"
@@ -471,6 +483,22 @@ static const char *builtinshaderstring =
 "# endif\n"
 "\n"
 "#else\n"
 "# endif\n"
 "\n"
 "#else\n"
+"#ifdef MODE_SHOWDEPTH\n"
+"# ifdef VERTEX_SHADER\n"
+"void main(void)\n"
+"{\n"
+"      gl_Position = ftransform();\n"
+"      gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
+"}\n"
+"# endif\n"
+"# ifdef FRAGMENT_SHADER\n"
+"void main(void)\n"
+"{\n"
+"      gl_FragColor = gl_Color;\n"
+"}\n"
+"# endif\n"
+"\n"
+"#else // !MODE_SHOWDEPTH\n"
 "\n"
 "#ifdef MODE_POSTPROCESS\n"
 "# ifdef VERTEX_SHADER\n"
 "\n"
 "#ifdef MODE_POSTPROCESS\n"
 "# ifdef VERTEX_SHADER\n"
@@ -479,7 +507,7 @@ static const char *builtinshaderstring =
 "      gl_FrontColor = gl_Color;\n"
 "      gl_Position = ftransform();\n"
 "      gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
 "      gl_FrontColor = gl_Color;\n"
 "      gl_Position = ftransform();\n"
 "      gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
-"#ifdef USEGLOW\n"
+"#ifdef USEBLOOM\n"
 "      gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
 "#endif\n"
 "}\n"
 "      gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
 "#endif\n"
 "}\n"
@@ -487,7 +515,7 @@ static const char *builtinshaderstring =
 "# ifdef FRAGMENT_SHADER\n"
 "\n"
 "uniform sampler2D Texture_First;\n"
 "# ifdef FRAGMENT_SHADER\n"
 "\n"
 "uniform sampler2D Texture_First;\n"
-"#ifdef USEGLOW\n"
+"#ifdef USEBLOOM\n"
 "uniform sampler2D Texture_Second;\n"
 "#endif\n"
 "#ifdef USEGAMMARAMPS\n"
 "uniform sampler2D Texture_Second;\n"
 "#endif\n"
 "#ifdef USEGAMMARAMPS\n"
@@ -496,12 +524,9 @@ static const char *builtinshaderstring =
 "#ifdef USESATURATION\n"
 "uniform float Saturation;\n"
 "#endif\n"
 "#ifdef USESATURATION\n"
 "uniform float Saturation;\n"
 "#endif\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
+"#ifdef USEVIEWTINT\n"
 "uniform vec4 TintColor;\n"
 "#endif\n"
 "uniform vec4 TintColor;\n"
 "#endif\n"
-"#ifdef USECOLORMOD\n"
-"uniform vec3 Gamma;\n"
-"#endif\n"
 "//uncomment these if you want to use them:\n"
 "uniform vec4 UserVec1;\n"
 "// uniform vec4 UserVec2;\n"
 "//uncomment these if you want to use them:\n"
 "uniform vec4 UserVec1;\n"
 "// uniform vec4 UserVec2;\n"
@@ -512,10 +537,10 @@ static const char *builtinshaderstring =
 "void main(void)\n"
 "{\n"
 "      gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
 "void main(void)\n"
 "{\n"
 "      gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
-"#ifdef USEGLOW\n"
+"#ifdef USEBLOOM\n"
 "      gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
 "#endif\n"
 "      gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
 "#endif\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
+"#ifdef USEVIEWTINT\n"
 "      gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
 "#endif\n"
 "\n"
 "      gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
 "#endif\n"
 "\n"
@@ -534,7 +559,7 @@ static const char *builtinshaderstring =
 "      //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
 "      myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
 "      //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
 "      //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
 "      myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
 "      //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
-"      gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" // TODO: test this on ATI
+"      gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
 "#endif\n"
 "\n"
 "#ifdef USEGAMMARAMPS\n"
 "#endif\n"
 "\n"
 "#ifdef USEGAMMARAMPS\n"
@@ -740,6 +765,18 @@ static const char *builtinshaderstring =
 "uniform sampler2D Texture_Attenuation;\n"
 "uniform samplerCube Texture_Cube;\n"
 "\n"
 "uniform sampler2D Texture_Attenuation;\n"
 "uniform samplerCube Texture_Cube;\n"
 "\n"
+"#define showshadowmap 0\n"
+"\n"
+"#ifdef USESHADOWMAPRECT\n"
+"# ifdef USESHADOWSAMPLER\n"
+"uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
+"# else\n"
+"uniform sampler2DRect Texture_ShadowMapRect;\n"
+"# endif\n"
+"\n"
+"uniform samplerCube Texture_CubeProjection;\n"
+"#endif\n"
+"\n"
 "uniform myhalf3 LightColor;\n"
 "uniform myhalf3 AmbientColor;\n"
 "uniform myhalf3 DiffuseColor;\n"
 "uniform myhalf3 LightColor;\n"
 "uniform myhalf3 AmbientColor;\n"
 "uniform myhalf3 DiffuseColor;\n"
@@ -780,9 +817,6 @@ static const char *builtinshaderstring =
 "\n"
 "uniform myhalf GlowScale;\n"
 "uniform myhalf SceneBrightness;\n"
 "\n"
 "uniform myhalf GlowScale;\n"
 "uniform myhalf SceneBrightness;\n"
-"#ifdef USECONTRASTBOOST\n"
-"uniform myhalf ContrastBoostCoeff;\n"
-"#endif\n"
 "\n"
 "uniform float OffsetMapping_Scale;\n"
 "uniform float OffsetMapping_Bias;\n"
 "\n"
 "uniform float OffsetMapping_Scale;\n"
 "uniform float OffsetMapping_Bias;\n"
@@ -838,6 +872,181 @@ static const char *builtinshaderstring =
 "}\n"
 "#endif // USEOFFSETMAPPING\n"
 "\n"
 "}\n"
 "#endif // USEOFFSETMAPPING\n"
 "\n"
+"#ifdef USESHADOWMAPRECT \n"
+"uniform vec4 ShadowMap_TextureScale;\n"
+"#if 0\n"
+"uniform vec4 ShadowMap_Parameters;\n"
+"#endif\n"
+"\n"
+"vec3 GetShadowMapTC2D(vec3 dir)\n"
+"{\n"
+"      vec3 adir = abs(dir);\n"
+"# if 0\n"
+"      vec2 tc;\n"
+"      vec2 offset;\n"
+"      float ma;\n"
+"      if (adir.x > adir.y)\n"
+"      {\n"
+"              if (adir.x > adir.z)\n"
+"              {\n"
+"                      ma = adir.x;\n"
+"                      if (dir.x >= 0.0)\n"
+"                      {\n"
+"                              // +X\n"
+"                              tc = vec2(-dir.z, -dir.y);\n"
+"                              offset = vec2(0.5, 0.5);\n"
+"                      }\n"
+"                      else\n"
+"                      {\n"
+"                              // -X\n"
+"                              tc = vec2( dir.z, -dir.y);\n"
+"                              offset = vec2(1.5, 0.5);\n"
+"                      }\n"
+"              }\n"
+"              else\n"
+"              {\n"
+"            ma = adir.z;\n"
+"                      if (dir.z >= 0.0)\n"
+"                      {\n"
+"                              // +Z\n"
+"                              tc = vec2( dir.x, -dir.y);\n"
+"                              offset = vec2(0.5, 2.5);\n"
+"                      }\n"
+"                      else\n"
+"                      {\n"
+"                              // -Z\n"
+"                              tc = vec2(-dir.x, -dir.y);\n"
+"                              offset = vec2(1.5, 2.5);\n"
+"                      }\n"
+"              }\n"
+"      }\n"
+"      else\n"
+"      {\n"
+"              if (adir.y > adir.z)\n"
+"              {\n"
+"            ma = adir.y;\n"
+"                      if (dir.y >= 0.0)\n"
+"                      {\n"
+"                              // +Y\n"
+"                              tc = vec2( dir.x,  dir.z);\n"
+"                              offset = vec2(0.5, 1.5);\n"
+"                      }\n"
+"                      else\n"
+"                      {\n"
+"                              // -Y\n"
+"                              tc = vec2( dir.x, -dir.z);\n"
+"                              offset = vec2(1.5, 1.5);\n"
+"                      }\n"
+"              }\n"
+"              else\n"
+"              {\n"
+"            ma = adir.z;\n"
+"                      if (dir.z >= 0.0)\n"
+"                      {\n"
+"                              // +Z\n"
+"                              tc = vec2(dir.x, -dir.y);\n"
+"                              offset = vec2(0.5, 2.5);\n"
+"                      }\n"
+"                      else\n"
+"                      {\n"
+"                              // -Z\n"
+"                              tc = vec2(-dir.x, -dir.y);\n"
+"                              offset = vec2(1.5, 2.5);\n"
+"                      }\n"
+"              }\n"
+"      }\n"
+"\n"
+"      return vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma + vec3(offset * ShadowMap_Parameters.y, ShadowMap_Parameters.z);\n"
+"# else\n"
+"    return vec3(textureCube(Texture_CubeProjection, dir.xyz).ra * ShadowMap_TextureScale.xy, ShadowMap_TextureScale.z + ShadowMap_TextureScale.w / max(max(adir.x, adir.y), adir.z));\n"
+"# endif\n"
+"}\n"
+"\n"
+"#endif // USESHADOWMAPRECT\n"
+"\n"
+"#if !showshadowmap\n"
+"# ifdef USESHADOWMAPRECT\n"
+"float ShadowMapCompare(vec3 dir)\n"
+"{\n"
+"      vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
+"      float f;\n"
+"#  ifdef USESHADOWSAMPLER\n"
+"\n"
+"#    ifdef USESHADOWMAPPCF\n"
+"      f = dot(vec4(0.25),\n"
+"                      vec4(shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3(-0.4,  1.0, 0.0)).r,\n"
+"                               shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3(-1.0, -0.4, 0.0)).r,\n"
+"                               shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3( 0.4, -1.0, 0.0)).r,\n"
+"                               shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3( 1.0,  0.4, 0.0)).r));\n"
+"#    else\n"
+"    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
+"#    endif\n"
+"\n"
+"#  else\n"
+"\n"
+"#    ifdef USESHADOWMAPPCF\n"
+"#      if defined(HASTEXTUREGATHER) || defined(HASTEXTURE4)\n"
+"    vec2 offset = fract(shadowmaptc.xy - 0.5);\n"
+"    vec4 group1 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, -1.0))),\n"
+"         group2 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, -1.0))),\n"
+"         group3 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0,  1.0))),\n"
+"         group4 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0,  1.0))),\n"
+"         cols = vec4(group1.ab, group2.ab) + vec4(group3.rg, group4.rg) +\n"
+"                mix(vec4(group1.rg, group2.rg), vec4(group3.ab, group4.ab), offset.y);\n"
+"    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
+"#      elif 1\n"
+"    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
+"    vec4 row1 = step(shadowmaptc.z,\n"
+"                    vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0, -1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 0.0, -1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0, -1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0, -1.0)).r)),\n"
+"         row2 = step(shadowmaptc.z,\n"
+"                    vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0,  0.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0,  0.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0,  0.0)).r)),\n"
+"         row3 = step(shadowmaptc.z,\n"
+"                    vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0,  1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 0.0,  1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0,  1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0,  1.0)).r)),\n"
+"         row4 = step(shadowmaptc.z,\n"
+"                    vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0,  2.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 0.0,  2.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0,  2.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0,  2.0)).r)),\n"
+"         cols = row2 + row3 + mix(row1, row4, offset.y);\n"
+"    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
+"#      else\n"
+"    vec2 offset = fract(shadowmaptc.xy);\n"
+"    vec3 row1 = step(shadowmaptc.z,\n"
+"                    vec3(texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, -1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 0.0, -1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, -1.0)).r)),\n"
+"         row2 = step(shadowmaptc.z,\n"
+"                    vec3(texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0,  0.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0,  0.0)).r)),\n"
+"         row3 = step(shadowmaptc.z,\n"
+"                    vec3(texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0,  1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 0.0,  1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0,  1.0)).r)),\n"
+"         cols = row2 + mix(row1, row3, offset.y);\n"
+"    f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
+"#      endif\n"
+"#    else\n"
+"    f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
+"#    endif\n"
+"\n"
+"#  endif\n"
+"      return f;\n"
+"}\n"
+"# endif\n"
+"\n"
+"#endif\n"
+"\n"
+"\n"
 "#ifdef MODE_WATER\n"
 "\n"
 "// water pass\n"
 "#ifdef MODE_WATER\n"
 "\n"
 "// water pass\n"
@@ -851,7 +1060,23 @@ static const char *builtinshaderstring =
 "\n"
 "      vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
 "      //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
 "\n"
 "      vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
 "      //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
-"      vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
+"      vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
+"      vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
+"      // FIXME temporary hack to detect the case that the reflection\n"
+"      // gets blackened at edges due to leaving the area that contains actual\n"
+"      // content.\n"
+"      // Remove this 'ack once we have a better way to stop this thing from\n"
+"      // 'appening.\n"
+"      float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
+"      f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
+"      f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
+"      f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
+"      ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
+"      f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
+"      f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
+"      f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
+"      f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
+"      ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
 "      float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
 "      gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
 "}\n"
 "      float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
 "      gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
 "}\n"
@@ -870,7 +1095,18 @@ static const char *builtinshaderstring =
 "\n"
 "      vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
 "      //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
 "\n"
 "      vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
 "      //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
-"      vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
+"      vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
+"      vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
+"      // FIXME temporary hack to detect the case that the reflection\n"
+"      // gets blackened at edges due to leaving the area that contains actual\n"
+"      // content.\n"
+"      // Remove this 'ack once we have a better way to stop this thing from\n"
+"      // 'appening.\n"
+"      float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
+"      f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
+"      f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
+"      f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
+"      ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
 "      gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
 "}\n"
 "\n"
 "      gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
 "}\n"
 "\n"
@@ -946,6 +1182,12 @@ static const char *builtinshaderstring =
 "#  endif\n"
 "# endif\n"
 "\n"
 "#  endif\n"
 "# endif\n"
 "\n"
+"#ifdef USESHADOWMAPRECT\n"
+"#if !showshadowmap\n"
+"      color.rgb *= ShadowMapCompare(CubeVector);\n"
+"#endif\n"
+"#endif\n"
+"\n"
 "# ifdef USECUBEFILTER\n"
 "      // apply light cubemap filter\n"
 "      //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
 "# ifdef USECUBEFILTER\n"
 "      // apply light cubemap filter\n"
 "      //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
@@ -1079,10 +1321,6 @@ static const char *builtinshaderstring =
 "#endif\n"
 "#endif\n"
 "\n"
 "#endif\n"
 "#endif\n"
 "\n"
-"#ifdef USECONTRASTBOOST\n"
-"      color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
-"#endif\n"
-"\n"
 "      color.rgb *= SceneBrightness;\n"
 "\n"
 "      // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
 "      color.rgb *= SceneBrightness;\n"
 "\n"
 "      // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
@@ -1094,11 +1332,32 @@ static const char *builtinshaderstring =
 "#ifdef USEREFLECTION\n"
 "      vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
 "      //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
 "#ifdef USEREFLECTION\n"
 "      vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
 "      //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
-"      vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
-"      color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
+"      vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
+"      vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
+"      // FIXME temporary hack to detect the case that the reflection\n"
+"      // gets blackened at edges due to leaving the area that contains actual\n"
+"      // content.\n"
+"      // Remove this 'ack once we have a better way to stop this thing from\n"
+"      // 'appening.\n"
+"      float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
+"      f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
+"      f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
+"      f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
+"      ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
+"      color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
 "#endif\n"
 "\n"
 "      gl_FragColor = vec4(color);\n"
 "#endif\n"
 "\n"
 "      gl_FragColor = vec4(color);\n"
+"\n"
+"#if showshadowmap\n"
+"# ifdef USESHADOWMAPRECT\n"
+"#  ifdef USESHADOWSAMPLER\n"
+"      gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
+"#  else\n"
+"      gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
+"#  endif\n"
+"# endif\n"
+"#endif\n"
 "}\n"
 "#endif // !MODE_REFRACTION\n"
 "#endif // !MODE_WATER\n"
 "}\n"
 "#endif // !MODE_REFRACTION\n"
 "#endif // !MODE_WATER\n"
@@ -1107,6 +1366,7 @@ static const char *builtinshaderstring =
 "\n"
 "#endif // !MODE_GENERIC\n"
 "#endif // !MODE_POSTPROCESS\n"
 "\n"
 "#endif // !MODE_GENERIC\n"
 "#endif // !MODE_POSTPROCESS\n"
+"#endif // !MODE_SHOWDEPTH\n"
 "#endif // !MODE_DEPTH_OR_SHADOW\n"
 ;
 
 "#endif // !MODE_DEPTH_OR_SHADOW\n"
 ;
 
@@ -1131,21 +1391,25 @@ typedef enum shaderpermutation_e
 {
        SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
        SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
 {
        SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
        SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
+       SHADERPERMUTATION_VIEWTINT = 1<<1, ///< view tint (postprocessing only)
        SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
        SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
-       SHADERPERMUTATION_CONTRASTBOOST = 1<<3, ///< r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
-       SHADERPERMUTATION_FOG = 1<<4, ///< tint the color by fog color or black if using additive blend mode
-       SHADERPERMUTATION_CUBEFILTER = 1<<5, ///< (lightsource) use cubemap light filter
-       SHADERPERMUTATION_GLOW = 1<<6, ///< (lightmap) blend in an additive glow texture
-       SHADERPERMUTATION_SPECULAR = 1<<7, ///< (lightsource or deluxemapping) render specular effects
-       SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
-       SHADERPERMUTATION_REFLECTION = 1<<9, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
-       SHADERPERMUTATION_OFFSETMAPPING = 1<<10, ///< adjust texcoords to roughly simulate a displacement mapped surface
-       SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
-       SHADERPERMUTATION_GAMMARAMPS = 1<<12, ///< gamma (postprocessing only)
-       SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing
-       SHADERPERMUTATION_SATURATION = 1<<14, ///< user defined postprocessing
-       SHADERPERMUTATION_LIMIT = 1<<15, ///< size of permutations array
-       SHADERPERMUTATION_COUNT = 15 ///< size of shaderpermutationinfo array
+       SHADERPERMUTATION_SATURATION = 1<<2, ///< saturation (postprocessing only)
+       SHADERPERMUTATION_FOG = 1<<3, ///< tint the color by fog color or black if using additive blend mode
+       SHADERPERMUTATION_GAMMARAMPS = 1<<3, ///< gamma (postprocessing only)
+       SHADERPERMUTATION_CUBEFILTER = 1<<4, ///< (lightsource) use cubemap light filter
+       SHADERPERMUTATION_GLOW = 1<<5, ///< (lightmap) blend in an additive glow texture
+       SHADERPERMUTATION_BLOOM = 1<<5, ///< bloom (postprocessing only)
+       SHADERPERMUTATION_SPECULAR = 1<<6, ///< (lightsource or deluxemapping) render specular effects
+       SHADERPERMUTATION_POSTPROCESSING = 1<<6, ///< user defined postprocessing (postprocessing only)
+       SHADERPERMUTATION_EXACTSPECULARMATH = 1<<7, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
+       SHADERPERMUTATION_REFLECTION = 1<<8, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
+       SHADERPERMUTATION_OFFSETMAPPING = 1<<9, ///< adjust texcoords to roughly simulate a displacement mapped surface
+       SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
+       SHADERPERMUTATION_SHADOWMAPRECT = 1<<11, ///< (lightsource) use shadowmap rectangle texture as light filter
+       SHADERPERMUTATION_SHADOWMAPPCF = 1<<12, //< (lightsource) use percentage closer filtering on shadowmap test results
+       SHADERPERMUTATION_SHADOWSAMPLER = 1<<13, //< (lightsource) use hardware shadowmap test
+       SHADERPERMUTATION_LIMIT = 1<<14, ///< size of permutations array
+       SHADERPERMUTATION_COUNT = 14 ///< size of shaderpermutationinfo array
 }
 shaderpermutation_t;
 
 }
 shaderpermutation_t;
 
@@ -1153,20 +1417,19 @@ shaderpermutation_t;
 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
 {
        {"#define USEDIFFUSE\n", " diffuse"},
 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
 {
        {"#define USEDIFFUSE\n", " diffuse"},
-       {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
-       {"#define USECOLORMAPPING\n", " colormapping"},
-       {"#define USECONTRASTBOOST\n", " contrastboost"},
-       {"#define USEFOG\n", " fog"},
+       {"#define USEVERTEXTEXTUREBLEND\n#define USEVIEWTINT\n", " vertextextureblend/tint"},
+       {"#define USECOLORMAPPING\n#define USESATURATION\n", " colormapping/saturation"},
+       {"#define USEFOG\n#define USEGAMMARAMPS\n", " fog/gammaramps"},
        {"#define USECUBEFILTER\n", " cubefilter"},
        {"#define USECUBEFILTER\n", " cubefilter"},
-       {"#define USEGLOW\n", " glow"},
-       {"#define USESPECULAR\n", " specular"},
+       {"#define USEGLOW\n#define USEBLOOM\n", " glow/bloom"},
+       {"#define USESPECULAR\n#define USEPOSTPROCESSING", " specular/postprocessing"},
        {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
        {"#define USEREFLECTION\n", " reflection"},
        {"#define USEOFFSETMAPPING\n", " offsetmapping"},
        {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
        {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
        {"#define USEREFLECTION\n", " reflection"},
        {"#define USEOFFSETMAPPING\n", " offsetmapping"},
        {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
-       {"#define USEGAMMARAMPS\n", " gammaramps"},
-       {"#define USEPOSTPROCESSING\n", " postprocessing"},
-       {"#define USESATURATION\n", " saturation"},
+       {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
+       {"#define USESHADOWMAPPCF\n", " shadowmappcf"},
+       {"#define USESHADOWSAMPLER\n", " shadowsampler"},
 };
 
 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
 };
 
 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
@@ -1184,6 +1447,7 @@ typedef enum shadermode_e
        SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
        SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
        SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
        SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
        SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
        SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
+       SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
        SHADERMODE_COUNT
 }
 shadermode_t;
        SHADERMODE_COUNT
 }
 shadermode_t;
@@ -1203,6 +1467,7 @@ shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
        {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
        {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
        {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
        {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
        {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
        {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
+       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
 };
 
 typedef struct r_glsl_permutation_s
 };
 
 typedef struct r_glsl_permutation_s
@@ -1232,6 +1497,8 @@ typedef struct r_glsl_permutation_s
        int loc_Texture_Cube;
        int loc_Texture_Refraction;
        int loc_Texture_Reflection;
        int loc_Texture_Cube;
        int loc_Texture_Refraction;
        int loc_Texture_Reflection;
+       int loc_Texture_ShadowMapRect;
+       int loc_Texture_CubeProjection;
        int loc_FogColor;
        int loc_LightPosition;
        int loc_EyePosition;
        int loc_FogColor;
        int loc_LightPosition;
        int loc_EyePosition;
@@ -1266,6 +1533,8 @@ typedef struct r_glsl_permutation_s
        int loc_ClientTime;
        int loc_PixelSize;
        int loc_Saturation;
        int loc_ClientTime;
        int loc_PixelSize;
        int loc_Saturation;
+       int loc_ShadowMap_TextureScale;
+       int loc_ShadowMap_Parameters;
 }
 r_glsl_permutation_t;
 
 }
 r_glsl_permutation_t;
 
@@ -1393,6 +1662,8 @@ static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutatio
                p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
                p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
                p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
                p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
                p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
                p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
+               p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
+               p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");  
                p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
                p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
                p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
                p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
                p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
                p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
@@ -1427,6 +1698,8 @@ static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutatio
                p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
                p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
                p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
                p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
                p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
                p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
+               p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
+               p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
                // 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);
                // 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);
@@ -1448,6 +1721,8 @@ static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutatio
                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_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_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
                CHECKGLERROR
                if (developer.integer)
                        Con_Printf("GLSL shader %s compiled.\n", permutationname);
                CHECKGLERROR
                if (developer.integer)
                        Con_Printf("GLSL shader %s compiled.\n", permutationname);
@@ -1486,13 +1761,13 @@ void R_GLSL_DumpShader_f(void)
                return;
        }
 
                return;
        }
 
-       FS_Print(file, "// The engine may define the following macros:\n");
-       FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
+       FS_Print(file, "/* The engine may define the following macros:\n");
+       FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
        for (i = 0;i < SHADERMODE_COUNT;i++)
        for (i = 0;i < SHADERMODE_COUNT;i++)
-               FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
+               FS_Print(file, shadermodeinfo[i].pretext);
        for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
        for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
-               FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
-       FS_Print(file, "\n");
+               FS_Print(file, shaderpermutationinfo[i].pretext);
+       FS_Print(file, "*/\n");
        FS_Print(file, builtinshaderstring);
        FS_Close(file);
 
        FS_Print(file, builtinshaderstring);
        FS_Close(file);
 
@@ -1588,9 +1863,28 @@ void R_SetupDepthOrShadowShader(void)
        }
 }
 
        }
 }
 
+void R_SetupShowDepthShader(void)
+{
+       if (gl_support_fragment_shader)
+       {
+               if (r_glsl.integer && r_glsl_usegeneric.integer)
+                       R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
+               else if (r_glsl_permutation)
+               {
+                       r_glsl_permutation = NULL;
+                       qglUseProgramObjectARB(0);CHECKGLERROR
+               }
+       }
+}
+
 extern rtexture_t *r_shadow_attenuationgradienttexture;
 extern rtexture_t *r_shadow_attenuation2dtexture;
 extern rtexture_t *r_shadow_attenuation3dtexture;
 extern rtexture_t *r_shadow_attenuationgradienttexture;
 extern rtexture_t *r_shadow_attenuation2dtexture;
 extern rtexture_t *r_shadow_attenuation3dtexture;
+extern float r_shadow_shadowmap_bias;
+extern float r_shadow_shadowmap_texturescale[4];
+extern float r_shadow_shadowmap_parameters[4];
+extern int r_shadow_shadowmode;
+extern int r_shadow_shadowmapfilter;
 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
 {
        // select a permutation of the lighting shader appropriate to this
 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
 {
        // select a permutation of the lighting shader appropriate to this
@@ -1630,8 +1924,14 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f
                        permutation |= SHADERPERMUTATION_FOG;
                if (rsurface.texture->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
                        permutation |= SHADERPERMUTATION_FOG;
                if (rsurface.texture->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
-               if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
-                       permutation |= SHADERPERMUTATION_CONTRASTBOOST;
+               if (r_shadow_shadowmode)
+                       permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+               if (r_shadow_shadowmapfilter == 3)
+                       permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+               else if (r_shadow_shadowmapfilter == 2)
+                       permutation |= SHADERPERMUTATION_SHADOWMAPPCF | SHADERPERMUTATION_SHADOWSAMPLER;
+               else if (r_shadow_shadowmapfilter == 1)
+                       permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
        }
        else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
        {
        }
        else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
        {
@@ -1651,8 +1951,6 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f
                        if (r_glsl_offsetmapping_reliefmapping.integer)
                                permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
                }
                        if (r_glsl_offsetmapping_reliefmapping.integer)
                                permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
                }
-               if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
-                       permutation |= SHADERPERMUTATION_CONTRASTBOOST;
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
                        permutation |= SHADERPERMUTATION_REFLECTION;
        }
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
                        permutation |= SHADERPERMUTATION_REFLECTION;
        }
@@ -1671,8 +1969,6 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f
                        permutation |= SHADERPERMUTATION_FOG;
                if (rsurface.texture->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
                        permutation |= SHADERPERMUTATION_FOG;
                if (rsurface.texture->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
-               if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
-                       permutation |= SHADERPERMUTATION_CONTRASTBOOST;
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
                        permutation |= SHADERPERMUTATION_REFLECTION;
        }
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
                        permutation |= SHADERPERMUTATION_REFLECTION;
        }
@@ -1688,8 +1984,6 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f
                        permutation |= SHADERPERMUTATION_FOG;
                if (rsurface.texture->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
                        permutation |= SHADERPERMUTATION_FOG;
                if (rsurface.texture->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
-               if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
-                       permutation |= SHADERPERMUTATION_CONTRASTBOOST;
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
                        permutation |= SHADERPERMUTATION_REFLECTION;
        }
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
                        permutation |= SHADERPERMUTATION_REFLECTION;
        }
@@ -1733,8 +2027,6 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f
                        permutation |= SHADERPERMUTATION_FOG;
                if (rsurface.texture->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
                        permutation |= SHADERPERMUTATION_FOG;
                if (rsurface.texture->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
-               if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
-                       permutation |= SHADERPERMUTATION_CONTRASTBOOST;
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
                        permutation |= SHADERPERMUTATION_REFLECTION;
        }
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
                        permutation |= SHADERPERMUTATION_REFLECTION;
        }
@@ -1763,6 +2055,8 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f
                // 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);
                // 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) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1], r_shadow_shadowmap_texturescale[2], r_shadow_shadowmap_texturescale[3]);
+               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]);
        }
        else
        {
        }
        else
        {
@@ -1797,19 +2091,7 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f
                if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
                if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
        }
                if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
                if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
        }
-       if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
-       {
-               // The formula used is actually:
-               //   color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
-               //   color.rgb *= SceneBrightness;
-               // simplified:
-               //   color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
-               // and do [[calculations]] here in the engine
-               qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
-               if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
-       }
-       else
-               if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
+       if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
        if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
        if (r_glsl_permutation->loc_Color_Pants >= 0)
        {
        if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
        if (r_glsl_permutation->loc_Color_Pants >= 0)
        {
@@ -2438,7 +2720,7 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_fullbright);
        Cvar_RegisterVariable(&r_shadows);
        Cvar_RegisterVariable(&r_shadows_darken);
        Cvar_RegisterVariable(&r_fullbright);
        Cvar_RegisterVariable(&r_shadows);
        Cvar_RegisterVariable(&r_shadows_darken);
-       Cvar_RegisterVariable(&r_shadows_drawafterrtlightning);
+       Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
        Cvar_RegisterVariable(&r_shadows_castfrombmodels);
        Cvar_RegisterVariable(&r_shadows_throwdistance);
        Cvar_RegisterVariable(&r_shadows_throwdirection);
        Cvar_RegisterVariable(&r_shadows_castfrombmodels);
        Cvar_RegisterVariable(&r_shadows_throwdistance);
        Cvar_RegisterVariable(&r_shadows_throwdirection);
@@ -2449,7 +2731,6 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_drawfog);
        Cvar_RegisterVariable(&r_textureunits);
        Cvar_RegisterVariable(&r_glsl);
        Cvar_RegisterVariable(&r_drawfog);
        Cvar_RegisterVariable(&r_textureunits);
        Cvar_RegisterVariable(&r_glsl);
-       Cvar_RegisterVariable(&r_glsl_contrastboost);
        Cvar_RegisterVariable(&r_glsl_deluxemapping);
        Cvar_RegisterVariable(&r_glsl_offsetmapping);
        Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
        Cvar_RegisterVariable(&r_glsl_deluxemapping);
        Cvar_RegisterVariable(&r_glsl_offsetmapping);
        Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
@@ -3086,10 +3367,10 @@ static void R_View_SetFrustum(void)
                VectorNormalize(r_refdef.view.frustum[3].normal);
 
                // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
                VectorNormalize(r_refdef.view.frustum[3].normal);
 
                // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
-               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
-               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
-               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[2]);
-               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[3]);
+               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
+               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
+               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
+               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
 
                r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
                r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
 
                r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
                r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
@@ -3161,15 +3442,8 @@ void R_View_Update(void)
 
 void R_SetupView(qboolean allowwaterclippingplane)
 {
 
 void R_SetupView(qboolean allowwaterclippingplane)
 {
-       if (!r_refdef.view.useperspective)
-               GL_SetupView_Mode_Ortho(-r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
-       else if (gl_stencil && r_useinfinitefarclip.integer)
-               GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
-       else
-               GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
-
-       GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
-
+       const double *customclipplane = NULL;
+       double plane[4];
        if (r_refdef.view.useclipplane && allowwaterclippingplane)
        {
                // LordHavoc: couldn't figure out how to make this approach the
        if (r_refdef.view.useclipplane && allowwaterclippingplane)
        {
                // LordHavoc: couldn't figure out how to make this approach the
@@ -3177,18 +3451,31 @@ void R_SetupView(qboolean allowwaterclippingplane)
                vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
                if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
                        dist = r_refdef.view.clipplane.dist;
                vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
                if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
                        dist = r_refdef.view.clipplane.dist;
-               GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
+               plane[0] = r_refdef.view.clipplane.normal[0];
+               plane[1] = r_refdef.view.clipplane.normal[1];
+               plane[2] = r_refdef.view.clipplane.normal[2];
+               plane[3] = dist;
+               customclipplane = plane;
        }
        }
+
+       if (!r_refdef.view.useperspective)
+               R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
+       else if (gl_stencil && r_useinfinitefarclip.integer)
+               R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
+       else
+               R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
+       R_SetViewport(&r_refdef.view.viewport);
 }
 
 void R_ResetViewRendering2D(void)
 {
 }
 
 void R_ResetViewRendering2D(void)
 {
+       r_viewport_t viewport;
        DrawQ_Finish();
 
        // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
        DrawQ_Finish();
 
        // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
-       qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
-       GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
-       GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
+       R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
+       R_SetViewport(&viewport);
+       GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
        GL_Color(1, 1, 1, 1);
        GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
        GL_BlendFunc(GL_ONE, GL_ZERO);
        GL_Color(1, 1, 1, 1);
        GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
        GL_BlendFunc(GL_ONE, GL_ZERO);
@@ -3214,10 +3501,8 @@ void R_ResetViewRendering3D(void)
 {
        DrawQ_Finish();
 
 {
        DrawQ_Finish();
 
-       // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
-       qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
        R_SetupView(true);
        R_SetupView(true);
-       GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
+       GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
        GL_Color(1, 1, 1, 1);
        GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
        GL_BlendFunc(GL_ONE, GL_ZERO);
        GL_Color(1, 1, 1, 1);
        GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
        GL_BlendFunc(GL_ONE, GL_ZERO);
@@ -3250,8 +3535,8 @@ static void R_Water_StartFrame(void)
 
        // set waterwidth and waterheight to the water resolution that will be
        // used (often less than the screen resolution for faster rendering)
 
        // set waterwidth and waterheight to the water resolution that will be
        // used (often less than the screen resolution for faster rendering)
-       waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
-       waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
+       waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
+       waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
 
        // calculate desired texture sizes
        // can't use water if the card does not support the texture size
 
        // calculate desired texture sizes
        // can't use water if the card does not support the texture size
@@ -3288,6 +3573,10 @@ static void R_Water_StartFrame(void)
                r_waterstate.textureheight = textureheight;
        }
 
                r_waterstate.textureheight = textureheight;
        }
 
+       // when doing a reduced render (HDR) we want to use a smaller area
+       waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
+       waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
+
        if (r_waterstate.waterwidth)
        {
                r_waterstate.enabled = true;
        if (r_waterstate.waterwidth)
        {
                r_waterstate.enabled = true;
@@ -3427,7 +3716,7 @@ static void R_Water_ProcessPlanes(void)
                        R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
                        GL_ActiveTexture(0);
                        CHECKGLERROR
                        R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
                        GL_ActiveTexture(0);
                        CHECKGLERROR
-                       qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
+                       qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
                }
 
                if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
                }
 
                if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
@@ -3458,7 +3747,7 @@ static void R_Water_ProcessPlanes(void)
                        R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
                        GL_ActiveTexture(0);
                        CHECKGLERROR
                        R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
                        GL_ActiveTexture(0);
                        CHECKGLERROR
-                       qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
+                       qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
                }
        }
        r_waterstate.renderingscene = false;
                }
        }
        r_waterstate.renderingscene = false;
@@ -3481,11 +3770,11 @@ void R_Bloom_StartFrame(void)
 
        // set bloomwidth and bloomheight to the bloom resolution that will be
        // used (often less than the screen resolution for faster rendering)
 
        // set bloomwidth and bloomheight to the bloom resolution that will be
        // used (often less than the screen resolution for faster rendering)
-       r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
-       r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
-       r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
-       r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
-       r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
+       r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
+       r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
+       r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
+       r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
+       r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
 
        // calculate desired texture sizes
        if (gl_support_arb_texture_non_power_of_two)
 
        // calculate desired texture sizes
        if (gl_support_arb_texture_non_power_of_two)
@@ -3538,6 +3827,13 @@ void R_Bloom_StartFrame(void)
                        r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
        }
 
                        r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
        }
 
+       // when doing a reduced render (HDR) we want to use a smaller area
+       r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
+       r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
+       r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
+       r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
+       r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
+
        // set up a texcoord array for the full resolution screen image
        // (we have to keep this around to copy back during final render)
        r_bloomstate.screentexcoord2f[0] = 0;
        // set up a texcoord array for the full resolution screen image
        // (we have to keep this around to copy back during final render)
        r_bloomstate.screentexcoord2f[0] = 0;
@@ -3565,6 +3861,8 @@ void R_Bloom_StartFrame(void)
                r_bloomstate.enabled = true;
                r_bloomstate.hdr = r_hdr.integer != 0;
        }
                r_bloomstate.enabled = true;
                r_bloomstate.hdr = r_hdr.integer != 0;
        }
+
+       R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
 }
 
 void R_Bloom_CopyBloomTexture(float colorscale)
 }
 
 void R_Bloom_CopyBloomTexture(float colorscale)
@@ -3573,7 +3871,7 @@ void R_Bloom_CopyBloomTexture(float colorscale)
 
        // scale down screen texture to the bloom texture size
        CHECKGLERROR
 
        // scale down screen texture to the bloom texture size
        CHECKGLERROR
-       qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
+       R_SetViewport(&r_bloomstate.viewport);
        GL_BlendFunc(GL_ONE, GL_ZERO);
        GL_Color(colorscale, colorscale, colorscale, 1);
        // TODO: optimize with multitexture or GLSL
        GL_BlendFunc(GL_ONE, GL_ZERO);
        GL_Color(colorscale, colorscale, colorscale, 1);
        // TODO: optimize with multitexture or GLSL
@@ -3588,8 +3886,8 @@ void R_Bloom_CopyBloomTexture(float colorscale)
        R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
        GL_ActiveTexture(0);
        CHECKGLERROR
        R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
        GL_ActiveTexture(0);
        CHECKGLERROR
-       qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
-       r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+       qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
+       r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
 }
 
 void R_Bloom_CopyHDRTexture(void)
 }
 
 void R_Bloom_CopyHDRTexture(void)
@@ -3597,8 +3895,8 @@ void R_Bloom_CopyHDRTexture(void)
        R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
        GL_ActiveTexture(0);
        CHECKGLERROR
        R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
        GL_ActiveTexture(0);
        CHECKGLERROR
-       qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
-       r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
+       qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
+       r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
 }
 
 void R_Bloom_MakeTexture(void)
 }
 
 void R_Bloom_MakeTexture(void)
@@ -3615,7 +3913,7 @@ void R_Bloom_MakeTexture(void)
 
        // we have a bloom image in the framebuffer
        CHECKGLERROR
 
        // we have a bloom image in the framebuffer
        CHECKGLERROR
-       qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
+       R_SetViewport(&r_bloomstate.viewport);
 
        for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
        {
 
        for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
        {
@@ -3631,8 +3929,8 @@ void R_Bloom_MakeTexture(void)
                // copy the vertically blurred bloom view to a texture
                GL_ActiveTexture(0);
                CHECKGLERROR
                // copy the vertically blurred bloom view to a texture
                GL_ActiveTexture(0);
                CHECKGLERROR
-               qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
-               r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+               qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
+               r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
        }
 
        range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
        }
 
        range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
@@ -3677,8 +3975,8 @@ void R_Bloom_MakeTexture(void)
                // copy the vertically blurred bloom view to a texture
                GL_ActiveTexture(0);
                CHECKGLERROR
                // copy the vertically blurred bloom view to a texture
                GL_ActiveTexture(0);
                CHECKGLERROR
-               qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
-               r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+               qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
+               r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
        }
 
        // apply subtract last
        }
 
        // apply subtract last
@@ -3705,8 +4003,8 @@ void R_Bloom_MakeTexture(void)
                R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
                GL_ActiveTexture(0);
                CHECKGLERROR
                R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
                GL_ActiveTexture(0);
                CHECKGLERROR
-               qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
-               r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+               qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
+               r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
        }
 }
 
        }
 }
 
@@ -3738,8 +4036,9 @@ void R_HDR_RenderBloomTexture(void)
        if (r_timereport_active)
                R_TimeReport("visibility");
 
        if (r_timereport_active)
                R_TimeReport("visibility");
 
+       // only do secondary renders with HDR if r_hdr is 2 or higher
        r_waterstate.numwaterplanes = 0;
        r_waterstate.numwaterplanes = 0;
-       if (r_waterstate.enabled)
+       if (r_waterstate.enabled && r_hdr.integer >= 2)
                R_RenderWaterPlanes();
 
        r_refdef.view.showdebug = true;
                R_RenderWaterPlanes();
 
        r_refdef.view.showdebug = true;
@@ -3813,20 +4112,20 @@ static void R_BlendView(void)
                                R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
                                R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
                                R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
                                R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
                                R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
                                R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
-                               r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
+                               r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
                        }
                }
 
                // copy view into the screen texture
                        }
                }
 
                // copy view into the screen texture
-               qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
-               r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
+               qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
+               r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
        }
 
        if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
        {
                unsigned int permutation =
        }
 
        if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
        {
                unsigned int permutation =
-                         (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
-                       | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
+                         (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
+                       | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
                        | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
                        | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
                        | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
                        | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
                        | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
                        | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
@@ -3888,7 +4187,7 @@ static void R_BlendView(void)
                if (r_glsl_permutation->loc_Saturation >= 0)
                        qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
                R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
                if (r_glsl_permutation->loc_Saturation >= 0)
                        qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
                R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
-               r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
+               r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
                return;
        }
 
                return;
        }
 
@@ -3908,7 +4207,7 @@ static void R_BlendView(void)
                R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
                R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
                R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
                R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
                R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
                R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
-               r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
+               r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
        }
        else if (r_bloomstate.texture_bloom)
        {
        }
        else if (r_bloomstate.texture_bloom)
        {
@@ -3937,14 +4236,14 @@ static void R_BlendView(void)
                {
                        R_SetupGenericShader(true);
                        R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
                {
                        R_SetupGenericShader(true);
                        R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
-                       r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
+                       r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
                        // now blend on the bloom texture
                        GL_BlendFunc(GL_ONE, GL_ONE);
                        R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
                        R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
                }
                R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
                        // now blend on the bloom texture
                        GL_BlendFunc(GL_ONE, GL_ONE);
                        R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
                        R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
                }
                R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
-               r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
+               r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
        }
        if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
        {
        }
        if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
        {
@@ -3972,13 +4271,6 @@ void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as t
                {
                        vec3_t fogvec;
                        VectorCopy(r_refdef.fogcolor, fogvec);
                {
                        vec3_t fogvec;
                        VectorCopy(r_refdef.fogcolor, fogvec);
-                       if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
-                       {
-                               //   color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
-                               fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
-                               fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
-                               fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
-                       }
                        //   color.rgb *= ContrastBoost * SceneBrightness;
                        VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
                        r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
                        //   color.rgb *= ContrastBoost * SceneBrightness;
                        VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
                        r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
@@ -4148,6 +4440,8 @@ R_RenderView
 */
 void R_RenderView(void)
 {
 */
 void R_RenderView(void)
 {
+       if (r_timereport_active)
+               R_TimeReport("start");
        r_frame++; // used only by R_GetCurrentTexture
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
 
        r_frame++; // used only by R_GetCurrentTexture
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
 
@@ -4326,7 +4620,7 @@ void R_RenderScene(void)
        if (r_refdef.scene.extraupdate)
                S_ExtraUpdate ();
 
        if (r_refdef.scene.extraupdate)
                S_ExtraUpdate ();
 
-       if (r_shadows.integer > 0 && !r_shadows_drawafterrtlightning.integer && r_refdef.lightmapintensity > 0)
+       if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
        {
                R_DrawModelShadows();
                R_ResetViewRendering3D();
        {
                R_DrawModelShadows();
                R_ResetViewRendering3D();
@@ -4343,7 +4637,7 @@ void R_RenderScene(void)
        if (r_refdef.scene.extraupdate)
                S_ExtraUpdate ();
 
        if (r_refdef.scene.extraupdate)
                S_ExtraUpdate ();
 
-       if (r_shadows.integer > 0 && r_shadows_drawafterrtlightning.integer && r_refdef.lightmapintensity > 0)
+       if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
        {
                R_DrawModelShadows();
                R_ResetViewRendering3D();
        {
                R_DrawModelShadows();
                R_ResetViewRendering3D();