]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rmain.c
vary r_drawparticles_drawdistance and r_drawdecals_drawdistance for
[xonotic/darkplaces.git] / gl_rmain.c
index c248ae33477504294dc7e2767b9c7f2dbe5ce35a..c2f6ad2f2c84a21b986045961c8805a8ea696f13 100644 (file)
@@ -455,14 +455,14 @@ static const char *builtinshaderstring =
 "\n"
 "#ifdef __GLSL_CG_DATA_TYPES\n"
 "# define myhalf half\n"
-"# define myhvec2 hvec2\n"
-"# define myhvec3 hvec3\n"
-"# define myhvec4 hvec4\n"
+"# define myhalf2 half2\n"
+"# define myhalf3 half3\n"
+"# define myhalf4 half4\n"
 "#else\n"
 "# define myhalf float\n"
-"# define myhvec2 vec2\n"
-"# define myhvec3 vec3\n"
-"# define myhvec4 vec4\n"
+"# define myhalf2 vec2\n"
+"# define myhalf3 vec3\n"
+"# define myhalf4 vec4\n"
 "#endif\n"
 "\n"
 "varying vec2 TexCoord;\n"
@@ -593,34 +593,38 @@ 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 myhvec3 LightColor;\n"
-"uniform myhvec3 AmbientColor;\n"
-"uniform myhvec3 DiffuseColor;\n"
-"uniform myhvec3 SpecularColor;\n"
-"uniform myhvec3 Color_Pants;\n"
-"uniform myhvec3 Color_Shirt;\n"
-"uniform myhvec3 FogColor;\n"
+"uniform myhalf3 LightColor;\n"
+"uniform myhalf3 AmbientColor;\n"
+"uniform myhalf3 DiffuseColor;\n"
+"uniform myhalf3 SpecularColor;\n"
+"uniform myhalf3 Color_Pants;\n"
+"uniform myhalf3 Color_Shirt;\n"
+"uniform myhalf3 FogColor;\n"
 "\n"
-"uniform myhvec4 TintColor;\n"
+"uniform myhalf4 TintColor;\n"
 "\n"
 "\n"
 "//#ifdef MODE_WATER\n"
 "uniform vec4 DistortScaleRefractReflect;\n"
 "uniform vec4 ScreenScaleRefractReflect;\n"
 "uniform vec4 ScreenCenterRefractReflect;\n"
-"uniform myhvec4 RefractColor;\n"
-"uniform myhvec4 ReflectColor;\n"
+"uniform myhalf4 RefractColor;\n"
+"uniform myhalf4 ReflectColor;\n"
 "uniform myhalf ReflectFactor;\n"
 "uniform myhalf ReflectOffset;\n"
 "//#else\n"
@@ -628,16 +632,16 @@ static const char *builtinshaderstring =
 "//uniform vec4 DistortScaleRefractReflect;\n"
 "//uniform vec4 ScreenScaleRefractReflect;\n"
 "//uniform vec4 ScreenCenterRefractReflect;\n"
-"//uniform myhvec4 RefractColor;\n"
+"//uniform myhalf4 RefractColor;\n"
 "//#  ifdef USEREFLECTION\n"
-"//uniform myhvec4 ReflectColor;\n"
+"//uniform myhalf4 ReflectColor;\n"
 "//#  endif\n"
 "//# else\n"
 "//#  ifdef USEREFLECTION\n"
 "//uniform vec4 DistortScaleRefractReflect;\n"
 "//uniform vec4 ScreenScaleRefractReflect;\n"
 "//uniform vec4 ScreenCenterRefractReflect;\n"
-"//uniform myhvec4 ReflectColor;\n"
+"//uniform myhalf4 ReflectColor;\n"
 "//#  endif\n"
 "//# endif\n"
 "//#endif\n"
@@ -714,9 +718,9 @@ static const char *builtinshaderstring =
 "#endif\n"
 "\n"
 "      vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
-"      //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
-"      vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
-"      float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 5.0) * ReflectFactor + ReflectOffset;\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)), 2.0) * ReflectFactor + ReflectOffset;\n"
 "      gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
 "}\n"
 "\n"
@@ -733,8 +737,8 @@ static const char *builtinshaderstring =
 "#endif\n"
 "\n"
 "      vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
-"      //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
-"      vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
+"      //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
+"      vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
 "      gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
 "}\n"
 "\n"
@@ -748,11 +752,32 @@ static const char *builtinshaderstring =
 "#endif\n"
 "\n"
 "      // combine the diffuse textures (base, pants, shirt)\n"
-"      myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
+"      myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
 "#ifdef USECOLORMAPPING\n"
-"      color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\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,30 +788,29 @@ 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 USEDIFFUSE\n"
+"      // get the light normal\n"
+"      myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
+"# endif\n"
 "# ifdef USESPECULAR\n"
-"      myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
-"      myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
-"      myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\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)) * myhvec3(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"
-"      myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
-"      myhvec3 diffusenormal = myhvec3(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"
 "# ifdef USECUBEFILTER\n"
 "      // apply light cubemap filter\n"
 "      //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
-"      color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
+"      color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
 "# endif\n"
 "#endif // MODE_LIGHTSOURCE\n"
 "\n"
@@ -795,20 +819,17 @@ static const char *builtinshaderstring =
 "\n"
 "#ifdef MODE_LIGHTDIRECTION\n"
 "      // directional model lighting\n"
+"# ifdef USEDIFFUSE\n"
+"      // get the light normal\n"
+"      myhalf3 diffusenormal = myhalf3(LightVector);\n"
+"# endif\n"
 "# ifdef USESPECULAR\n"
-"      // get the surface normal and light normal\n"
-"      myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
-"      myhvec3 diffusenormal = myhvec3(LightVector);\n"
-"\n"
 "      // calculate directional shading\n"
 "      color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
-"      myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
-"      color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\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"
-"      myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
-"      myhvec3 diffusenormal = myhvec3(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,22 +845,18 @@ 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"
-"      myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
-"\n"
-"      myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
-"      myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\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"
-"      myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
+"      myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
 "# ifdef USESPECULAR\n"
-"      myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
-"      tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+"      myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
+"      tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
 "# endif\n"
 "\n"
 "      // apply lightmap color\n"
-"      color.rgb = color.rgb * AmbientScale + tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
-"\n"
-"      color *= TintColor;\n"
+"      color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
 "\n"
 "\n"
@@ -850,21 +865,17 @@ 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"
-"      myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
-"\n"
-"      myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
+"      // get the light normal\n"
+"      myhalf3 diffusenormal = normalize(myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5));\n"
 "      // calculate directional shading\n"
-"      myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
+"      myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
 "# ifdef USESPECULAR\n"
-"      myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
-"      tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+"      myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
+"      tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
 "# endif\n"
 "\n"
 "      // apply lightmap color\n"
-"      color.rgb = color.rgb * AmbientScale + tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
-"\n"
-"      color *= TintColor;\n"
+"      color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
 "\n"
 "\n"
@@ -872,9 +883,7 @@ static const char *builtinshaderstring =
 "\n"
 "#ifdef MODE_LIGHTMAP\n"
 "      // apply lightmap color\n"
-"      color.rgb = color.rgb * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
-"\n"
-"      color *= TintColor;\n"
+"      color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
 "#endif // MODE_LIGHTMAP\n"
 "\n"
 "\n"
@@ -882,16 +891,13 @@ static const char *builtinshaderstring =
 "\n"
 "#ifdef MODE_VERTEXCOLOR\n"
 "      // apply lightmap color\n"
-"      color.rgb = color.rgb * myhvec3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
-"\n"
-"      color *= TintColor;\n"
+"      color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
 "#endif // MODE_VERTEXCOLOR\n"
 "\n"
 "\n"
 "\n"
 "\n"
 "#ifdef MODE_FLATCOLOR\n"
-"      color *= TintColor;\n"
 "#endif // MODE_FLATCOLOR\n"
 "\n"
 "\n"
@@ -900,28 +906,29 @@ static const char *builtinshaderstring =
 "\n"
 "\n"
 "\n"
+"      color *= TintColor;\n"
 "\n"
 "#ifdef USEGLOW\n"
-"      color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
+"      color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
 "#endif\n"
 "\n"
 "#ifdef USECONTRASTBOOST\n"
-"      color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
+"      color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
 "#endif\n"
 "\n"
 "      color.rgb *= SceneBrightness;\n"
 "\n"
 "      // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
 "#ifdef USEFOG\n"
-"      color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
+"      color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
 "#endif\n"
 "\n"
 "      // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
 "#ifdef USEREFLECTION\n"
 "      vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
-"      //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
-"      vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
-"      color.rgb = mix(color.rgb, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
+"      //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
+"      vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
+"      color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
 "#endif\n"
 "\n"
 "      gl_FragColor = vec4(color);\n"
@@ -946,36 +953,37 @@ typedef struct shadermodeinfo_s
        const char *fragmentfilename;
        const char *pretext;
        const char *name;
-       int allowedpermutations;
 }
 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"},
@@ -1001,15 +1009,15 @@ shadermode_t;
 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
 {
-       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor", SHADERPERMUTATION_COLORMAPPING | SHADERPERMUTATION_CONTRASTBOOST | SHADERPERMUTATION_FOG | SHADERPERMUTATION_GLOW | SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_REFLECTION | SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING},
-       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor", SHADERPERMUTATION_COLORMAPPING | SHADERPERMUTATION_CONTRASTBOOST | SHADERPERMUTATION_FOG | SHADERPERMUTATION_GLOW | SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_REFLECTION | SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING},
-       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap", SHADERPERMUTATION_COLORMAPPING | SHADERPERMUTATION_CONTRASTBOOST | SHADERPERMUTATION_FOG | SHADERPERMUTATION_GLOW | SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_REFLECTION | SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING},
-       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace", SHADERPERMUTATION_COLORMAPPING | SHADERPERMUTATION_CONTRASTBOOST | SHADERPERMUTATION_FOG | SHADERPERMUTATION_GLOW | SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_REFLECTION | SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING},
-       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace", SHADERPERMUTATION_COLORMAPPING | SHADERPERMUTATION_CONTRASTBOOST | SHADERPERMUTATION_FOG | SHADERPERMUTATION_GLOW | SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_REFLECTION | SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING},
-       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection", SHADERPERMUTATION_COLORMAPPING | SHADERPERMUTATION_CONTRASTBOOST | SHADERPERMUTATION_FOG | SHADERPERMUTATION_GLOW | SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_REFLECTION | SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING},
-       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource", SHADERPERMUTATION_COLORMAPPING | SHADERPERMUTATION_CONTRASTBOOST | SHADERPERMUTATION_FOG | SHADERPERMUTATION_CUBEFILTER | SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING},
-       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction", SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING},
-       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water", SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING},
+       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
+       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
+       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
+       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
+       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
+       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
+       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
+       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
+       {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
 };
 
 typedef struct r_glsl_permutation_s
@@ -1022,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;
@@ -1166,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)
@@ -1263,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);
@@ -1303,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)
@@ -1320,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)
@@ -1341,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;
@@ -1359,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)
@@ -1373,13 +1399,14 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl
        else
        {
                // lightmapped wall
-               if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
+               if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
                {
                        // deluxemapping (light direction texture)
-                       if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
+                       if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
                                mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
                        else
                                mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
+                       permutation |= SHADERPERMUTATION_DIFFUSE;
                        if (specularscale > 0)
                                permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
                }
@@ -1387,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;
                }
@@ -1400,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)
@@ -1448,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);
@@ -1456,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:
@@ -1494,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)
        {
@@ -1520,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;
 }
@@ -2237,23 +2269,23 @@ static void R_View_UpdateEntityVisible (void)
                return;
 
        renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
-       if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
+       if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
        {
                // worldmodel can check visibility
-               for (i = 0;i < r_refdef.numentities;i++)
+               for (i = 0;i < r_refdef.scene.numentities;i++)
                {
-                       ent = r_refdef.entities[i];
-                       r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs));
+                       ent = r_refdef.scene.entities[i];
+                       r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs));
 
                }
-               if(r_cullentities_trace.integer && r_refdef.worldmodel->brush.TraceLineOfSight)
+               if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
                {
-                       for (i = 0;i < r_refdef.numentities;i++)
+                       for (i = 0;i < r_refdef.scene.numentities;i++)
                        {
-                               ent = r_refdef.entities[i];
+                               ent = r_refdef.scene.entities[i];
                                if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
                                {
-                                       if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_refdef.view.origin, ent->mins, ent->maxs))
+                                       if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.scene.worldmodel, r_refdef.view.origin, ent->mins, ent->maxs))
                                                ent->last_trace_visibility = realtime;
                                        if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
                                                r_refdef.viewcache.entityvisible[i] = 0;
@@ -2264,9 +2296,9 @@ static void R_View_UpdateEntityVisible (void)
        else
        {
                // no worldmodel or it can't check visibility
-               for (i = 0;i < r_refdef.numentities;i++)
+               for (i = 0;i < r_refdef.scene.numentities;i++)
                {
-                       ent = r_refdef.entities[i];
+                       ent = r_refdef.scene.entities[i];
                        r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
                }
        }
@@ -2282,11 +2314,11 @@ int R_DrawBrushModelsSky (void)
                return false;
 
        sky = false;
-       for (i = 0;i < r_refdef.numentities;i++)
+       for (i = 0;i < r_refdef.scene.numentities;i++)
        {
                if (!r_refdef.viewcache.entityvisible[i])
                        continue;
-               ent = r_refdef.entities[i];
+               ent = r_refdef.scene.entities[i];
                if (!ent->model || !ent->model->DrawSky)
                        continue;
                ent->model->DrawSky(ent);
@@ -2304,11 +2336,11 @@ static void R_DrawModels(void)
        if (!r_drawentities.integer)
                return;
 
-       for (i = 0;i < r_refdef.numentities;i++)
+       for (i = 0;i < r_refdef.scene.numentities;i++)
        {
                if (!r_refdef.viewcache.entityvisible[i])
                        continue;
-               ent = r_refdef.entities[i];
+               ent = r_refdef.scene.entities[i];
                r_refdef.stats.entities++;
                if (ent->model && ent->model->Draw != NULL)
                        ent->model->Draw(ent);
@@ -2325,11 +2357,11 @@ static void R_DrawModelsDepth(void)
        if (!r_drawentities.integer)
                return;
 
-       for (i = 0;i < r_refdef.numentities;i++)
+       for (i = 0;i < r_refdef.scene.numentities;i++)
        {
                if (!r_refdef.viewcache.entityvisible[i])
                        continue;
-               ent = r_refdef.entities[i];
+               ent = r_refdef.scene.entities[i];
                if (ent->model && ent->model->DrawDepth != NULL)
                        ent->model->DrawDepth(ent);
        }
@@ -2343,11 +2375,11 @@ static void R_DrawModelsDebug(void)
        if (!r_drawentities.integer)
                return;
 
-       for (i = 0;i < r_refdef.numentities;i++)
+       for (i = 0;i < r_refdef.scene.numentities;i++)
        {
                if (!r_refdef.viewcache.entityvisible[i])
                        continue;
-               ent = r_refdef.entities[i];
+               ent = r_refdef.scene.entities[i];
                if (ent->model && ent->model->DrawDebug != NULL)
                        ent->model->DrawDebug(ent);
        }
@@ -2361,11 +2393,11 @@ static void R_DrawModelsAddWaterPlanes(void)
        if (!r_drawentities.integer)
                return;
 
-       for (i = 0;i < r_refdef.numentities;i++)
+       for (i = 0;i < r_refdef.scene.numentities;i++)
        {
                if (!r_refdef.viewcache.entityvisible[i])
                        continue;
-               ent = r_refdef.entities[i];
+               ent = r_refdef.scene.entities[i];
                if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
                        ent->model->DrawAddWaterPlanes(ent);
        }
@@ -2375,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;
@@ -2446,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
@@ -2461,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);
@@ -2474,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;
@@ -2501,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]);
 }
@@ -2533,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);
@@ -2544,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;
@@ -2599,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);
@@ -2630,14 +2662,14 @@ void R_ResetViewRendering3D(void)
 "\n"
 "#ifdef __GLSL_CG_DATA_TYPES\n"
 "#define myhalf half\n"
-"#define myhvec2 hvec2\n"
-"#define myhvec3 hvec3\n"
-"#define myhvec4 hvec4\n"
+"#define myhalf2 half2\n"
+"#define myhalf3 half3\n"
+"#define myhalf4 half4\n"
 "#else\n"
 "#define myhalf float\n"
-"#define myhvec2 vec2\n"
-"#define myhvec3 vec3\n"
-"#define myhvec4 vec4\n"
+"#define myhalf2 vec2\n"
+"#define myhalf3 vec3\n"
+"#define myhalf4 vec4\n"
 "#endif\n"
 "\n"
 "varying vec2 ScreenTexCoord;\n"
@@ -2669,12 +2701,12 @@ void R_ResetViewRendering3D(void)
 "void main(void)\n"
 "{\n"
 "      int x, y;
-"      myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
+"      myhalf3 color = myhalf3(texture2D(Texture_Screen, ScreenTexCoord));\n"
 "      for (x = -BLUR_X;x <= BLUR_X;x++)
-"      color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
-"      color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
-"      color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
-"      color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
+"      color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
+"      color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
+"      color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
+"      color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
 
 "      gl_FragColor = vec4(color);\n"
 "}\n"
@@ -2796,10 +2828,10 @@ static void R_Water_AddWaterPlane(msurface_t *surface)
        p->materialflags |= surface->texture->currentframe->currentmaterialflags;
        // merge this surface's PVS into the waterplane
        VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
-       if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS
-        && r_refdef.worldmodel->brush.PointInLeaf && r_refdef.worldmodel->brush.PointInLeaf(r_refdef.worldmodel, center)->clusterindex >= 0)
+       if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
+        && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
        {
-               r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
+               r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
                p->pvsvalid = true;
        }
 }
@@ -2863,17 +2895,19 @@ 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;
                        r_refdef.view.cullface_back = GL_BACK;
-                       if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
+                       if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
                        {
                                r_refdef.view.usecustompvs = true;
                                if (p->pvsvalid)
-                                       memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
+                                       memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
                                else
-                                       memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
+                                       memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
                        }
 
                        R_ResetViewRendering3D();
@@ -3300,8 +3334,8 @@ void R_UpdateVariables(void)
        R_Textures_Frame();
 
        r_refdef.farclip = 4096;
-       if (r_refdef.worldmodel)
-               r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
+       if (r_refdef.scene.worldmodel)
+               r_refdef.farclip += VectorDistance(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
        r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
 
        if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
@@ -3386,11 +3420,19 @@ R_RenderView
 */
 void R_RenderView(void)
 {
-       if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
+       if (!r_refdef.scene.entities/* || !r_refdef.scene.worldmodel*/)
                return; //Host_Error ("R_RenderView: NULL worldmodel");
 
        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();
@@ -3436,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)
@@ -3447,15 +3490,15 @@ void R_RenderScene(qboolean addwaterplanes)
                if (r_timereport_active)
                        R_TimeReport("watervis");
 
-               if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
+               if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
                {
-                       r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
+                       r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
                        if (r_timereport_active)
                                R_TimeReport("waterworld");
                }
 
                // don't let sound skip if going slow
-               if (r_refdef.extraupdate)
+               if (r_refdef.scene.extraupdate)
                        S_ExtraUpdate ();
 
                R_DrawModelsAddWaterPlanes();
@@ -3470,7 +3513,7 @@ void R_RenderScene(qboolean addwaterplanes)
        R_ResetViewRendering3D();
 
        // don't let sound skip if going slow
-       if (r_refdef.extraupdate)
+       if (r_refdef.scene.extraupdate)
                S_ExtraUpdate ();
 
        R_MeshQueue_BeginScene();
@@ -3481,17 +3524,17 @@ void R_RenderScene(qboolean addwaterplanes)
        if (r_timereport_active)
                R_TimeReport("visibility");
 
-       Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
+       Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
 
        if (cl.csqc_vidvars.drawworld)
        {
                // don't let sound skip if going slow
-               if (r_refdef.extraupdate)
+               if (r_refdef.scene.extraupdate)
                        S_ExtraUpdate ();
 
-               if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
+               if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
                {
-                       r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
+                       r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
                        if (r_timereport_active)
                                R_TimeReport("worldsky");
                }
@@ -3500,9 +3543,9 @@ void R_RenderScene(qboolean addwaterplanes)
                        R_TimeReport("bmodelsky");
        }
 
-       if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
+       if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
        {
-               r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
+               r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
                if (r_timereport_active)
                        R_TimeReport("worlddepth");
        }
@@ -3513,15 +3556,15 @@ void R_RenderScene(qboolean addwaterplanes)
                        R_TimeReport("modeldepth");
        }
 
-       if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
+       if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
        {
-               r_refdef.worldmodel->Draw(r_refdef.worldentity);
+               r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
                if (r_timereport_active)
                        R_TimeReport("world");
        }
 
        // don't let sound skip if going slow
-       if (r_refdef.extraupdate)
+       if (r_refdef.scene.extraupdate)
                S_ExtraUpdate ();
 
        R_DrawModels();
@@ -3529,7 +3572,7 @@ void R_RenderScene(qboolean addwaterplanes)
                R_TimeReport("models");
 
        // don't let sound skip if going slow
-       if (r_refdef.extraupdate)
+       if (r_refdef.scene.extraupdate)
                S_ExtraUpdate ();
 
        if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
@@ -3539,7 +3582,7 @@ void R_RenderScene(qboolean addwaterplanes)
                R_ResetViewRendering3D();
 
                // don't let sound skip if going slow
-               if (r_refdef.extraupdate)
+               if (r_refdef.scene.extraupdate)
                        S_ExtraUpdate ();
        }
 
@@ -3548,7 +3591,7 @@ void R_RenderScene(qboolean addwaterplanes)
                R_TimeReport("rtlights");
 
        // don't let sound skip if going slow
-       if (r_refdef.extraupdate)
+       if (r_refdef.scene.extraupdate)
                S_ExtraUpdate ();
 
        if (cl.csqc_vidvars.drawworld)
@@ -3613,9 +3656,9 @@ void R_RenderScene(qboolean addwaterplanes)
                qglUseProgramObjectARB(0);CHECKGLERROR
        }
 
-       if (r_refdef.view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
+       if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
        {
-               r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
+               r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
                if (r_timereport_active)
                        R_TimeReport("worlddebug");
                R_DrawModelsDebug();
@@ -3636,7 +3679,7 @@ void R_RenderScene(qboolean addwaterplanes)
        }
 
        // don't let sound skip if going slow
-       if (r_refdef.extraupdate)
+       if (r_refdef.scene.extraupdate)
                S_ExtraUpdate ();
 
        R_ResetViewRendering2D();
@@ -3890,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);
@@ -4045,7 +4089,7 @@ static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1,
 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
 {
        double index, f;
-       index = parms[2] + r_refdef.time * parms[3];
+       index = parms[2] + r_refdef.scene.time * parms[3];
        index -= floor(index);
        switch (func)
        {
@@ -4092,7 +4136,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                if (model->skinscenes)
                {
                        if (model->skinscenes[s].framecount > 1)
-                               s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
+                               s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
                        else
                                s = model->skinscenes[s].firstframe;
                }
@@ -4103,9 +4147,9 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                        // use an alternate animation if the entity's frame is not 0,
                        // and only if the texture has an alternate animation
                        if (ent->frame2 != 0 && t->anim_total[1])
-                               t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
+                               t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
                        else
-                               t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
+                               t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
                }
                texture->currentframe = t;
        }
@@ -4162,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;
@@ -4189,14 +4239,14 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                        break;
                case Q3TCMOD_ROTATE:
                        Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
-                       Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
+                       Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
                        Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
                        break;
                case Q3TCMOD_SCALE:
                        Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
                        break;
                case Q3TCMOD_SCROLL:
-                       Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
+                       Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
                        break;
                case Q3TCMOD_STRETCH:
                        f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
@@ -4317,7 +4367,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                                        // applied to the color
                                        // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
                                        if (ent->model->type == mod_brushq3)
-                                               colorscale *= r_refdef.rtlightstylevalue[0];
+                                               colorscale *= r_refdef.scene.rtlightstylevalue[0];
                                        colorscale *= r_refdef.lightmapintensity;
                                        VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor);
                                        VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
@@ -4407,7 +4457,7 @@ void RSurf_CleanUp(void)
 
 void RSurf_ActiveWorldEntity(void)
 {
-       model_t *model = r_refdef.worldmodel;
+       model_t *model = r_refdef.scene.worldmodel;
        RSurf_CleanUp();
        if (rsurface.array_size < model->surfmesh.num_vertices)
                R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
@@ -4851,9 +4901,9 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta
                                        float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
                                        VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
                                        VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
-                                       normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
-                                       normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
-                                       normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
+                                       normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
+                                       normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
+                                       normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
                                        VectorNormalize(normal);
                                }
                                Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
@@ -4904,7 +4954,7 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta
                                const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
                                for (j = 0;j < surface->num_vertices;j++)
                                {
-                                       scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
+                                       scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
                                        VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
                                }
                        }
@@ -4987,7 +5037,7 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta
        if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
        {
                amplitude = rsurface.texture->tcmods[0].parms[1];
-               animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
+               animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
                for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                {
                        const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
@@ -5379,23 +5429,23 @@ static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t
                                if (surface->lightmapinfo->samples)
                                {
                                        const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
-                                       float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
+                                       float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
                                        VectorScale(lm, scale, c);
                                        if (surface->lightmapinfo->styles[1] != 255)
                                        {
                                                int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
                                                lm += size3;
-                                               scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
+                                               scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
                                                VectorMA(c, scale, lm, c);
                                                if (surface->lightmapinfo->styles[2] != 255)
                                                {
                                                        lm += size3;
-                                                       scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
+                                                       scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
                                                        VectorMA(c, scale, lm, c);
                                                        if (surface->lightmapinfo->styles[3] != 255)
                                                        {
                                                                lm += size3;
-                                                               scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
+                                                               scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
                                                                VectorMA(c, scale, lm, c);
                                                        }
                                                }
@@ -5516,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)
        {
@@ -5529,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);
        }
@@ -5541,7 +5594,7 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **te
        // in Quake3 maps as it causes problems with q3map2 sky tricks,
        // and skymasking also looks very bad when noclipping outside the
        // level, so don't use it then either.
-       if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
+       if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
        {
                GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
                R_Mesh_ColorPointer(NULL, 0, 0);
@@ -5579,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))
        {
@@ -5626,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));
-                       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));
+               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(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);
@@ -5675,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)
@@ -6066,7 +6093,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const
        // if the model is static it doesn't matter what value we give for
        // wantnormals and wanttangents, so this logic uses only rules applicable
        // to a model, knowing that they are meaningless otherwise
-       if (ent == r_refdef.worldentity)
+       if (ent == r_refdef.scene.worldentity)
                RSurf_ActiveWorldEntity();
        else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
                RSurf_ActiveModelEntity(ent, false, false);
@@ -6286,7 +6313,7 @@ void R_DrawDebugModel(entity_render_t *ent)
                }
                for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
                {
-                       if (ent == r_refdef.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
+                       if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
                                continue;
                        rsurface.texture = surface->texture->currentframe;
                        if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
@@ -6296,7 +6323,7 @@ void R_DrawDebugModel(entity_render_t *ent)
                                {
                                        if (!rsurface.texture->currentlayers->depthmask)
                                                GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
-                                       else if (ent == r_refdef.worldentity)
+                                       else if (ent == r_refdef.scene.worldentity)
                                                GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
                                        else
                                                GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
@@ -6364,7 +6391,7 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep
        int i, j, endj, f, flagsmask;
        msurface_t *surface;
        texture_t *t;
-       model_t *model = r_refdef.worldmodel;
+       model_t *model = r_refdef.scene.worldmodel;
        const int maxsurfacelist = 1024;
        int numsurfacelist = 0;
        msurface_t *surfacelist[1024];
@@ -6379,23 +6406,23 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep
                model_brush_lightstyleinfo_t *style;
                for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
                {
-                       if (style->value != r_refdef.lightstylevalue[style->style])
+                       if (style->value != r_refdef.scene.lightstylevalue[style->style])
                        {
                                msurface_t *surfaces = model->data_surfaces;
                                int *list = style->surfacelist;
-                               style->value = r_refdef.lightstylevalue[style->style];
+                               style->value = r_refdef.scene.lightstylevalue[style->style];
                                for (j = 0;j < style->numsurfaces;j++)
                                        surfaces[list[j]].cached_dlight = true;
                        }
                }
        }
 
-       R_UpdateAllTextureInfo(r_refdef.worldentity);
+       R_UpdateAllTextureInfo(r_refdef.scene.worldentity);
        flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
 
        if (debug)
        {
-               R_DrawDebugModel(r_refdef.worldentity);
+               R_DrawDebugModel(r_refdef.scene.worldentity);
                return;
        }
 
@@ -6421,14 +6448,14 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep
                        {
                                // if lightmap parameters changed, rebuild lightmap texture
                                if (surface->cached_dlight)
-                                       R_BuildLightMap(r_refdef.worldentity, surface);
+                                       R_BuildLightMap(r_refdef.scene.worldentity, surface);
                                // add face to draw list
                                surfacelist[numsurfacelist++] = surface;
                                r_refdef.stats.world_triangles += surface->num_triangles;
                                if (numsurfacelist >= maxsurfacelist)
                                {
                                        r_refdef.stats.world_surfaces += numsurfacelist;
-                                       R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
+                                       R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
                                        numsurfacelist = 0;
                                }
                        }
@@ -6436,7 +6463,7 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep
        }
        r_refdef.stats.world_surfaces += numsurfacelist;
        if (numsurfacelist)
-               R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
+               R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
        RSurf_CleanUp();
 }
 
@@ -6455,7 +6482,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
        // if the model is static it doesn't matter what value we give for
        // wantnormals and wanttangents, so this logic uses only rules applicable
        // to a model, knowing that they are meaningless otherwise
-       if (ent == r_refdef.worldentity)
+       if (ent == r_refdef.scene.worldentity)
                RSurf_ActiveWorldEntity();
        else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
                RSurf_ActiveModelEntity(ent, false, false);
@@ -6468,11 +6495,11 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
                model_brush_lightstyleinfo_t *style;
                for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
                {
-                       if (style->value != r_refdef.lightstylevalue[style->style])
+                       if (style->value != r_refdef.scene.lightstylevalue[style->style])
                        {
                                msurface_t *surfaces = model->data_surfaces;
                                int *list = style->surfacelist;
-                               style->value = r_refdef.lightstylevalue[style->style];
+                               style->value = r_refdef.scene.lightstylevalue[style->style];
                                for (j = 0;j < style->numsurfaces;j++)
                                        surfaces[list[j]].cached_dlight = true;
                        }