]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rmain.c
implemented framerate-dependent particle quality reduction to try to
[xonotic/darkplaces.git] / gl_rmain.c
index d41416db0a01544d7dfe19f6508c65d24f1c0c00..c2f6ad2f2c84a21b986045961c8805a8ea696f13 100644 (file)
@@ -593,16 +593,20 @@ static const char *builtinshaderstring =
 "uniform sampler2D Texture_Normal;\n"
 "uniform sampler2D Texture_Color;\n"
 "uniform sampler2D Texture_Gloss;\n"
-"uniform samplerCube Texture_Cube;\n"
-"uniform sampler2D Texture_Attenuation;\n"
-"uniform sampler2D Texture_FogMask;\n"
+"uniform sampler2D Texture_Glow;\n"
+"uniform sampler2D Texture_SecondaryNormal;\n"
+"uniform sampler2D Texture_SecondaryColor;\n"
+"uniform sampler2D Texture_SecondaryGloss;\n"
+"uniform sampler2D Texture_SecondaryGlow;\n"
 "uniform sampler2D Texture_Pants;\n"
 "uniform sampler2D Texture_Shirt;\n"
+"uniform sampler2D Texture_FogMask;\n"
 "uniform sampler2D Texture_Lightmap;\n"
 "uniform sampler2D Texture_Deluxemap;\n"
-"uniform sampler2D Texture_Glow;\n"
-"uniform sampler2D Texture_Reflection;\n"
 "uniform sampler2D Texture_Refraction;\n"
+"uniform sampler2D Texture_Reflection;\n"
+"uniform sampler2D Texture_Attenuation;\n"
+"uniform samplerCube Texture_Cube;\n"
 "\n"
 "uniform myhalf3 LightColor;\n"
 "uniform myhalf3 AmbientColor;\n"
@@ -716,7 +720,7 @@ static const char *builtinshaderstring =
 "      vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
 "      //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
 "      vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
-"      float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 5.0) * ReflectFactor + ReflectOffset;\n"
+"      float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
 "      gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
 "}\n"
 "\n"
@@ -752,7 +756,28 @@ static const char *builtinshaderstring =
 "#ifdef USECOLORMAPPING\n"
 "      color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
 "#endif\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+"      myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
+"      //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
+"      //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
+"      color = mix(myhalf4(texture2D(Texture_SecondaryColor, TexCoord)), color, terrainblend);\n"
+"      //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
+"#endif\n"
 "\n"
+"#ifdef USEDIFFUSE\n"
+"      // get the surface normal and the gloss color\n"
+"# ifdef USEVERTEXTEXTUREBLEND\n"
+"      myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
+"#  ifdef USESPECULAR\n"
+"      myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
+"#  endif\n"
+"# else\n"
+"      myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
+"#  ifdef USESPECULAR\n"
+"      myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
+"#  endif\n"
+"# endif\n"
+"#endif\n"
 "\n"
 "\n"
 "\n"
@@ -763,23 +788,22 @@ static const char *builtinshaderstring =
 "      // compute color intensity for the two textures (colormap and glossmap)\n"
 "      // scale by light color and attenuation as efficiently as possible\n"
 "      // (do as much scalar math as possible rather than vector math)\n"
-"# ifdef USESPECULAR\n"
-"      myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
+"# ifdef USEDIFFUSE\n"
+"      // get the light normal\n"
 "      myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
+"# endif\n"
+"# ifdef USESPECULAR\n"
 "      myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
 "\n"
 "      // calculate directional shading\n"
-"      color.rgb = LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * myhalf3(texture2D(Texture_Gloss, TexCoord)));\n"
+"      color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * glosscolor);\n"
 "# else\n"
 "#  ifdef USEDIFFUSE\n"
-"      myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
-"      myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
-"\n"
 "      // calculate directional shading\n"
-"      color.rgb = color.rgb * LightColor * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
+"      color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
 "#  else\n"
 "      // calculate directionless shading\n"
-"      color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
+"      color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
 "#  endif\n"
 "# endif\n"
 "\n"
@@ -795,20 +819,17 @@ static const char *builtinshaderstring =
 "\n"
 "#ifdef MODE_LIGHTDIRECTION\n"
 "      // directional model lighting\n"
-"# ifdef USESPECULAR\n"
-"      // get the surface normal and light normal\n"
-"      myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
+"# ifdef USEDIFFUSE\n"
+"      // get the light normal\n"
 "      myhalf3 diffusenormal = myhalf3(LightVector);\n"
-"\n"
+"# endif\n"
+"# ifdef USESPECULAR\n"
 "      // calculate directional shading\n"
 "      color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
 "      myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
 "      color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
 "# else\n"
 "#  ifdef USEDIFFUSE\n"
-"      // get the surface normal and light normal\n"
-"      myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
-"      myhalf3 diffusenormal = myhalf3(LightVector);\n"
 "\n"
 "      // calculate directional shading\n"
 "      color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
@@ -816,8 +837,6 @@ static const char *builtinshaderstring =
 "      color.rgb *= AmbientColor;\n"
 "#  endif\n"
 "# endif\n"
-"\n"
-"      color.a *= TintColor.a;\n"
 "#endif // MODE_LIGHTDIRECTION\n"
 "\n"
 "\n"
@@ -826,9 +845,7 @@ static const char *builtinshaderstring =
 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
 "      // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
 "\n"
-"      // get the surface normal and light normal\n"
-"      myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
-"\n"
+"      // get the light normal\n"
 "      myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5);\n"
 "      myhalf3 diffusenormal = normalize(myhalf3(dot(diffusenormal_modelspace, myhalf3(VectorS)), dot(diffusenormal_modelspace, myhalf3(VectorT)), dot(diffusenormal_modelspace, myhalf3(VectorR))));\n"
 "      // calculate directional shading\n"
@@ -840,8 +857,6 @@ static const char *builtinshaderstring =
 "\n"
 "      // apply lightmap color\n"
 "      color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
-"\n"
-"      color *= TintColor;\n"
 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
 "\n"
 "\n"
@@ -850,9 +865,7 @@ static const char *builtinshaderstring =
 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
 "      // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
 "\n"
-"      // get the surface normal and light normal\n"
-"      myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
-"\n"
+"      // get the light normal\n"
 "      myhalf3 diffusenormal = normalize(myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5));\n"
 "      // calculate directional shading\n"
 "      myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
@@ -863,8 +876,6 @@ static const char *builtinshaderstring =
 "\n"
 "      // apply lightmap color\n"
 "      color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
-"\n"
-"      color *= TintColor;\n"
 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
 "\n"
 "\n"
@@ -873,8 +884,6 @@ static const char *builtinshaderstring =
 "#ifdef MODE_LIGHTMAP\n"
 "      // apply lightmap color\n"
 "      color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
-"\n"
-"      color *= TintColor;\n"
 "#endif // MODE_LIGHTMAP\n"
 "\n"
 "\n"
@@ -883,15 +892,12 @@ static const char *builtinshaderstring =
 "#ifdef MODE_VERTEXCOLOR\n"
 "      // apply lightmap color\n"
 "      color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
-"\n"
-"      color *= TintColor;\n"
 "#endif // MODE_VERTEXCOLOR\n"
 "\n"
 "\n"
 "\n"
 "\n"
 "#ifdef MODE_FLATCOLOR\n"
-"      color *= TintColor;\n"
 "#endif // MODE_FLATCOLOR\n"
 "\n"
 "\n"
@@ -900,6 +906,7 @@ static const char *builtinshaderstring =
 "\n"
 "\n"
 "\n"
+"      color *= TintColor;\n"
 "\n"
 "#ifdef USEGLOW\n"
 "      color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
@@ -951,30 +958,32 @@ shadermodeinfo_t;
 
 typedef enum shaderpermutation_e
 {
-       SHADERPERMUTATION_COLORMAPPING = 1<<0, // indicates this is a colormapped skin
-       SHADERPERMUTATION_CONTRASTBOOST = 1<<1, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
-       SHADERPERMUTATION_FOG = 1<<2, // tint the color by fog color or black if using additive blend mode
-       SHADERPERMUTATION_CUBEFILTER = 1<<3, // (lightsource) use cubemap light filter
-       SHADERPERMUTATION_GLOW = 1<<4, // (lightmap) blend in an additive glow texture
-       SHADERPERMUTATION_DIFFUSE = 1<<5, // (lightsource) whether to use directional shading
-       SHADERPERMUTATION_SPECULAR = 1<<6, // (lightsource or deluxemapping) render specular effects
-       SHADERPERMUTATION_REFLECTION = 1<<7, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
-       SHADERPERMUTATION_OFFSETMAPPING = 1<<8, // adjust texcoords to roughly simulate a displacement mapped surface
-       SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<9, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
-       SHADERPERMUTATION_LIMIT = 1<<10, // size of permutations array
-       SHADERPERMUTATION_COUNT = 10 // size of shaderpermutationinfo array
+       SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
+       SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
+       SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
+       SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
+       SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
+       SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
+       SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
+       SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
+       SHADERPERMUTATION_REFLECTION = 1<<8, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
+       SHADERPERMUTATION_OFFSETMAPPING = 1<<9, // adjust texcoords to roughly simulate a displacement mapped surface
+       SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
+       SHADERPERMUTATION_LIMIT = 1<<11, // size of permutations array
+       SHADERPERMUTATION_COUNT = 11 // size of shaderpermutationinfo array
 }
 shaderpermutation_t;
 
 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
 {
+       {"#define USEDIFFUSE\n", " diffuse"},
+       {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
        {"#define USECOLORMAPPING\n", " colormapping"},
        {"#define USECONTRASTBOOST\n", " contrastboost"},
        {"#define USEFOG\n", " fog"},
        {"#define USECUBEFILTER\n", " cubefilter"},
        {"#define USEGLOW\n", " glow"},
-       {"#define USEDIFFUSE\n", " diffuse"},
        {"#define USESPECULAR\n", " specular"},
        {"#define USEREFLECTION\n", " reflection"},
        {"#define USEOFFSETMAPPING\n", " offsetmapping"},
@@ -1021,20 +1030,23 @@ typedef struct r_glsl_permutation_s
        int loc_Texture_Normal;
        int loc_Texture_Color;
        int loc_Texture_Gloss;
-       int loc_Texture_Cube;
-       int loc_Texture_Attenuation;
-       int loc_Texture_FogMask;
+       int loc_Texture_Glow;
+       int loc_Texture_SecondaryNormal;
+       int loc_Texture_SecondaryColor;
+       int loc_Texture_SecondaryGloss;
+       int loc_Texture_SecondaryGlow;
        int loc_Texture_Pants;
        int loc_Texture_Shirt;
+       int loc_Texture_FogMask;
        int loc_Texture_Lightmap;
        int loc_Texture_Deluxemap;
-       int loc_Texture_Glow;
+       int loc_Texture_Attenuation;
+       int loc_Texture_Cube;
        int loc_Texture_Refraction;
        int loc_Texture_Reflection;
        int loc_FogColor;
        int loc_LightPosition;
        int loc_EyePosition;
-       int loc_LightColor;
        int loc_Color_Pants;
        int loc_Color_Shirt;
        int loc_FogRangeRecip;
@@ -1165,60 +1177,67 @@ static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t per
                qglUseProgramObjectARB(p->program);CHECKGLERROR
                // look up all the uniform variable names we care about, so we don't
                // have to look them up every time we set them
-               p->loc_Texture_Normal      = qglGetUniformLocationARB(p->program, "Texture_Normal");
-               p->loc_Texture_Color       = qglGetUniformLocationARB(p->program, "Texture_Color");
-               p->loc_Texture_Gloss       = qglGetUniformLocationARB(p->program, "Texture_Gloss");
-               p->loc_Texture_Cube        = qglGetUniformLocationARB(p->program, "Texture_Cube");
-               p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
-               p->loc_Texture_FogMask     = qglGetUniformLocationARB(p->program, "Texture_FogMask");
-               p->loc_Texture_Pants       = qglGetUniformLocationARB(p->program, "Texture_Pants");
-               p->loc_Texture_Shirt       = qglGetUniformLocationARB(p->program, "Texture_Shirt");
-               p->loc_Texture_Lightmap    = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
-               p->loc_Texture_Deluxemap   = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
-               p->loc_Texture_Glow        = qglGetUniformLocationARB(p->program, "Texture_Glow");
-               p->loc_Texture_Refraction  = qglGetUniformLocationARB(p->program, "Texture_Refraction");
-               p->loc_Texture_Reflection  = qglGetUniformLocationARB(p->program, "Texture_Reflection");
-               p->loc_FogColor            = qglGetUniformLocationARB(p->program, "FogColor");
-               p->loc_LightPosition       = qglGetUniformLocationARB(p->program, "LightPosition");
-               p->loc_EyePosition         = qglGetUniformLocationARB(p->program, "EyePosition");
-               p->loc_LightColor          = qglGetUniformLocationARB(p->program, "LightColor");
-               p->loc_Color_Pants         = qglGetUniformLocationARB(p->program, "Color_Pants");
-               p->loc_Color_Shirt         = qglGetUniformLocationARB(p->program, "Color_Shirt");
-               p->loc_FogRangeRecip       = qglGetUniformLocationARB(p->program, "FogRangeRecip");
-               p->loc_AmbientScale        = qglGetUniformLocationARB(p->program, "AmbientScale");
-               p->loc_DiffuseScale        = qglGetUniformLocationARB(p->program, "DiffuseScale");
-               p->loc_SpecularPower       = qglGetUniformLocationARB(p->program, "SpecularPower");
-               p->loc_SpecularScale       = qglGetUniformLocationARB(p->program, "SpecularScale");
-               p->loc_GlowScale           = qglGetUniformLocationARB(p->program, "GlowScale");
-               p->loc_SceneBrightness     = qglGetUniformLocationARB(p->program, "SceneBrightness");
-               p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
-               p->loc_TintColor       = qglGetUniformLocationARB(p->program, "TintColor");
-               p->loc_AmbientColor        = qglGetUniformLocationARB(p->program, "AmbientColor");
-               p->loc_DiffuseColor        = qglGetUniformLocationARB(p->program, "DiffuseColor");
-               p->loc_SpecularColor       = qglGetUniformLocationARB(p->program, "SpecularColor");
-               p->loc_LightDir            = qglGetUniformLocationARB(p->program, "LightDir");
-               p->loc_ContrastBoostCoeff  = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
+               p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
+               p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
+               p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
+               p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
+               p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
+               p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
+               p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
+               p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
+               p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
+               p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
+               p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
+               p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
+               p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
+               p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
+               p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
+               p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
+               p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
+               p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
+               p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
+               p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
+               p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
+               p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
+               p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
+               p->loc_AmbientScale               = qglGetUniformLocationARB(p->program, "AmbientScale");
+               p->loc_DiffuseScale               = qglGetUniformLocationARB(p->program, "DiffuseScale");
+               p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
+               p->loc_SpecularScale              = qglGetUniformLocationARB(p->program, "SpecularScale");
+               p->loc_GlowScale                  = qglGetUniformLocationARB(p->program, "GlowScale");
+               p->loc_SceneBrightness            = qglGetUniformLocationARB(p->program, "SceneBrightness");
+               p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
+               p->loc_TintColor                  = qglGetUniformLocationARB(p->program, "TintColor");
+               p->loc_AmbientColor               = qglGetUniformLocationARB(p->program, "AmbientColor");
+               p->loc_DiffuseColor               = qglGetUniformLocationARB(p->program, "DiffuseColor");
+               p->loc_SpecularColor              = qglGetUniformLocationARB(p->program, "SpecularColor");
+               p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
+               p->loc_ContrastBoostCoeff         = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
                p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
-               p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
+               p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
                p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
-               p->loc_RefractColor        = qglGetUniformLocationARB(p->program, "RefractColor");
-               p->loc_ReflectColor        = qglGetUniformLocationARB(p->program, "ReflectColor");
-               p->loc_ReflectFactor       = qglGetUniformLocationARB(p->program, "ReflectFactor");
-               p->loc_ReflectOffset       = qglGetUniformLocationARB(p->program, "ReflectOffset");
+               p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
+               p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
+               p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
+               p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
                // initialize the samplers to refer to the texture units we use
-               if (p->loc_Texture_Normal >= 0)    qglUniform1iARB(p->loc_Texture_Normal, 0);
-               if (p->loc_Texture_Color >= 0)     qglUniform1iARB(p->loc_Texture_Color, 1);
-               if (p->loc_Texture_Gloss >= 0)     qglUniform1iARB(p->loc_Texture_Gloss, 2);
-               if (p->loc_Texture_Cube >= 0)      qglUniform1iARB(p->loc_Texture_Cube, 3);
-               if (p->loc_Texture_FogMask >= 0)   qglUniform1iARB(p->loc_Texture_FogMask, 4);
-               if (p->loc_Texture_Pants >= 0)     qglUniform1iARB(p->loc_Texture_Pants, 5);
-               if (p->loc_Texture_Shirt >= 0)     qglUniform1iARB(p->loc_Texture_Shirt, 6);
-               if (p->loc_Texture_Lightmap >= 0)  qglUniform1iARB(p->loc_Texture_Lightmap, 7);
-               if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
-               if (p->loc_Texture_Glow >= 0)      qglUniform1iARB(p->loc_Texture_Glow, 9);
-               if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
-               if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
-               if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
+               if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
+               if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
+               if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
+               if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
+               if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
+               if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
+               if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
+               if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
+               if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
+               if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
+               if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
+               if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
+               if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
+               if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
+               if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
+               if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
+               if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
                CHECKGLERROR
                qglUseProgramObjectARB(0);CHECKGLERROR
                if (developer.integer)
@@ -1262,7 +1281,7 @@ void R_GLSL_DumpShader_f(void)
        FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
        for (i = 0;i < SHADERMODE_COUNT;i++)
                FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
-       for (i = 0;i < SHADERPERMUTATION_LIMIT;i++)
+       for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
                FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
        FS_Print(file, "\n");
        FS_Print(file, builtinshaderstring);
@@ -1302,6 +1321,8 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl
        {
                // light source
                mode = SHADERMODE_LIGHTSOURCE;
+               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+                       permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
                if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
                        permutation |= SHADERPERMUTATION_CUBEFILTER;
                if (diffusescale > 0)
@@ -1319,6 +1340,8 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl
        {
                // unshaded geometry (fullbright or ambient model lighting)
                mode = SHADERMODE_FLATCOLOR;
+               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+                       permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
                if (rsurface.texture->currentskinframe->glow)
                        permutation |= SHADERPERMUTATION_GLOW;
                if (r_refdef.fogenabled)
@@ -1340,6 +1363,8 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl
        {
                // directional model lighting
                mode = SHADERMODE_LIGHTDIRECTION;
+               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+                       permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
                if (rsurface.texture->currentskinframe->glow)
                        permutation |= SHADERPERMUTATION_GLOW;
                permutation |= SHADERPERMUTATION_DIFFUSE;
@@ -1358,6 +1383,8 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl
        {
                // ambient model lighting
                mode = SHADERMODE_LIGHTDIRECTION;
+               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+                       permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
                if (rsurface.texture->currentskinframe->glow)
                        permutation |= SHADERPERMUTATION_GLOW;
                if (r_refdef.fogenabled)
@@ -1379,6 +1406,7 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl
                                mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
                        else
                                mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
+                       permutation |= SHADERPERMUTATION_DIFFUSE;
                        if (specularscale > 0)
                                permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
                }
@@ -1386,6 +1414,7 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl
                {
                        // fake deluxemapping (uniform light direction in tangentspace)
                        mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
+                       permutation |= SHADERPERMUTATION_DIFFUSE;
                        if (specularscale > 0)
                                permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
                }
@@ -1399,6 +1428,8 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl
                        // ordinary vertex coloring (q3bsp)
                        mode = SHADERMODE_VERTEXCOLOR;
                }
+               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+                       permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
                if (rsurface.texture->currentskinframe->glow)
                        permutation |= SHADERPERMUTATION_GLOW;
                if (r_refdef.fogenabled)
@@ -1447,7 +1478,7 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl
                if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
                if (permutation & SHADERPERMUTATION_DIFFUSE)
                {
-                       if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
+                       if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
                        if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
                        if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
                        if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
@@ -1455,31 +1486,48 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl
                else
                {
                        // ambient only is simpler
-                       if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
+                       if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale, rsurface.texture->lightmapcolor[3]);
                        if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
                        if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
                        if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
                }
-       }
-       else if (mode == SHADERMODE_LIGHTDIRECTION)
-       {
-               if (r_glsl_permutation->loc_AmbientColor >= 0)
-                       qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale  * rsurface.texture->lightmapcolor[0] * 0.5f, rsurface.modellight_ambient[1] * ambientscale  * rsurface.texture->lightmapcolor[1] * 0.5f, rsurface.modellight_ambient[2] * ambientscale  * rsurface.texture->lightmapcolor[2] * 0.5f);
-               if (r_glsl_permutation->loc_DiffuseColor >= 0)
-                       qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale  * rsurface.texture->lightmapcolor[0] * 0.5f, rsurface.modellight_diffuse[1] * diffusescale  * rsurface.texture->lightmapcolor[1] * 0.5f, rsurface.modellight_diffuse[2] * diffusescale  * rsurface.texture->lightmapcolor[2] * 0.5f);
-               if (r_glsl_permutation->loc_SpecularColor >= 0)
-                       qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * rsurface.texture->lightmapcolor[0] * 0.5f, rsurface.modellight_diffuse[1] * specularscale * rsurface.texture->lightmapcolor[1] * 0.5f, rsurface.modellight_diffuse[2] * specularscale * rsurface.texture->lightmapcolor[2] * 0.5f);
-               if (r_glsl_permutation->loc_LightDir >= 0)
-                       qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
+               // additive passes are only darkened by fog, not tinted
+               if (r_glsl_permutation->loc_FogColor >= 0)
+                       qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
        }
        else
        {
-               if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
-               if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
-               if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
+               if (mode == SHADERMODE_LIGHTDIRECTION)
+               {
+                       if (r_glsl_permutation->loc_AmbientColor  >= 0) qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale  * 0.5f, rsurface.modellight_ambient[1] * ambientscale  * 0.5f, rsurface.modellight_ambient[2] * ambientscale  * 0.5f);
+                       if (r_glsl_permutation->loc_DiffuseColor  >= 0) qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale  * 0.5f, rsurface.modellight_diffuse[1] * diffusescale  * 0.5f, rsurface.modellight_diffuse[2] * diffusescale  * 0.5f);
+                       if (r_glsl_permutation->loc_SpecularColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * 0.5f, rsurface.modellight_diffuse[1] * specularscale * 0.5f, rsurface.modellight_diffuse[2] * specularscale * 0.5f);
+                       if (r_glsl_permutation->loc_LightDir      >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
+               }
+               else
+               {
+                       if (r_glsl_permutation->loc_AmbientScale  >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
+                       if (r_glsl_permutation->loc_DiffuseScale  >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
+                       if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
+               }
+               if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]);
+               if (r_glsl_permutation->loc_GlowScale     >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
+               // additive passes are only darkened by fog, not tinted
+               if (r_glsl_permutation->loc_FogColor >= 0)
+               {
+                       if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
+                               qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
+                       else
+                               qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
+               }
+               if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
+               if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
+               if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
+               if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
+               if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
+               if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
+               if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
        }
-       if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]);
-       if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
        if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
        {
                // The formula used is actually:
@@ -1493,14 +1541,6 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl
        }
        else
                if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
-       if (r_glsl_permutation->loc_FogColor >= 0)
-       {
-               // additive passes are only darkened by fog, not tinted
-               if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
-                       qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
-               else
-                       qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
-       }
        if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
        if (r_glsl_permutation->loc_Color_Pants >= 0)
        {
@@ -1519,13 +1559,6 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl
        if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
        if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
        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_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
-       if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
-       if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
-       if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
-       if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
-       if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
-       if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
        CHECKGLERROR
        return permutation;
 }
@@ -2374,10 +2407,10 @@ static void R_View_SetFrustum(void)
 {
        int i;
        double slopex, slopey;
+       vec3_t forward, left, up, origin;
 
-       // break apart the view matrix into vectors for various purposes
-       Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
-       VectorNegate(r_refdef.view.left, r_refdef.view.right);
+       // we can't trust r_refdef.view.forward and friends in reflected scenes
+       Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
 
 #if 0
        r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
@@ -2445,11 +2478,11 @@ static void R_View_SetFrustum(void)
        {
                slopex = 1.0 / r_refdef.view.frustum_x;
                slopey = 1.0 / r_refdef.view.frustum_y;
-               VectorMA(r_refdef.view.forward, -slopex, r_refdef.view.left, r_refdef.view.frustum[0].normal);
-               VectorMA(r_refdef.view.forward,  slopex, r_refdef.view.left, r_refdef.view.frustum[1].normal);
-               VectorMA(r_refdef.view.forward, -slopey, r_refdef.view.up  , r_refdef.view.frustum[2].normal);
-               VectorMA(r_refdef.view.forward,  slopey, r_refdef.view.up  , r_refdef.view.frustum[3].normal);
-               VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
+               VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
+               VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
+               VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
+               VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
+               VectorCopy(forward, r_refdef.view.frustum[4].normal);
 
                // Leaving those out was a mistake, those were in the old code, and they
                // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
@@ -2460,10 +2493,10 @@ static void R_View_SetFrustum(void)
                VectorNormalize(r_refdef.view.frustum[3].normal);
 
                // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
-               VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, -1024 * slopex, r_refdef.view.left, -1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[0]);
-               VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward,  1024 * slopex, r_refdef.view.left, -1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[1]);
-               VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, -1024 * slopex, r_refdef.view.left,  1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[2]);
-               VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward,  1024 * slopex, r_refdef.view.left,  1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[3]);
+               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
+               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
+               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[2]);
+               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[3]);
 
                r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
                r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
@@ -2473,11 +2506,11 @@ static void R_View_SetFrustum(void)
        }
        else
        {
-               VectorScale(r_refdef.view.left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
-               VectorScale(r_refdef.view.left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
-               VectorScale(r_refdef.view.up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
-               VectorScale(r_refdef.view.up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
-               VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
+               VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
+               VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
+               VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
+               VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
+               VectorCopy(forward, r_refdef.view.frustum[4].normal);
                r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
                r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
                r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
@@ -2500,27 +2533,27 @@ static void R_View_SetFrustum(void)
        // Quake2 has it disabled as well.
 
        // rotate R_VIEWFORWARD right by FOV_X/2 degrees
-       //RotatePointAroundVector( r_refdef.view.frustum[0].normal, r_refdef.view.up, r_refdef.view.forward, -(90 - r_refdef.fov_x / 2));
+       //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
        //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
        //PlaneClassify(&frustum[0]);
 
        // rotate R_VIEWFORWARD left by FOV_X/2 degrees
-       //RotatePointAroundVector( r_refdef.view.frustum[1].normal, r_refdef.view.up, r_refdef.view.forward, (90 - r_refdef.fov_x / 2));
+       //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
        //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
        //PlaneClassify(&frustum[1]);
 
        // rotate R_VIEWFORWARD up by FOV_X/2 degrees
-       //RotatePointAroundVector( r_refdef.view.frustum[2].normal, r_refdef.view.left, r_refdef.view.forward, -(90 - r_refdef.fov_y / 2));
+       //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
        //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
        //PlaneClassify(&frustum[2]);
 
        // rotate R_VIEWFORWARD down by FOV_X/2 degrees
-       //RotatePointAroundVector( r_refdef.view.frustum[3].normal, r_refdef.view.left, r_refdef.view.forward, (90 - r_refdef.fov_y / 2));
+       //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
        //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
        //PlaneClassify(&frustum[3]);
 
        // nearclip plane
-       //VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
+       //VectorCopy(forward, r_refdef.view.frustum[4].normal);
        //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
        //PlaneClassify(&frustum[4]);
 }
@@ -2532,7 +2565,7 @@ void R_View_Update(void)
        R_View_UpdateEntityVisible();
 }
 
-void R_SetupView(void)
+void R_SetupView(qboolean allowwaterclippingplane)
 {
        if (!r_refdef.view.useperspective)
                GL_SetupView_Mode_Ortho(-r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
@@ -2543,7 +2576,7 @@ void R_SetupView(void)
 
        GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
 
-       if (r_refdef.view.useclipplane)
+       if (r_refdef.view.useclipplane && allowwaterclippingplane)
        {
                // LordHavoc: couldn't figure out how to make this approach the
                vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
@@ -2598,7 +2631,7 @@ void R_ResetViewRendering3D(void)
 
        // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
        qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
-       R_SetupView();
+       R_SetupView(true);
        GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
        GL_Color(1, 1, 1, 1);
        GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
@@ -2862,6 +2895,8 @@ static void R_Water_ProcessPlanes(void)
                {
                        // render reflected scene and copy into texture
                        Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
+                       // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
+                       Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
                        r_refdef.view.clipplane = p->plane;
                        // reverse the cullface settings for this render
                        r_refdef.view.cullface_front = GL_FRONT;
@@ -3390,6 +3425,14 @@ void R_RenderView(void)
 
        r_refdef.view.colorscale = r_hdr_scenebrightness.value;
 
+       // break apart the view matrix into vectors for various purposes
+       // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
+       // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
+       Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
+       VectorNegate(r_refdef.view.left, r_refdef.view.right);
+       // make an inverted copy of the view matrix for tracking sprites
+       Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
+
        R_Shadow_UpdateWorldLightSelection();
 
        R_Bloom_StartFrame();
@@ -3435,7 +3478,8 @@ static void R_DrawLocs(void);
 static void R_DrawEntityBBoxes(void);
 void R_RenderScene(qboolean addwaterplanes)
 {
-       Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
+       r_refdef.stats.renders++;
+
        R_UpdateFogColor();
 
        if (addwaterplanes)
@@ -3889,6 +3933,7 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_
        }
        else
                GL_CullFace(r_refdef.view.cullface_back);
+       GL_CullFace(GL_NONE);
 
        GL_DepthMask(false);
        GL_DepthRange(0, depthshort ? 0.0625 : 1);
@@ -4161,10 +4206,16 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
        if (ent->flags & RENDER_VIEWMODEL)
                t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
-       if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
+       if (t->backgroundnumskinframes)
                t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
+       if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
+       {
+               if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
+                       t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
+       }
+       else
+               t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
 
-       // make sure that the waterscroll matrix is used on water surfaces when
        // there is no tcmod
        if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
                t->currenttexmatrix = r_waterscrollmatrix;
@@ -5515,7 +5566,7 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurfa
 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
 {
        // transparent sky would be ridiculous
-       if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
+       if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
                return;
        if (rsurface.mode != RSURFMODE_SKY)
        {
@@ -5528,7 +5579,10 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **te
        if (skyrendernow)
        {
                skyrendernow = false;
+               // we have to force off the water clipping plane while rendering sky
+               R_SetupView(false);
                R_Sky();
+               R_SetupView(true);
                // restore entity matrix
                R_Mesh_Matrix(&rsurface.matrix);
        }
@@ -5578,33 +5632,24 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t
        }
 
        R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
-       R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
-       R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
-       R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
-       R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
-       R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
-       R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
-       if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
-       {
-               R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
-               R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
-               R_Mesh_ColorPointer(NULL, 0, 0);
-       }
-       else if (rsurface.uselightmaptexture)
-       {
-               R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
-               R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
+       R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
+       R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
+       R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
+       R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
+       if (rsurface.texture->backgroundcurrentskinframe)
+       {
+               R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
+               R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
+               R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
+               R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
+       }
+       R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
+       R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
+       R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
+       if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
                R_Mesh_ColorPointer(NULL, 0, 0);
-       }
        else
-       {
-               R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
-               R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
                R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
-       }
-       R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
-       R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
-       R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
 
        if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
        {
@@ -5625,32 +5670,18 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t
                        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, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
+                       RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
                }
 
                GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
                GL_DepthMask(false);
                GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
-               {
-                       R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
-                       R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
+               if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
                        R_Mesh_ColorPointer(NULL, 0, 0);
-               }
-               else if (rsurface.uselightmaptexture)
-               {
-                       R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
-                       R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
-                       R_Mesh_ColorPointer(NULL, 0, 0);
-               }
                else
-               {
-                       R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
-                       R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
                        R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
-               }
-               R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
-               R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
+               R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
+               R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
        }
 
        R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
@@ -5674,20 +5705,17 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t
        if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
        {
                if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
-                       RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? 12 : -1);
+                       RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
                else
-                       RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
+                       RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
        }
        else
        {
                if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
-                       RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? 12 : -1);
+                       RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
                else
                        RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
        }
-       if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
-       {
-       }
 }
 
 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)