]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rmain.c
attempt to fix white flicker when r_water is toggled
[xonotic/darkplaces.git] / gl_rmain.c
index e88b31efbaced40464eb4d6d1d82b30f8ea705e4..aab6fd6bdae9e736ebca7946ca3ec6ac7cec938a 100644 (file)
@@ -29,11 +29,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 mempool_t *r_main_mempool;
 rtexturepool_t *r_main_texturepool;
 
-static int r_frame = 0; ///< used only by R_GetCurrentTexture
+static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
 
-qboolean r_loadnormalmap;
-qboolean r_loadgloss;
+static qboolean r_loadnormalmap;
+static qboolean r_loadgloss;
 qboolean r_loadfog;
+static qboolean r_loaddds;
+static qboolean r_savedds;
 
 //
 // screen size info
@@ -107,6 +109,9 @@ cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Ne
 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
 
+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_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"};
@@ -127,7 +132,7 @@ cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier"
 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
 
-cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
+cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
@@ -157,6 +162,9 @@ cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* s
 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
+cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
+cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
+
 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
 
 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
@@ -417,18 +425,18 @@ static void R_BuildFogTexture(void)
        for (x = 0;x < FOGMASKTABLEWIDTH;x++)
        {
                d = (x * r - r_refdef.fogmasktable_start);
-               if(developer.integer >= 100)
-                       Con_Printf("%f ", d);
+               if(developer_extra.integer)
+                       Con_DPrintf("%f ", d);
                d = max(0, d);
                if (r_fog_exp2.integer)
                        alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
                else
                        alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
-               if(developer.integer >= 100)
-                       Con_Printf(" : %f ", alpha);
+               if(developer_extra.integer)
+                       Con_DPrintf(" : %f ", alpha);
                alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
-               if(developer.integer >= 100)
-                       Con_Printf(" = %f\n", alpha);
+               if(developer_extra.integer)
+                       Con_DPrintf(" = %f\n", alpha);
                r_refdef.fogmasktable[x] = bound(0, alpha, 1);
        }
 
@@ -494,9 +502,9 @@ static const char *builtinshaderstring =
 "# extension GL_EXT_gpu_shader4 : enable\n"
 "#endif\n"
 "\n"
-"#ifdef USESHADOWSAMPLER\n"
-"# extension GL_ARB_shadow : enable\n"
-"#endif\n"
+"//#ifdef USESHADOWSAMPLER\n"
+"//# extension GL_ARB_shadow : enable\n"
+"//#endif\n"
 "\n"
 "//#ifdef __GLSL_CG_DATA_TYPES\n"
 "//# define myhalf half\n"
@@ -835,10 +843,7 @@ static const char *builtinshaderstring =
 "varying vec3 CubeVector;\n"
 "#endif\n"
 "\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"varying vec3 LightVector;\n"
-"#endif\n"
-"#if defined(MODE_LIGHTDIRECTION)\n"
+"#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
 "varying vec3 LightVector;\n"
 "#endif\n"
 "\n"
@@ -917,12 +922,12 @@ static const char *builtinshaderstring =
 "#endif\n"
 "\n"
 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
-"uniform sampler2DRect Texture_ScreenDepth;\n"
-"uniform sampler2DRect Texture_ScreenNormalMap;\n"
+"uniform sampler2D Texture_ScreenDepth;\n"
+"uniform sampler2D Texture_ScreenNormalMap;\n"
 "#endif\n"
 "#ifdef USEDEFERREDLIGHTMAP\n"
-"uniform sampler2DRect Texture_ScreenDiffuse;\n"
-"uniform sampler2DRect Texture_ScreenSpecular;\n"
+"uniform sampler2D Texture_ScreenDiffuse;\n"
+"uniform sampler2D Texture_ScreenSpecular;\n"
 "#endif\n"
 "\n"
 "uniform myhalf3 Color_Pants;\n"
@@ -1158,9 +1163,9 @@ static const char *builtinshaderstring =
 "#    ifdef USESHADOWMAPPCF\n"
 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
 "#      ifdef GL_ARB_texture_gather\n"
-"#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
+"#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
 "#      else\n"
-"#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
+"#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
 "#      endif\n"
 "      vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
 "      center *= ShadowMap_TextureScale;\n"
@@ -1308,14 +1313,16 @@ static const char *builtinshaderstring =
 "uniform myhalf3 DeferredColor_Specular;\n"
 "uniform myhalf SpecularPower;\n"
 "#endif\n"
+"uniform myhalf2 PixelToScreenTexCoord;\n"
 "void main(void)\n"
 "{\n"
 "      // calculate viewspace pixel position\n"
+"      vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
 "      vec3 position;\n"
-"      position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
+"      position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
 "      position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
 "      // decode viewspace pixel normal\n"
-"      myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
+"      myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
 "      myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
 "      // surfacenormal = pixel normal in viewspace\n"
 "      // LightVector = pixel to light in viewspace\n"
@@ -1356,8 +1363,8 @@ static const char *builtinshaderstring =
 "\n"
 "# ifdef USECUBEFILTER\n"
 "      vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
-"      gl_FragData[0] *= cubecolor;\n"
-"      gl_FragData[1] *= cubecolor;\n"
+"      gl_FragData[0].rgb *= cubecolor;\n"
+"      gl_FragData[1].rgb *= cubecolor;\n"
 "# endif\n"
 "}\n"
 "#endif // FRAGMENT_SHADER\n"
@@ -1443,6 +1450,7 @@ static const char *builtinshaderstring =
 "\n"
 "#ifdef FRAGMENT_SHADER\n"
 "#ifdef USEDEFERREDLIGHTMAP\n"
+"uniform myhalf2 PixelToScreenTexCoord;\n"
 "uniform myhalf3 DeferredMod_Diffuse;\n"
 "uniform myhalf3 DeferredMod_Specular;\n"
 "#endif\n"
@@ -1515,6 +1523,7 @@ static const char *builtinshaderstring =
 "\n"
 "#ifdef MODE_LIGHTSOURCE\n"
 "      // light source\n"
+"#ifdef USEDIFFUSE\n"
 "      myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
 "      myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
 "      color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
@@ -1527,6 +1536,9 @@ static const char *builtinshaderstring =
 "#endif\n"
 "      color.rgb += glosstex * (specular * Color_Specular);\n"
 "#endif\n"
+"#else\n"
+"      color.rgb = diffusetex * Color_Ambient;\n"
+"#endif\n"
 "      color.rgb *= LightColor;\n"
 "      color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
@@ -1542,7 +1554,9 @@ static const char *builtinshaderstring =
 "\n"
 "#ifdef MODE_LIGHTDIRECTION\n"
 "#define SHADING\n"
+"#ifdef USEDIFFUSE\n"
 "      myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
+"#endif\n"
 "#define lightcolor LightColor\n"
 "#endif // MODE_LIGHTDIRECTION\n"
 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
@@ -1609,8 +1623,9 @@ static const char *builtinshaderstring =
 "#endif\n"
 "\n"
 "#ifdef USEDEFERREDLIGHTMAP\n"
-"      color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
-"      color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
+"      vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
+"      color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
+"      color.rgb += glosstex * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
 "#endif\n"
 "\n"
 "#ifdef USEGLOW\n"
@@ -1807,7 +1822,7 @@ const char *builtincgshaderstring =
 "      gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
 "#endif\n"
 "#ifdef USEVIEWTINT\n"
-"      gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
+"      gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
 "#endif\n"
 "\n"
 "#ifdef USEPOSTPROCESSING\n"
@@ -1825,7 +1840,7 @@ const char *builtincgshaderstring =
 "      //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
 "      float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
 "      //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
-"      gl_FragColor.rgb = mix(float3(y), gl_FragColor.rgb, Saturation);\n"
+"      gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
 "#endif\n"
 "\n"
 "#ifdef USEGAMMARAMPS\n"
@@ -1896,7 +1911,7 @@ const char *builtincgshaderstring =
 "      gl_FragColor += tex2;\n"
 "# endif\n"
 "# ifdef USEVERTEXTEXTUREBLEND\n"
-"      gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
+"      gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
 "# endif\n"
 "#endif\n"
 "}\n"
@@ -1952,7 +1967,7 @@ const char *builtincgshaderstring =
 "float4 gl_Vertex : POSITION,\n"
 "uniform float4x4 ModelViewProjectionMatrix,\n"
 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
-"uniform mat4 TexMatrix,\n"
+"uniform float4x4 TexMatrix,\n"
 "uniform float3 EyePosition,\n"
 "out float4 gl_Position : POSITION,\n"
 "out float2 TexCoord : TEXCOORD0,\n"
@@ -1995,7 +2010,7 @@ const char *builtincgshaderstring =
 "      f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
 "      f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
 "      f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
-"      ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
+"      ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
 "      gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
 "}\n"
 "#endif\n"
@@ -2012,7 +2027,7 @@ const char *builtincgshaderstring =
 "float4 gl_Vertex : POSITION,\n"
 "uniform float4x4 ModelViewProjectionMatrix,\n"
 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
-"uniform mat4 TexMatrix,\n"
+"uniform float4x4 TexMatrix,\n"
 "uniform float3 EyePosition,\n"
 "out float4 gl_Position : POSITION,\n"
 "out float2 TexCoord : TEXCOORD0,\n"
@@ -2062,14 +2077,14 @@ const char *builtincgshaderstring =
 "      f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
 "      f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
 "      f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
-"      ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
+"      ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
 "      f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
 "      f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
 "      f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
 "      f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
-"      ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
+"      ScreenTexCoord.zw = lerp(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(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
+"      gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
 "}\n"
 "#endif\n"
 "#else // !MODE_WATER\n"
@@ -2155,13 +2170,13 @@ const char *builtincgshaderstring =
 "              {\n"
 "                      ma = adir.x;\n"
 "                      tc = dir.zy;\n"
-"                      offset = float2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
+"                      offset = float2(lerp(0.5, 1.5, dir.x < 0.0), 0.5);\n"
 "              }\n"
 "              else // Z\n"
 "              {\n"
 "                      ma = adir.z;\n"
 "                      tc = dir.xy;\n"
-"                      offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
+"                      offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
 "              }\n"
 "      }\n"
 "      else\n"
@@ -2170,13 +2185,13 @@ const char *builtincgshaderstring =
 "              {\n"
 "                      ma = adir.y;\n"
 "                      tc = dir.xz;\n"
-"                      offset = float2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
+"                      offset = float2(lerp(0.5, 1.5, dir.y < 0.0), 1.5);\n"
 "              }\n"
 "              else // Z\n"
 "              {\n"
 "                      ma = adir.z;\n"
 "                      tc = dir.xy;\n"
-"                      offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
+"                      offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
 "              }\n"
 "      }\n"
 "\n"
@@ -2191,7 +2206,7 @@ const char *builtincgshaderstring =
 "      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(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\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"
@@ -2234,21 +2249,21 @@ const char *builtincgshaderstring =
 "#    ifdef USESHADOWMAPPCF\n"
 "#      if USESHADOWMAPPCF > 1\n"
 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
-"    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
+"    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
-"    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
-"    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
+"    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
+"    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
 "#      else\n"
 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
-"    float2 offset = fract(shadowmaptc.xy);\n"
+"    float2 offset = frac(shadowmaptc.xy);\n"
 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
-"    float3 cols = row2 + mix(row1, row3, offset.y);\n"
-"    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
+"    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
+"    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
 "#      endif\n"
 "#    else\n"
 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
@@ -2289,37 +2304,33 @@ const char *builtincgshaderstring =
 "#      else\n"
 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
 "#      endif\n"
-"    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
+"    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
 "    center *= ShadowMap_TextureScale;\n"
 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
-"                mix(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
-"    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
+"                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
+"    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
 "#     else\n"
-"#      ifdef GL_EXT_gpu_shader4\n"
-"#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, ifloat2(x, y)).r\n"
-"#      else\n"
-"#        define texval(x, y) tex2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
-"#      endif\n"
+"#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
 "#      if USESHADOWMAPPCF > 1\n"
-"    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
+"    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
 "    center *= ShadowMap_TextureScale;\n"
 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
-"    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
-"    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
+"    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
+"    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
 "#      else\n"
-"    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
+"    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
-"    float3 cols = row2 + mix(row1, row3, offset.y);\n"
-"    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
+"    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
+"    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
 "#      endif\n"
 "#     endif\n"
 "#    else\n"
@@ -2363,14 +2374,20 @@ const char *builtincgshaderstring =
 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
-"uniform mat4 TexMatrix,\n"
+"uniform float4x4 TexMatrix,\n"
 "#ifdef USEVERTEXTEXTUREBLEND\n"
-"uniform mat4 BackgroundTexMatrix,\n"
+"uniform float4x4 BackgroundTexMatrix,\n"
+"#endif\n"
+"uniform float4x4 ModelViewMatrix,\n"
+"#ifdef USEOFFSETMAPPING\n"
+"uniform float3 EyePosition,\n"
 "#endif\n"
-"uniform mat4 ModelViewMatrix,\n"
 "out float4 gl_Position : POSITION,\n"
 "out float4 gl_FrontColor : COLOR,\n"
 "out float4 TexCoordBoth : TEXCOORD0,\n"
+"#ifdef USEOFFSETMAPPING\n"
+"out float3 EyeVector : TEXCOORD2,\n"
+"#endif\n"
 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
@@ -2439,7 +2456,7 @@ const char *builtincgshaderstring =
 "#endif\n"
 "\n"
 "#ifdef USEVERTEXTEXTUREBLEND\n"
-"      float3 surfacenormal = mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
+"      float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
 "#else\n"
 "      float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
 "#endif\n"
@@ -2458,7 +2475,7 @@ const char *builtincgshaderstring =
 "(\n"
 "float4 gl_Vertex : POSITION,\n"
 "uniform float4x4 ModelViewProjectionMatrix,\n"
-"uniform mat4 ModelViewMatrix,\n"
+"uniform float4x4 ModelViewMatrix,\n"
 "out float4 gl_Position : POSITION,\n"
 "out float4 ModelViewPosition : TEXCOORD0\n"
 ")\n"
@@ -2473,9 +2490,10 @@ const char *builtincgshaderstring =
 "(\n"
 "float2 Pixel : WPOS,\n"
 "float4 ModelViewPosition : TEXCOORD0,\n"
-"uniform mat4 ViewToLight,\n"
+"uniform float4x4 ViewToLight,\n"
 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
 "uniform float3 LightPosition,\n"
+"uniform half2 PixelToScreenTexCoord,\n"
 "uniform half3 DeferredColor_Ambient,\n"
 "uniform half3 DeferredColor_Diffuse,\n"
 "#ifdef USESPECULAR\n"
@@ -2483,8 +2501,8 @@ const char *builtincgshaderstring =
 "uniform half SpecularPower,\n"
 "#endif\n"
 "uniform sampler2D Texture_Attenuation,\n"
-"uniform samplerRECT Texture_ScreenDepth,\n"
-"uniform samplerRECT Texture_ScreenNormalMap,\n"
+"uniform sampler2D Texture_ScreenDepth,\n"
+"uniform sampler2D Texture_ScreenNormalMap,\n"
 "\n"
 "#ifdef USESHADOWMAPRECT\n"
 "# ifdef USESHADOWSAMPLER\n"
@@ -2524,11 +2542,13 @@ const char *builtincgshaderstring =
 ")\n"
 "{\n"
 "      // calculate viewspace pixel position\n"
+"      float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
+"      ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
 "      float3 position;\n"
-"      position.z = ScreenToDepth.y / (texRECT(Texture_ScreenDepth, Pixel).r + ScreenToDepth.x);\n"
+"      position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
 "      position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
 "      // decode viewspace pixel normal\n"
-"      half4 normalmap = texRECT(Texture_ScreenNormalMap, Pixel);\n"
+"      half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
 "      half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
 "      // surfacenormal = pixel normal in viewspace\n"
 "      // LightVector = pixel to light in viewspace\n"
@@ -2583,8 +2603,8 @@ const char *builtincgshaderstring =
 "\n"
 "# ifdef USECUBEFILTER\n"
 "      float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
-"      gl_FragData0 *= cubecolor;\n"
-"      gl_FragData1 *= cubecolor;\n"
+"      gl_FragData0.rgb *= cubecolor;\n"
+"      gl_FragData1.rgb *= cubecolor;\n"
 "# endif\n"
 "}\n"
 "#endif // FRAGMENT_SHADER\n"
@@ -2608,12 +2628,12 @@ const char *builtincgshaderstring =
 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
 "\n"
 "uniform float3 EyePosition,\n"
-"uniform mat4 TexMatrix,\n"
+"uniform float4x4 TexMatrix,\n"
 "#ifdef USEVERTEXTEXTUREBLEND\n"
-"uniform mat4 BackgroundTexMatrix,\n"
+"uniform float4x4 BackgroundTexMatrix,\n"
 "#endif\n"
 "#ifdef MODE_LIGHTSOURCE\n"
-"uniform mat4 ModelToLight,\n"
+"uniform float4x4 ModelToLight,\n"
 "#endif\n"
 "#ifdef MODE_LIGHTSOURCE\n"
 "uniform float3 LightPosition,\n"
@@ -2789,13 +2809,13 @@ const char *builtincgshaderstring =
 "uniform sampler2D Texture_Reflection,\n"
 "#endif\n"
 "\n"
-"//#ifdef MODE_DEFERREDLIGHTSOURCE\n"
-"uniform samplerRECT Texture_ScreenDepth,\n"
-"uniform samplerRECT Texture_ScreenNormalMap,\n"
-"//#endif\n"
+"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
+"uniform sampler2D Texture_ScreenDepth,\n"
+"uniform sampler2D Texture_ScreenNormalMap,\n"
+"#endif\n"
 "#ifdef USEDEFERREDLIGHTMAP\n"
-"uniform samplerRECT Texture_ScreenDiffuse,\n"
-"uniform samplerRECT Texture_ScreenSpecular,\n"
+"uniform sampler2D Texture_ScreenDiffuse,\n"
+"uniform sampler2D Texture_ScreenSpecular,\n"
 "#endif\n"
 "\n"
 "#ifdef USECOLORMAPPING\n"
@@ -2814,6 +2834,7 @@ const char *builtincgshaderstring =
 "#endif\n"
 "\n"
 "#ifdef USEDEFERREDLIGHTMAP\n"
+"uniform half2 PixelToScreenTexCoord,\n"
 "uniform half3 DeferredMod_Diffuse,\n"
 "uniform half3 DeferredMod_Specular,\n"
 "#endif\n"
@@ -2903,14 +2924,14 @@ const char *builtincgshaderstring =
 "      float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
 "      //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
 "      //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
-"      color.rgb = half3(mix(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
+"      color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
 "      color.a = 1.0;\n"
-"      //color = mix(half4(1, 0, 0, 1), color, terrainblend);\n"
+"      //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
 "#endif\n"
 "\n"
 "      // get the surface normal\n"
 "#ifdef USEVERTEXTEXTUREBLEND\n"
-"      half3 surfacenormal = normalize(half3(mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
+"      half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
 "#else\n"
 "      half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
 "#endif\n"
@@ -2919,7 +2940,7 @@ const char *builtincgshaderstring =
 "      half3 diffusetex = color.rgb;\n"
 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
 "# ifdef USEVERTEXTEXTUREBLEND\n"
-"      half3 glosstex = half3(mix(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
+"      half3 glosstex = half3(lerp(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
 "# else\n"
 "      half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
 "# endif\n"
@@ -2930,6 +2951,7 @@ const char *builtincgshaderstring =
 "\n"
 "#ifdef MODE_LIGHTSOURCE\n"
 "      // light source\n"
+"#ifdef USEDIFFUSE\n"
 "      half3 lightnormal = half3(normalize(LightVector));\n"
 "      half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
 "      color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
@@ -2942,6 +2964,9 @@ const char *builtincgshaderstring =
 "#endif\n"
 "      color.rgb += glosstex * (specular * Color_Specular);\n"
 "#endif\n"
+"#else\n"
+"      color.rgb = diffusetex * Color_Ambient;\n"
+"#endif\n"
 "      color.rgb *= LightColor;\n"
 "      color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
@@ -2972,7 +2997,9 @@ const char *builtincgshaderstring =
 "\n"
 "#ifdef MODE_LIGHTDIRECTION\n"
 "#define SHADING\n"
+"#ifdef USEDIFFUSE\n"
 "      half3 lightnormal = half3(normalize(LightVector));\n"
+"#endif\n"
 "#define lightcolor LightColor\n"
 "#endif // MODE_LIGHTDIRECTION\n"
 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
@@ -3039,14 +3066,14 @@ const char *builtincgshaderstring =
 "#endif\n"
 "\n"
 "#ifdef USEDEFERREDLIGHTMAP\n"
-"      color.rgb += diffusetex * half3(texRECT(Texture_ScreenDiffuse, Pixel)) * DeferredMod_Diffuse;\n"
-"      color.rgb += glosstex * half3(texRECT(Texture_ScreenSpecular, Pixel)) * DeferredMod_Specular;\n"
-"      color.rgb = half3(texRECT(Texture_ScreenDepth, Pixel));\n"
+"      float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
+"      color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
+"      color.rgb += glosstex * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
 "#endif\n"
 "\n"
 "#ifdef USEGLOW\n"
 "#ifdef USEVERTEXTEXTUREBLEND\n"
-"      color.rgb += mix(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
+"      color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
 "#else\n"
 "      color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
 "#endif\n"
@@ -3054,9 +3081,9 @@ const char *builtincgshaderstring =
 "\n"
 "#ifdef USEFOG\n"
 "#ifdef MODE_LIGHTSOURCE\n"
-"      color.rgb *= half(FogVertex());\n"
+"      color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
 "#else\n"
-"      color.rgb = mix(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
+"      color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
 "#endif\n"
 "#endif\n"
 "\n"
@@ -3075,8 +3102,8 @@ const char *builtincgshaderstring =
 "      f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
 "      f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
 "      f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
-"      ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
-"      color.rgb = mix(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
+"      ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
+"      color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
 "#endif\n"
 "\n"
 "      gl_FragColor = float4(color);\n"
@@ -3142,7 +3169,7 @@ typedef enum shaderpermutation_e
        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_LIMIT = 1<<26, ///< size of permutations array
-       SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
+       SHADERPERMUTATION_COUNT = 26 ///< size of shaderpermutationinfo array
 }
 shaderpermutation_t;
 
@@ -3329,6 +3356,7 @@ typedef struct r_glsl_permutation_s
        int loc_BackgroundTexMatrix;
        int loc_ModelViewProjectionMatrix;
        int loc_ModelViewMatrix;
+       int loc_PixelToScreenTexCoord;
 }
 r_glsl_permutation_t;
 
@@ -3541,6 +3569,7 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode
                p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
                p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
                p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
+               p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
                // 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);
@@ -3571,8 +3600,7 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode
                if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
                if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
                CHECKGLERROR
-               if (developer.integer)
-                       Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
+               Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
        }
        else
                Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
@@ -3626,6 +3654,7 @@ void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutatio
                qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
        }
        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);
 }
 
 #ifdef SUPPORTCG
@@ -3725,6 +3754,7 @@ typedef struct r_cg_permutation_s
        CGparameter fp_UserVec4;
        CGparameter fp_ViewTintColor;
        CGparameter fp_ViewToLight;
+       CGparameter fp_PixelToScreenTexCoord;
 }
 r_cg_permutation_t;
 
@@ -3889,9 +3919,10 @@ static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, un
        CHECKGLERROR
 
        // compile the vertex program
-       if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL)))
+       if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL)))
        {
                CHECKCGERROR
+#if 0
                cgCompileProgram(p->vprogram);CHECKCGERROR
                if (!cgIsProgramCompiled(p->vprogram))
                {
@@ -3900,6 +3931,7 @@ static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, un
                        p->vprogram = 0;
                }
                else
+#endif
                {
                        cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
                        cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
@@ -3920,8 +3952,9 @@ static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, un
        }
 
        // compile the fragment program
-       if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL)))
+       if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL)))
        {
+#if 0
                cgCompileProgram(p->fprogram);CHECKCGERROR
                if (!cgIsProgramCompiled(p->fprogram))
                {
@@ -3930,6 +3963,7 @@ static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, un
                        p->fprogram = 0;
                }
                else
+#endif
                {
                        cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
                        cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
@@ -4005,6 +4039,7 @@ static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, un
                        p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
                        p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
                        p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
+                       p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
                        CHECKCGERROR
                }
        }
@@ -4070,13 +4105,13 @@ void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
                CHECKCGERROR
                if (r_cg_permutation->vprogram)
                {
-                       //cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
+                       cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
                        cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
-                       //cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
+                       cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
                }
                else
                {
-                       //cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
+                       cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
                        cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
                }
                if (r_cg_permutation->fprogram)
@@ -4093,11 +4128,12 @@ 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
 }
 
-void CG_BindTexture(CGparameter param, int texnum)
+void CG_BindTexture(CGparameter param, rtexture_t *tex)
 {
-       cgGLSetTextureParameter(param, texnum);
+       cgGLSetTextureParameter(param, R_GetTexture(tex));
        cgGLEnableTextureParameter(param);
 }
 #endif
@@ -4110,6 +4146,7 @@ void R_GLSL_Restart_f(void)
        case RENDERPATH_GL20:
                {
                        r_glsl_permutation_t *p;
+                       r_glsl_permutation = NULL;
                        limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
                        for (i = 0;i < limit;i++)
                        {
@@ -4126,6 +4163,11 @@ void R_GLSL_Restart_f(void)
 #ifdef SUPPORTCG
                {
                        r_cg_permutation_t *p;
+                       r_cg_permutation = NULL;
+                       cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
+                       cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
+                       cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
+                       cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
                        limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
                        for (i = 0;i < limit;i++)
                        {
@@ -4138,8 +4180,8 @@ void R_GLSL_Restart_f(void)
                                        Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
                                }
                        }
+                       memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
                }
-               memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
                break;
 #endif
        case RENDERPATH_GL13:
@@ -4198,26 +4240,26 @@ void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemod
        {
        case RENDERPATH_GL20:
                R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
-               if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , R_GetTexture(first ));
-               if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, R_GetTexture(second));
+               if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
+               if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
                break;
        case RENDERPATH_CGGL:
 #ifdef SUPPORTCG
                CHECKCGERROR
                R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
-               if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , R_GetTexture(first ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, R_GetTexture(second));CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
 #endif
                break;
        case RENDERPATH_GL13:
-               R_Mesh_TexBind(0, R_GetTexture(first ));
+               R_Mesh_TexBind(0, first );
                R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
-               R_Mesh_TexBind(1, R_GetTexture(second));
+               R_Mesh_TexBind(1, second);
                if (second)
                        R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
                break;
        case RENDERPATH_GL11:
-               R_Mesh_TexBind(0, R_GetTexture(first ));
+               R_Mesh_TexBind(0, first );
                break;
        }
 }
@@ -4296,13 +4338,6 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
        unsigned int permutation = 0;
        unsigned int mode = 0;
        float m16f[16];
-       // TODO: implement geometry-shader based shadow volumes someday
-       if (r_glsl_offsetmapping.integer)
-       {
-               permutation |= SHADERPERMUTATION_OFFSETMAPPING;
-               if (r_glsl_offsetmapping_reliefmapping.integer)
-                       permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
-       }
        if (rsurfacepass == RSURFPASS_BACKGROUND)
        {
                // distorted background
@@ -4310,22 +4345,53 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        mode = SHADERMODE_WATER;
                else
                        mode = SHADERMODE_REFRACTION;
+               R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
+               R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
+               R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
+               R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
+               R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
+               R_Mesh_ColorPointer(NULL, 0, 0);
+               GL_AlphaTest(false);
+               GL_BlendFunc(GL_ONE, GL_ZERO);
        }
        else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
        {
+               if (r_glsl_offsetmapping.integer)
+               {
+                       permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+                       if (r_glsl_offsetmapping_reliefmapping.integer)
+                               permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+               }
+               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+                       permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
+               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
+                       permutation |= SHADERPERMUTATION_ALPHAKILL;
                // normalmap (deferred prepass), may use alpha test on diffuse
                mode = SHADERMODE_DEFERREDGEOMETRY;
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
                        permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
+               R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
+               R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
+               R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
+               R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
+               R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
+               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
+                       R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
+               else
+                       R_Mesh_ColorPointer(NULL, 0, 0);
+               GL_AlphaTest(false);
+               GL_BlendFunc(GL_ONE, GL_ZERO);
+       }
+       else if (rsurfacepass == RSURFPASS_RTLIGHT)
+       {
                if (r_glsl_offsetmapping.integer)
                {
                        permutation |= SHADERPERMUTATION_OFFSETMAPPING;
                        if (r_glsl_offsetmapping_reliefmapping.integer)
                                permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
                }
-       }
-       else if (rsurfacepass == RSURFPASS_RTLIGHT)
-       {
+               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+                       permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
                // light source
                mode = SHADERMODE_LIGHTSOURCE;
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
@@ -4335,7 +4401,11 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                if (diffusescale > 0)
                        permutation |= SHADERPERMUTATION_DIFFUSE;
                if (specularscale > 0)
+               {
                        permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
+                       if (r_shadow_glossexact.integer)
+                               permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
+               }
                if (r_refdef.fogenabled)
                        permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
                if (rsurface.texture->colormapping)
@@ -4358,40 +4428,90 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        else if (r_shadow_shadowmappcf)
                                permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
                }
+               R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
+               if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
+               {
+                       R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
+                       R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
+                       R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
+               }
+               else
+               {
+                       R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
+                       R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
+                       R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
+               }
+               //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
+               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
+                       R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
+               else
+                       R_Mesh_ColorPointer(NULL, 0, 0);
+               GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
        }
        else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
        {
+               if (r_glsl_offsetmapping.integer)
+               {
+                       permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+                       if (r_glsl_offsetmapping_reliefmapping.integer)
+                               permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+               }
+               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+                       permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
                // unshaded geometry (fullbright or ambient model lighting)
                mode = SHADERMODE_FLATCOLOR;
                ambientscale = diffusescale = specularscale = 0;
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
-                       permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
                if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
                        permutation |= SHADERPERMUTATION_GLOW;
                if (r_refdef.fogenabled)
                        permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
                if (rsurface.texture->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
+               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
+                       permutation |= SHADERPERMUTATION_REFLECTION;
+               R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
+               if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
+               {
+                       R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
+                       R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
+                       R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
+               }
+               else
+               {
+                       R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
+                       R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
+                       R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
+               }
+               R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
+               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
+                       R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
+               else
+                       R_Mesh_ColorPointer(NULL, 0, 0);
+               GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+               GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+       }
+       else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
+       {
                if (r_glsl_offsetmapping.integer)
                {
                        permutation |= SHADERPERMUTATION_OFFSETMAPPING;
                        if (r_glsl_offsetmapping_reliefmapping.integer)
                                permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
                }
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
-                       permutation |= SHADERPERMUTATION_REFLECTION;
-       }
-       else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
-       {
-               // directional model lighting
-               mode = SHADERMODE_LIGHTDIRECTION;
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
                        permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
+               // directional model lighting
+               mode = SHADERMODE_LIGHTDIRECTION;
                if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
                        permutation |= SHADERPERMUTATION_GLOW;
                permutation |= SHADERPERMUTATION_DIFFUSE;
                if (specularscale > 0)
+               {
                        permutation |= SHADERPERMUTATION_SPECULAR;
+                       if (r_shadow_glossexact.integer)
+                               permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
+               }
                if (r_refdef.fogenabled)
                        permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
                if (rsurface.texture->colormapping)
@@ -4400,13 +4520,36 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        permutation |= SHADERPERMUTATION_REFLECTION;
                if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
                        permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
+               R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
+               if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
+               {
+                       R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
+                       R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
+                       R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
+               }
+               else
+               {
+                       R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
+                       R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
+                       R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
+               }
+               R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
+               R_Mesh_ColorPointer(NULL, 0, 0);
+               GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+               GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
        }
        else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
        {
-               // ambient model lighting
-               mode = SHADERMODE_LIGHTDIRECTION;
+               if (r_glsl_offsetmapping.integer)
+               {
+                       permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+                       if (r_glsl_offsetmapping_reliefmapping.integer)
+                               permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+               }
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
                        permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
+               // ambient model lighting
+               mode = SHADERMODE_LIGHTDIRECTION;
                if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
                        permutation |= SHADERPERMUTATION_GLOW;
                if (r_refdef.fogenabled)
@@ -4417,10 +4560,45 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        permutation |= SHADERPERMUTATION_REFLECTION;
                if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
                        permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
+               R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
+               if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
+               {
+                       R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
+                       R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
+                       R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
+               }
+               else
+               {
+                       R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
+                       R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
+                       R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
+               }
+               R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
+               R_Mesh_ColorPointer(NULL, 0, 0);
+               GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+               GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
        }
        else
        {
+               if (r_glsl_offsetmapping.integer)
+               {
+                       permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+                       if (r_glsl_offsetmapping_reliefmapping.integer)
+                               permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+               }
+               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+                       permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
                // lightmapped wall
+               if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
+                       permutation |= SHADERPERMUTATION_GLOW;
+               if (r_refdef.fogenabled)
+                       permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+               if (rsurface.texture->colormapping)
+                       permutation |= SHADERPERMUTATION_COLORMAPPING;
+               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
+                       permutation |= SHADERPERMUTATION_REFLECTION;
+               if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
+                       permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
                if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
                {
                        // deluxemapping (light direction texture)
@@ -4430,7 +4608,16 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                                mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
                        permutation |= SHADERPERMUTATION_DIFFUSE;
                        if (specularscale > 0)
+                       {
                                permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
+                               if (r_shadow_glossexact.integer)
+                                       permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
+                       }
+                       R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
+                       if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
+                               R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
+                       else
+                               R_Mesh_ColorPointer(NULL, 0, 0);
                }
                else if (r_glsl_deluxemapping.integer >= 2)
                {
@@ -4438,36 +4625,50 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
                        permutation |= SHADERPERMUTATION_DIFFUSE;
                        if (specularscale > 0)
+                       {
                                permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
+                               if (r_shadow_glossexact.integer)
+                                       permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
+                       }
+                       R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
+                       if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
+                               R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
+                       else
+                               R_Mesh_ColorPointer(NULL, 0, 0);
                }
                else if (rsurface.uselightmaptexture)
                {
                        // ordinary lightmapping (q1bsp, q3bsp)
                        mode = SHADERMODE_LIGHTMAP;
+                       R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
+                       if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
+                               R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
+                       else
+                               R_Mesh_ColorPointer(NULL, 0, 0);
                }
                else
                {
                        // ordinary vertex coloring (q3bsp)
                        mode = SHADERMODE_VERTEXCOLOR;
+                       R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
+                       R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
                }
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
-                       permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
-               if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
-                       permutation |= SHADERPERMUTATION_GLOW;
-               if (r_refdef.fogenabled)
-                       permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
-               if (rsurface.texture->colormapping)
-                       permutation |= SHADERPERMUTATION_COLORMAPPING;
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
-                       permutation |= SHADERPERMUTATION_REFLECTION;
-               if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
-                       permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
+               R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
+               if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
+               {
+                       R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
+                       R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
+                       R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
+               }
+               else
+               {
+                       R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
+                       R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
+                       R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
+               }
+               GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+               GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
        }
-       if(permutation & SHADERPERMUTATION_SPECULAR)
-               if(r_shadow_glossexact.integer)
-                       permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
-       if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
-               permutation |= SHADERPERMUTATION_ALPHAKILL;
        switch(vid.renderpath)
        {
        case RENDERPATH_GL20:
@@ -4479,7 +4680,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
                        if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);
                        if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);
-                       if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
+                       if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
        
                        // additive passes are only darkened by fog, not tinted
                        if (r_glsl_permutation->loc_FogColor >= 0)
@@ -4497,8 +4698,8 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        else if (mode == SHADERMODE_LIGHTDIRECTION)
                        {
                                if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);
-                               if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
-                               if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
+                               if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);
+                               if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
                                if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);
                                if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
                                if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
@@ -4508,7 +4709,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        {
                                if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);
                                if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
-                               if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
+                               if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
                                if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
                                if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
                        }
@@ -4529,7 +4730,6 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
                        if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
                }
-               if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
                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_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
@@ -4555,38 +4755,39 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
                if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
                if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
-
-       //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             ,          R_GetTexture(r_texture_white                                     ));
-       //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            ,          R_GetTexture(r_texture_white                                     ));
-       //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        ,          R_GetTexture(r_texture_gammaramps                                ));
-               if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            ,          R_GetTexture(rsurface.texture->nmaptexture                       ));
-               if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             ,          R_GetTexture(rsurface.texture->basetexture                       ));
-               if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             ,          R_GetTexture(rsurface.texture->glosstexture                      ));
-               if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              ,          R_GetTexture(rsurface.texture->glowtexture                       ));
-               if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  ,          R_GetTexture(rsurface.texture->backgroundnmaptexture             ));
-               if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   ,          R_GetTexture(rsurface.texture->backgroundbasetexture             ));
-               if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   ,          R_GetTexture(rsurface.texture->backgroundglosstexture            ));
-               if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    ,          R_GetTexture(rsurface.texture->backgroundglowtexture             ));
-               if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             ,          R_GetTexture(rsurface.texture->pantstexture                      ));
-               if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             ,          R_GetTexture(rsurface.texture->shirttexture                      ));
-               if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           ,          R_GetTexture(r_texture_fogattenuation                            ));
-               if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          ,          R_GetTexture(r_texture_white                                     ));
-               if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          ,          R_GetTexture(r_texture_blanknormalmap                            ));
-               if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       ,          R_GetTexture(r_shadow_attenuationgradienttexture                 ));
-               if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        ,          R_GetTexture(r_texture_white                                     ));
-               if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        ,          R_GetTexture(r_texture_white                                     ));
-               if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH    , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
-               if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
-               if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE  , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture              ));
-               if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture             ));
+               if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
+
+       //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
+       //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
+       //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
+               if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
+               if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
+               if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
+               if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
+               if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
+               if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
+               if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
+               if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
+               if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
+               if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
+               if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
+               if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
+               if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
+               if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
+               if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
+               if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
+               if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
+               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 (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBindAll(GL20TU_CUBE           , 0, 0,    R_GetTexture(rsurface.rtlight->currentcubemap                    ), 0);
-                       if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT  , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
+                       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_TexBindAll(GL20TU_SHADOWMAPCUBE  , 0, 0,    R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
-                       if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       ,          R_GetTexture(r_shadow_shadowmap2dtexture                         ));
-                       if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0,    R_GetTexture(r_shadow_shadowmapvsdcttexture                      ), 0);
+                               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                      );
                }
                CHECKGLERROR
                break;
@@ -4605,7 +4806,6 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                                if (r_cg_permutation->vp_LightDir) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
                        }
                }
-               if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);CHECKCGERROR
                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_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
@@ -4618,7 +4818,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
                        if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);CHECKCGERROR
                        if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);CHECKCGERROR
-                       if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, specularscale, specularscale, specularscale);CHECKCGERROR
+                       if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
 
                        // 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
@@ -4635,8 +4835,8 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        else if (mode == SHADERMODE_LIGHTDIRECTION)
                        {
                                if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);CHECKCGERROR
-                               if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);CHECKCGERROR
-                               if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);CHECKCGERROR
+                               if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);CHECKCGERROR
+                               if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
                                if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
                                if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
                                if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
@@ -4646,7 +4846,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        {
                                if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);CHECKCGERROR
                                if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
-                               if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);CHECKCGERROR
+                               if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
                                if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
                                if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
                        }
@@ -4693,38 +4893,39 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
                if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
                if (r_cg_permutation->fp_ScreenToDepth) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
-
-       //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , R_GetTexture(r_texture_white                                     ));CHECKCGERROR
-       //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , R_GetTexture(r_texture_white                                     ));CHECKCGERROR
-       //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , R_GetTexture(r_texture_gammaramps                                ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , R_GetTexture(rsurface.texture->nmaptexture                       ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , R_GetTexture(rsurface.texture->basetexture                       ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , R_GetTexture(rsurface.texture->glosstexture                      ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , R_GetTexture(rsurface.texture->glowtexture                       ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, R_GetTexture(rsurface.texture->backgroundnmaptexture             ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , R_GetTexture(rsurface.texture->backgroundbasetexture             ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , R_GetTexture(rsurface.texture->backgroundglosstexture            ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , R_GetTexture(rsurface.texture->backgroundglowtexture             ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , R_GetTexture(rsurface.texture->pantstexture                      ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , R_GetTexture(rsurface.texture->shirttexture                      ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , R_GetTexture(r_texture_fogattenuation                            ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , R_GetTexture(r_texture_white                                     ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , R_GetTexture(r_texture_blanknormalmap                            ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , R_GetTexture(r_shadow_attenuationgradienttexture                 ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , R_GetTexture(r_texture_white                                     ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , R_GetTexture(r_texture_white                                     ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , R_GetTexture(r_shadow_prepasslightingdiffusetexture              ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , R_GetTexture(r_shadow_prepasslightingspeculartexture             ));CHECKCGERROR
+               if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
+
+       //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
+       //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );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_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
+               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 (r_cg_permutation->fp_Texture_Cube       ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , R_GetTexture(rsurface.rtlight->currentcubemap                    ));CHECKCGERROR
-                       if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , R_GetTexture(r_shadow_shadowmaprectangletexture                  ));CHECKCGERROR
+                       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_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));CHECKCGERROR
-                       if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , R_GetTexture(r_shadow_shadowmap2dtexture                         ));CHECKCGERROR
-                       if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture                      ));CHECKCGERROR
+                               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
                }
 
                CHECKGLERROR
@@ -4793,7 +4994,6 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
        {
        case RENDERPATH_GL20:
                R_SetupShader_SetPermutationGLSL(mode, permutation);
-               if (r_glsl_permutation->loc_ModelViewMatrix           >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix          , 1, false, gl_modelview16f);
                if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
                if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
                if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
@@ -4803,21 +5003,21 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
                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            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
                if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
+               if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
 
-               if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       ,          R_GetTexture(r_shadow_attenuationgradienttexture                 ));
-               if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH    , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
-               if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
-               if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBindAll(GL20TU_CUBE           , 0, 0,    R_GetTexture(rsurface.rtlight->currentcubemap                    ), 0);
-               if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT  , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
+               if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
+               if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
+               if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
+               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_TexBindAll(GL20TU_SHADOWMAPCUBE  , 0, 0,    R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
-               if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       ,          R_GetTexture(r_shadow_shadowmap2dtexture                         ));
-               if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0,    R_GetTexture(r_shadow_shadowmapvsdcttexture                      ), 0);
+                       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                      );
                break;
        case RENDERPATH_CGGL:
 #ifdef SUPPORTCG
                R_SetupShader_SetPermutationCG(mode, permutation);
-               if (r_cg_permutation->vp_ModelViewMatrix          ) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);CHECKCGERROR
                if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
                if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
                if (r_cg_permutation->fp_DeferredColor_Ambient    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);CHECKCGERROR
@@ -4827,16 +5027,17 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
                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, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
                if (r_cg_permutation->fp_ScreenToDepth            ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
+               if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
 
-               if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , R_GetTexture(r_shadow_attenuationgradienttexture                 ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , R_GetTexture(rsurface.rtlight->currentcubemap                    ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , R_GetTexture(r_shadow_shadowmaprectangletexture                  ));CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
+               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_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_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , R_GetTexture(r_shadow_shadowmap2dtexture                         ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture                      ));CHECKCGERROR
+                       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
 #endif
                break;
        case RENDERPATH_GL13:
@@ -5007,9 +5208,13 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        unsigned char *pixels;
        unsigned char *bumppixels;
        unsigned char *basepixels = NULL;
-       int basepixels_width;
-       int basepixels_height;
+       int basepixels_width = 0;
+       int basepixels_height = 0;
        skinframe_t *skinframe;
+       rtexture_t *ddsbase = NULL;
+       qboolean ddshasalpha = false;
+       float ddsavgcolor[4];
+       char basename[MAX_QPATH];
 
        if (cls.state == ca_dedicated)
                return NULL;
@@ -5021,9 +5226,15 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        if (skinframe && skinframe->base)
                return skinframe;
 
-       basepixels = loadimagepixelsbgra(name, complain, true);
-       if (basepixels == NULL)
-               return NULL;
+       Image_StripImageExtension(name, basename, sizeof(basename));
+
+       // 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);
+               if (basepixels == NULL)
+                       return NULL;
+       }
 
        if (developer_loading.integer)
                Con_Printf("loading skin \"%s\"\n", name);
@@ -5033,50 +5244,75 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
                skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
        skinframe->stain = NULL;
        skinframe->merged = NULL;
-       skinframe->base = r_texture_notexture;
+       skinframe->base = NULL;
        skinframe->pants = NULL;
        skinframe->shirt = NULL;
-       skinframe->nmap = r_texture_blanknormalmap;
+       skinframe->nmap = NULL;
        skinframe->gloss = NULL;
        skinframe->glow = NULL;
        skinframe->fog = NULL;
        skinframe->hasalpha = false;
 
-       basepixels_width = image_width;
-       basepixels_height = image_height;
-       skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
-
-       if (textureflags & TEXF_ALPHA)
+       if (ddsbase)
        {
-               for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
+               skinframe->base = ddsbase;
+               skinframe->hasalpha = ddshasalpha;
+               VectorCopy(ddsavgcolor, skinframe->avgcolor);
+               if (r_loadfog && skinframe->hasalpha)
+                       skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
+               //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
+       }
+       else
+       {
+               basepixels_width = image_width;
+               basepixels_height = image_height;
+               skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
+               if (textureflags & TEXF_ALPHA)
                {
-                       if (basepixels[j] < 255)
+                       for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
                        {
-                               skinframe->hasalpha = true;
-                               break;
+                               if (basepixels[j] < 255)
+                               {
+                                       skinframe->hasalpha = true;
+                                       break;
+                               }
                        }
-               }
-               if (r_loadfog && skinframe->hasalpha)
-               {
-                       // has transparent pixels
-                       pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
-                       for (j = 0;j < image_width * image_height * 4;j += 4)
+                       if (r_loadfog && skinframe->hasalpha)
                        {
-                               pixels[j+0] = 255;
-                               pixels[j+1] = 255;
-                               pixels[j+2] = 255;
-                               pixels[j+3] = basepixels[j+3];
+                               // has transparent pixels
+                               pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
+                               for (j = 0;j < image_width * image_height * 4;j += 4)
+                               {
+                                       pixels[j+0] = 255;
+                                       pixels[j+1] = 255;
+                                       pixels[j+2] = 255;
+                                       pixels[j+3] = basepixels[j+3];
+                               }
+                               skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
+                               Mem_Free(pixels);
                        }
-                       skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
-                       Mem_Free(pixels);
                }
+               R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
+               //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
+               if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
+                       R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
+               if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
+                       R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
        }
 
-       R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
-       //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
+       if (r_loaddds)
+       {
+               if (r_loadnormalmap)
+                       skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
+               skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
+               if (r_loadgloss)
+                       skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
+               skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
+               skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
+       }
 
        // _norm is the name used by tenebrae and has been adopted as standard
-       if (r_loadnormalmap)
+       if (r_loadnormalmap && skinframe->nmap == NULL)
        {
                if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
                {
@@ -5099,14 +5335,46 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
                        skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
                        Mem_Free(pixels);
                }
+               if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
+                       R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
        }
-       // _luma is supported for tenebrae compatibility
-       // (I think it's a very stupid name, but oh well)
+
+       // _luma is supported only for tenebrae compatibility
        // _glow is the preferred name
-       if ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))) {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);Mem_Free(pixels);pixels = NULL;}
-       if (r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false))) {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);Mem_Free(pixels);pixels = NULL;}
-       if ((pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false))) {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);Mem_Free(pixels);pixels = NULL;}
-       if ((pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false))) {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);Mem_Free(pixels);pixels = NULL;}
+       if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
+       {
+               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)
+                       R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
+               Mem_Free(pixels);pixels = NULL;
+       }
+
+       if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
+       {
+               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)
+                       R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
+               Mem_Free(pixels);
+               pixels = NULL;
+       }
+
+       if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
+       {
+               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)
+                       R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
+               Mem_Free(pixels);
+               pixels = NULL;
+       }
+
+       if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
+       {
+               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)
+                       R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
+               Mem_Free(pixels);
+               pixels = NULL;
+       }
 
        if (basepixels)
                Mem_Free(basepixels);
@@ -5131,10 +5399,10 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co
 
        skinframe->stain = NULL;
        skinframe->merged = NULL;
-       skinframe->base = r_texture_notexture;
+       skinframe->base = NULL;
        skinframe->pants = NULL;
        skinframe->shirt = NULL;
-       skinframe->nmap = r_texture_blanknormalmap;
+       skinframe->nmap = NULL;
        skinframe->gloss = NULL;
        skinframe->glow = NULL;
        skinframe->fog = NULL;
@@ -5199,10 +5467,10 @@ skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, i
 
        skinframe->stain = NULL;
        skinframe->merged = NULL;
-       skinframe->base = r_texture_notexture;
+       skinframe->base = NULL;
        skinframe->pants = NULL;
        skinframe->shirt = NULL;
-       skinframe->nmap = r_texture_blanknormalmap;
+       skinframe->nmap = NULL;
        skinframe->gloss = NULL;
        skinframe->glow = NULL;
        skinframe->fog = NULL;
@@ -5319,10 +5587,10 @@ skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, co
 
        skinframe->stain = NULL;
        skinframe->merged = NULL;
-       skinframe->base = r_texture_notexture;
+       skinframe->base = NULL;
        skinframe->pants = NULL;
        skinframe->shirt = NULL;
-       skinframe->nmap = r_texture_blanknormalmap;
+       skinframe->nmap = NULL;
        skinframe->gloss = NULL;
        skinframe->glow = NULL;
        skinframe->fog = NULL;
@@ -5366,10 +5634,10 @@ skinframe_t *R_SkinFrame_LoadMissing(void)
        skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
        skinframe->stain = NULL;
        skinframe->merged = NULL;
-       skinframe->base = r_texture_notexture;
+       skinframe->base = NULL;
        skinframe->pants = NULL;
        skinframe->shirt = NULL;
-       skinframe->nmap = r_texture_blanknormalmap;
+       skinframe->nmap = NULL;
        skinframe->gloss = NULL;
        skinframe->glow = NULL;
        skinframe->fog = NULL;
@@ -5447,6 +5715,9 @@ void gl_main_start(void)
        r_texture_fogattenuation = NULL;
        r_texture_gammaramps = NULL;
 
+       r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
+       r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
+
        switch(vid.renderpath)
        {
        case RENDERPATH_GL20:
@@ -5659,6 +5930,8 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_fog_exp2);
        Cvar_RegisterVariable(&r_drawfog);
        Cvar_RegisterVariable(&r_transparentdepthmasking);
+       Cvar_RegisterVariable(&r_texture_dds_load);
+       Cvar_RegisterVariable(&r_texture_dds_save);
        Cvar_RegisterVariable(&r_textureunits);
        Cvar_RegisterVariable(&gl_combine);
        Cvar_RegisterVariable(&r_glsl);
@@ -5706,6 +5979,8 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_track_sprites_flags);
        Cvar_RegisterVariable(&r_track_sprites_scalew);
        Cvar_RegisterVariable(&r_track_sprites_scaleh);
+       Cvar_RegisterVariable(&r_overheadsprites_perspective);
+       Cvar_RegisterVariable(&r_overheadsprites_pushback);
 }
 
 extern void R_Textures_Init(void);
@@ -5882,7 +6157,7 @@ static void *r_framedata_base;
 
 void R_FrameData_Reset(void)
 {
-       if (r_framedata_base);
+       if (r_framedata_base)
                Mem_Free(r_framedata_base);
        r_framedata_base = NULL;
        r_framedata_size = 0;
@@ -5900,7 +6175,7 @@ void R_FrameData_NewFrame(void)
        if (r_framedata_size != wantedsize)
        {
                r_framedata_size = wantedsize;
-               if (r_framedata_base);
+               if (r_framedata_base)
                        Mem_Free(r_framedata_base);
                r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
        }
@@ -6511,12 +6786,14 @@ void R_EntityMatrix(const matrix4x4_t *matrix)
                {
                case RENDERPATH_GL20:
                        if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
+                       if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
                        qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
                        break;
                case RENDERPATH_CGGL:
 #ifdef SUPPORTCG
                        CHECKCGERROR
                        if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
+                       if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
                        qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
 #endif
                        break;
@@ -6743,7 +7020,7 @@ static void R_Water_ProcessPlanes(void)
                if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
                {
                        if (!p->texture_refraction)
-                               p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
+                               p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
                        if (!p->texture_refraction)
                                goto error;
                }
@@ -6751,7 +7028,7 @@ static void R_Water_ProcessPlanes(void)
                if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
                {
                        if (!p->texture_reflection)
-                               p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
+                               p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
                        if (!p->texture_reflection)
                                goto error;
                }
@@ -6767,24 +7044,6 @@ static void R_Water_ProcessPlanes(void)
        r_waterstate.renderingscene = true;
        for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
        {
-               // render the normal view scene and copy into texture
-               // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
-               if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
-               {
-                       r_refdef.view = myview;
-                       r_refdef.view.clipplane = p->plane;
-                       VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
-                       r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
-                       PlaneClassify(&r_refdef.view.clipplane);
-
-                       R_ResetViewRendering3D();
-                       R_ClearScreen(r_refdef.fogenabled);
-                       R_View_Update();
-                       R_RenderScene();
-
-                       R_Mesh_CopyToTexture(R_GetTexture(p->texture_refraction), 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
-               }
-
                if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
                {
                        r_refdef.view = myview;
@@ -6810,8 +7069,27 @@ static void R_Water_ProcessPlanes(void)
                        R_View_Update();
                        R_RenderScene();
 
-                       R_Mesh_CopyToTexture(R_GetTexture(p->texture_reflection), 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+                       R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
                }
+
+               // render the normal view scene and copy into texture
+               // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
+               if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
+               {
+                       r_refdef.view = myview;
+                       r_refdef.view.clipplane = p->plane;
+                       VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
+                       r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
+                       PlaneClassify(&r_refdef.view.clipplane);
+
+                       R_ResetViewRendering3D();
+                       R_ClearScreen(r_refdef.fogenabled);
+                       R_View_Update();
+                       R_RenderScene();
+
+                       R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+               }
+
        }
        r_waterstate.renderingscene = false;
        r_refdef.view = originalview;
@@ -6887,7 +7165,7 @@ void R_Bloom_StartFrame(void)
                r_bloomstate.screentexturewidth = screentexturewidth;
                r_bloomstate.screentextureheight = screentextureheight;
                if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
-                       r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
+                       r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
        }
        if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
        {
@@ -6897,7 +7175,7 @@ void R_Bloom_StartFrame(void)
                r_bloomstate.bloomtexturewidth = bloomtexturewidth;
                r_bloomstate.bloomtextureheight = bloomtextureheight;
                if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
-                       r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
+                       r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
        }
 
        // when doing a reduced render (HDR) we want to use a smaller area
@@ -6955,13 +7233,13 @@ void R_Bloom_CopyBloomTexture(float colorscale)
 
        // we now have a bloom image in the framebuffer
        // copy it into the bloom image texture for later processing
-       R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_bloom), 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
+       R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
        r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
 }
 
 void R_Bloom_CopyHDRTexture(void)
 {
-       R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_bloom), 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+       R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
        r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
 }
 
@@ -6992,9 +7270,7 @@ void R_Bloom_MakeTexture(void)
                r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
 
                // copy the vertically blurred bloom view to a texture
-               GL_ActiveTexture(0);
-               CHECKGLERROR
-               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_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
                r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
        }
 
@@ -7044,9 +7320,7 @@ void R_Bloom_MakeTexture(void)
                }
 
                // copy the vertically blurred bloom view to a texture
-               GL_ActiveTexture(0);
-               CHECKGLERROR
-               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_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
                r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
        }
 
@@ -7071,7 +7345,7 @@ void R_Bloom_MakeTexture(void)
                qglBlendEquationEXT(GL_FUNC_ADD_EXT);
 
                // copy the darkened bloom view to a texture
-               R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_bloom), 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
+               R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
                r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
        }
 }
@@ -7122,7 +7396,6 @@ void R_HDR_RenderBloomTexture(void)
        r_refdef.view.width = oldwidth;
        r_refdef.view.height = oldheight;
        r_refdef.view.colorscale = oldcolorscale;
-       r_frame++; // used only by R_GetCurrentTexture
 
        R_ResetViewRendering3D();
 
@@ -7197,7 +7470,7 @@ static void R_BlendView(void)
                        }
 
                        // copy view into the screen texture
-                       R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_screen), 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+                       R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
                        r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
                }
                else if (!r_bloomstate.texture_bloom)
@@ -7247,9 +7520,9 @@ static void R_BlendView(void)
                {
                case RENDERPATH_GL20:
                        R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
-                       if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , R_GetTexture(r_bloomstate.texture_screen));
-                       if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , R_GetTexture(r_bloomstate.texture_bloom ));
-                       if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps       ));
+                       if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
+                       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);
@@ -7258,13 +7531,14 @@ static void R_BlendView(void)
                        if (r_glsl_permutation->loc_UserVec3           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
                        if (r_glsl_permutation->loc_UserVec4           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
                        if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
+                       if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
                        break;
                case RENDERPATH_CGGL:
 #ifdef SUPPORTCG
                        R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
-                       if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , R_GetTexture(r_bloomstate.texture_screen));CHECKCGERROR
-                       if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , R_GetTexture(r_bloomstate.texture_bloom ));CHECKCGERROR
-                       if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, R_GetTexture(r_texture_gammaramps       ));CHECKCGERROR
+                       if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
+                       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
@@ -7273,6 +7547,7 @@ static void R_BlendView(void)
                        if (r_cg_permutation->fp_UserVec3          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);CHECKCGERROR
                        if (r_cg_permutation->fp_UserVec4          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);CHECKCGERROR
                        if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
+                       if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
 #endif
                        break;
                default:
@@ -7500,7 +7775,7 @@ void R_RenderView(void)
 {
        if (r_timereport_active)
                R_TimeReport("start");
-       r_frame++; // used only by R_GetCurrentTexture
+       r_textureframe++; // used only by R_GetCurrentTexture
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
 
        if (!r_drawentities.integer)
@@ -7560,7 +7835,11 @@ void R_RenderView(void)
 
        // this produces a bloom texture to be used in R_BlendView() later
        if (r_hdr.integer && r_bloomstate.bloomwidth)
+       {
                R_HDR_RenderBloomTexture();
+               // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
+               r_textureframe++; // used only by R_GetCurrentTexture
+       }
 
        r_refdef.view.showdebug = true;
 
@@ -8329,9 +8608,9 @@ texture_t *R_GetCurrentTexture(texture_t *t)
        dp_model_t *model = ent->model;
        q3shaderinfo_layer_tcmod_t *tcmod;
 
-       if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
+       if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
                return t->currentframe;
-       t->update_lastrenderframe = r_frame;
+       t->update_lastrenderframe = r_textureframe;
        t->update_lastrenderentity = (void *)ent;
 
        // switch to an alternate material if this is a q1bsp animated material
@@ -8442,9 +8721,13 @@ texture_t *R_GetCurrentTexture(texture_t *t)
        if (t->currentskinframe->qpixels)
                R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
        t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
+       if (!t->basetexture)
+               t->basetexture = r_texture_notexture;
        t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
        t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
        t->nmaptexture = t->currentskinframe->nmap;
+       if (!t->nmaptexture)
+               t->nmaptexture = r_texture_blanknormalmap;
        t->glosstexture = r_texture_black;
        t->glowtexture = t->currentskinframe->glow;
        t->fogtexture = t->currentskinframe->fog;
@@ -8454,6 +8737,8 @@ texture_t *R_GetCurrentTexture(texture_t *t)
                t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
                t->backgroundglosstexture = r_texture_black;
                t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
+               if (!t->backgroundnmaptexture)
+                       t->backgroundnmaptexture = r_texture_blanknormalmap;
        }
        else
        {
@@ -9420,10 +9705,7 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesu
        int numtriangles;
        // TODO: lock all array ranges before render, rather than on each surface
        if (texturenumsurfaces == 1)
-       {
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
-       }
        else if (r_batchmode.integer == 2)
        {
                #define MAXBATCHTRIANGLES 4096
@@ -9468,7 +9750,6 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesu
                        surface2 = texturesurfacelist[j-1];
                        numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
                        numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
-                       GL_LockArrays(surface->num_firstvertex, numvertices);
                        R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
                }
        }
@@ -9477,7 +9758,6 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesu
                for (i = 0;i < texturenumsurfaces;i++)
                {
                        surface = texturesurfacelist[i];
-                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                        R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
                }
        }
@@ -9489,17 +9769,17 @@ static void RSurf_BindLightmapForSurface(const msurface_t *surface)
        {
        case RENDERPATH_CGGL:
 #ifdef SUPPORTCG
-               if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , R_GetTexture(surface->lightmaptexture ));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, R_GetTexture(surface->deluxemaptexture));CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
 #endif
                break;
        case RENDERPATH_GL20:
-               if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , R_GetTexture(surface->lightmaptexture ));
-               if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, R_GetTexture(surface->deluxemaptexture));
+               if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
+               if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
                break;
        case RENDERPATH_GL13:
        case RENDERPATH_GL11:
-               R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
+               R_Mesh_TexBind(0, surface->lightmaptexture);
                break;
        }
 }
@@ -9532,13 +9812,13 @@ static void RSurf_BindReflectionForSurface(const msurface_t *surface)
        {
        case RENDERPATH_CGGL:
 #ifdef SUPPORTCG
-               if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? R_GetTexture(bestp->texture_refraction) : R_GetTexture(r_texture_black));CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? R_GetTexture(bestp->texture_reflection) : R_GetTexture(r_texture_black));CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
+               if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
 #endif
                break;
        case RENDERPATH_GL20:
-               if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? R_GetTexture(bestp->texture_refraction) : R_GetTexture(r_texture_black));
-               if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? R_GetTexture(bestp->texture_reflection) : R_GetTexture(r_texture_black));
+               if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
+               if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
                break;
        case RENDERPATH_GL13:
        case RENDERPATH_GL11:
@@ -9557,7 +9837,6 @@ static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int
                surface = texturesurfacelist[i];
                RSurf_BindLightmapForSurface(surface);
                RSurf_BindReflectionForSurface(surface);
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
        }
 }
@@ -9575,7 +9854,6 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const
        if (texturenumsurfaces == 1)
        {
                RSurf_BindLightmapForSurface(surface);
-               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
        }
        else if (r_batchmode.integer == 2)
@@ -9640,7 +9918,6 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const
                        surface2 = texturesurfacelist[j-1];
                        numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
                        numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
-                       GL_LockArrays(surface->num_firstvertex, numvertices);
                        R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
                }
 #if 0
@@ -9653,7 +9930,6 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const
                {
                        surface = texturesurfacelist[i];
                        RSurf_BindLightmapForSurface(surface);
-                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                        R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
                }
        }
@@ -9683,7 +9959,6 @@ static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_
                        const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
                        int k = (int)(((size_t)surface) / sizeof(msurface_t));
                        GL_Color((k & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1);
-                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                        R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
                }
        }
@@ -10051,83 +10326,36 @@ extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
 {
-       qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
-       qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
-
-       if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
-               return;
-
-       if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
-               R_Mesh_ColorPointer(NULL, 0, 0);
-       else
-               R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
-
-       if (refract)
+       RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
+       if (prepass)
        {
-               // render background
-               GL_BlendFunc(GL_ONE, GL_ZERO);
+               // render screenspace normalmap to texture
                GL_DepthMask(true);
-               GL_AlphaTest(false);
-
-               GL_Color(1, 1, 1, 1);
-               R_Mesh_ColorPointer(NULL, 0, 0);
-
-               R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
-               RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
-               R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
-               R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
-               R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
-               R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
-               R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
-               RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
-               GL_LockArrays(0, 0);
-
-               GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
-               GL_DepthMask(false);
-               if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
-                       R_Mesh_ColorPointer(NULL, 0, 0);
-               else
-                       R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
+               R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
+               RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
        }
-
-       R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
-
-       RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
-       R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
-       R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
-       R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
-       R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
-       if (!prepass)
-               R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
-
-       if (refract)
+       else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
        {
-               GL_BlendFunc(GL_ONE, GL_ZERO);
+               // render water or distortion background, then blend surface on top
                GL_DepthMask(true);
-               GL_AlphaTest(false);
+               R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
+               RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
+               GL_DepthMask(false);
+               R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
+               RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
        }
        else
        {
-               GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+               // render surface normally
                GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
-               GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
-       }
-
-       if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
-       {
-               if (refract || reflect)
+               R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
+               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
                        RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
-               else
+               else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
                        RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
-       }
-       else
-       {
-               if (refract || reflect)
-                       RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
                else
                        RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
        }
-       GL_LockArrays(0, 0);
 }
 
 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
@@ -10179,11 +10407,11 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface
                {
                case TEXTURELAYERTYPE_LITTEXTURE:
                        // single-pass lightmapped texture with 2x rgbscale
-                       //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
+                       R_Mesh_TexBind(0, r_texture_white);
                        R_Mesh_TexMatrix(0, NULL);
                        R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
                        R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
-                       R_Mesh_TexBind(1, R_GetTexture(layer->texture));
+                       R_Mesh_TexBind(1, layer->texture);
                        R_Mesh_TexMatrix(1, &layer->texmatrix);
                        R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
                        R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
@@ -10196,7 +10424,7 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface
                        break;
                case TEXTURELAYERTYPE_TEXTURE:
                        // singletexture unlit texture with transparency support
-                       R_Mesh_TexBind(0, R_GetTexture(layer->texture));
+                       R_Mesh_TexBind(0, layer->texture);
                        R_Mesh_TexMatrix(0, &layer->texmatrix);
                        R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
                        R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
@@ -10208,7 +10436,7 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface
                        // singletexture fogging
                        if (layer->texture)
                        {
-                               R_Mesh_TexBind(0, R_GetTexture(layer->texture));
+                               R_Mesh_TexBind(0, layer->texture);
                                R_Mesh_TexMatrix(0, &layer->texmatrix);
                                R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
                                R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
@@ -10243,7 +10471,6 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface
                default:
                        Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
                }
-               GL_LockArrays(0, 0);
        }
        CHECKGLERROR
        if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
@@ -10285,7 +10512,7 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface
                        {
                                // two-pass lit texture with 2x rgbscale
                                // first the lightmap pass
-                               //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
+                               R_Mesh_TexBind(0, r_texture_white);
                                R_Mesh_TexMatrix(0, NULL);
                                R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
                                R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
@@ -10295,10 +10522,9 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface
                                        RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
                                else
                                        RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
-                               GL_LockArrays(0, 0);
                                // then apply the texture to it
                                GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
-                               R_Mesh_TexBind(0, R_GetTexture(layer->texture));
+                               R_Mesh_TexBind(0, layer->texture);
                                R_Mesh_TexMatrix(0, &layer->texmatrix);
                                R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
                                R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
@@ -10307,7 +10533,7 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface
                        else
                        {
                                // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
-                               R_Mesh_TexBind(0, R_GetTexture(layer->texture));
+                               R_Mesh_TexBind(0, layer->texture);
                                R_Mesh_TexMatrix(0, &layer->texmatrix);
                                R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
                                R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
@@ -10319,7 +10545,7 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface
                        break;
                case TEXTURELAYERTYPE_TEXTURE:
                        // singletexture unlit texture with transparency support
-                       R_Mesh_TexBind(0, R_GetTexture(layer->texture));
+                       R_Mesh_TexBind(0, layer->texture);
                        R_Mesh_TexMatrix(0, &layer->texmatrix);
                        R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
                        R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
@@ -10329,7 +10555,7 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface
                        // singletexture fogging
                        if (layer->texture)
                        {
-                               R_Mesh_TexBind(0, R_GetTexture(layer->texture));
+                               R_Mesh_TexBind(0, layer->texture);
                                R_Mesh_TexMatrix(0, &layer->texmatrix);
                                R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
                                R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
@@ -10362,7 +10588,6 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface
                default:
                        Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
                }
-               GL_LockArrays(0, 0);
        }
        CHECKGLERROR
        if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
@@ -11253,7 +11478,6 @@ typedef struct r_decalsystem_splatqueue_s
 r_decalsystem_splatqueue_t;
 
 int r_decalsystem_numqueued = 0;
-#define MAX_DECALSYSTEM_QUEUE 1024
 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
 
 void R_DecalSystem_SplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
@@ -11495,9 +11719,7 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent)
                GL_CullFace(GL_NONE);
                GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
                R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
-               GL_LockArrays(0, numtris * 3);
                R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
-               GL_LockArrays(0, 0);
        }
 }
 
@@ -11746,31 +11968,19 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep
                        r_surfacelist[numsurfacelist++] = surfaces + j;
        }
        // update lightmaps if needed
-       if (update)
+       if (model->brushq1.firstrender)
+       {
+               model->brushq1.firstrender = false;
+               for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
+                       if (update[j])
+                               R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
+       }
+       else if (update)
        {
-               int updated = 0;
                for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
-               {
                        if (r_refdef.viewcache.world_surfacevisible[j])
-                       {
                                if (update[j])
-                               {
-                                       updated++;
                                        R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
-                               }
-                       }
-               }
-               if (updated)
-               {
-                       int count = model->brushq3.num_mergedlightmaps;
-                       for (i = 0;i < count;i++)
-                       {
-                               if (model->brushq3.data_deluxemaps[i])
-                                       R_FlushTexture(model->brushq3.data_deluxemaps[i]);
-                               if (model->brushq3.data_lightmaps[i])
-                                       R_FlushTexture(model->brushq3.data_lightmaps[i]);
-                       }
-               }
        }
        // don't do anything if there were no surfaces
        if (!numsurfacelist)
@@ -11892,17 +12102,6 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
                                R_BuildLightMap(ent, surfaces + j);
                        }
                }
-               if (updated)
-               {
-                       int count = model->brushq3.num_mergedlightmaps;
-                       for (i = 0;i < count;i++)
-                       {
-                               if (model->brushq3.data_deluxemaps[i])
-                                       R_FlushTexture(model->brushq3.data_deluxemaps[i]);
-                               if (model->brushq3.data_lightmaps[i])
-                                       R_FlushTexture(model->brushq3.data_lightmaps[i]);
-                       }
-               }
        }
        if (update)
                for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)