]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rmain.c
Cvar onChange for qc menu for stable branch
[xonotic/darkplaces.git] / gl_rmain.c
index b57df7c1863269fa9c5b9a64d10de753465c59ee..7b2c7ac6f95677930af4cf7c6ce79a352df1eeda 100644 (file)
@@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "csprogs.h"
 #include "cl_video.h"
 #include "dpsoftrast.h"
+#include "cl_collision.h"
 
 #ifdef SUPPORTD3D
 #include <d3d9.h>
@@ -76,10 +77,10 @@ cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor
 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
 
 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
-cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
-cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
-cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
-cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
+cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light (DEPRECATED)"};
+cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
+cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression) (DEPRECATED)"};
+cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
 
 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
@@ -93,6 +94,7 @@ cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbyne
 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
+cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%,  10 = 100%)" };
 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
@@ -109,18 +111,26 @@ cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
+cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
+cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"};
 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
 
-cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
-cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
+cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
+cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
 
+cvar_t r_fullbright_directed = {0, "r_fullbright_directed", "0", "render fullbright things (unlit worldmodel and EF_FULLBRIGHT entities, but not fullbright shaders) using a constant light direction instead to add more depth while keeping uniform brightness"};
+cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
+cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
+cvar_t r_fullbright_directed_pitch = {0, "r_fullbright_directed_pitch", "20", "constant pitch direction ('height') of the fake light source to use for fullbright"};
+cvar_t r_fullbright_directed_pitch_relative = {0, "r_fullbright_directed_pitch_relative", "0", "whether r_fullbright_directed_pitch is interpreted as absolute (0) or relative (1) pitch"};
+
 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
@@ -131,7 +141,7 @@ cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -
 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
-cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
+cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "0.25", "higher values increase shadowmap quality at a cost of area covered (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
@@ -258,7 +268,6 @@ cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
        {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
 };
 
-extern cvar_t v_glslgamma;
 extern cvar_t v_glslgamma_2d;
 
 extern qboolean v_flipped_state;
@@ -637,9 +646,6 @@ const char *builtinhlslshaderstrings[] =
 0
 };
 
-char *glslshaderstring = NULL;
-char *hlslshaderstring = NULL;
-
 //=======================================================================================================================================================
 
 typedef struct shaderpermutationinfo_s
@@ -651,9 +657,14 @@ shaderpermutationinfo_t;
 
 typedef struct shadermodeinfo_s
 {
-       const char *filename;
+       const char *sourcebasename;
+       const char *extension;
+       const char **builtinshaderstrings;
        const char *pretext;
        const char *name;
+       char *filename;
+       char *builtinstring;
+       int builtincrc;
 }
 shadermodeinfo_t;
 
@@ -695,46 +706,48 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
 };
 
 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
-shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
-{
-       {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
-       {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
-       {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
-       {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
-       {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
-       {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
-       {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
-       {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
-       {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
-       {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
-       {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
-       {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
-       {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
-       {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
-       {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
-       {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
-       {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
-};
-
-shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
-{
-       {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
-       {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
-       {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
-       {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
-       {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
-       {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
-       {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
-       {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
-       {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
-       {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
-       {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
-       {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
-       {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
-       {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
-       {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
-       {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
-       {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
+shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
+{
+       // SHADERLANGUAGE_GLSL
+       {
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
+               {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
+       },
+       // SHADERLANGUAGE_HLSL
+       {
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
+               {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
+       },
 };
 
 struct r_glsl_permutation_s;
@@ -743,7 +756,7 @@ typedef struct r_glsl_permutation_s
        /// hash lookup data
        struct r_glsl_permutation_s *hashnext;
        unsigned int mode;
-       unsigned int permutation;
+       dpuint64 permutation;
 
        /// indicates if we have tried compiling this permutation already
        qboolean compiled;
@@ -954,7 +967,7 @@ qboolean R_CompileShader_CheckStaticParms(void)
                shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
        else \
                shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
-static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
+static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
 {
        shaderstaticparms_count = 0;
 
@@ -982,7 +995,7 @@ r_glsl_permutation_t *r_glsl_permutation;
 /// storage for permutations linked in the hash table
 memexpandablearray_t r_glsl_permutationarray;
 
-static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
+static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
 {
        //unsigned int hashdepth = 0;
        unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
@@ -1028,63 +1041,50 @@ static char *R_ShaderStrCat(const char **strings)
        return string;
 }
 
-static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
+static char *R_ShaderStrCat(const char **strings);
+static void R_InitShaderModeInfo(void)
 {
-       char *shaderstring;
-       if (!filename || !filename[0])
-               return NULL;
-       // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
-       if (!strcmp(filename, "glsl/default.glsl"))
-       {
-               if (builtinonly)
-                       return R_ShaderStrCat(builtinshaderstrings);
-               if (!glslshaderstring)
-               {
-                       glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
-                       if (glslshaderstring)
-                               Con_DPrintf("Loading shaders from file %s...\n", filename);
-                       else
-                               glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
-               }
-               shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
-               memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
-               return shaderstring;
-       }
-       if (!strcmp(filename, "hlsl/default.hlsl"))
+       int i, language;
+       shadermodeinfo_t *modeinfo;
+       // we have a bunch of things to compute that weren't calculated at engine compile time - all filenames should have a crc of the builtin strings to prevent accidental overrides (any customization must be updated to match engine)
+       for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
        {
-               if (builtinonly)
-                       return R_ShaderStrCat(builtinhlslshaderstrings);
-               if (!hlslshaderstring)
+               for (i = 0; i < SHADERMODE_COUNT; i++)
                {
-                       hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
-                       if (hlslshaderstring)
-                               Con_DPrintf("Loading shaders from file %s...\n", filename);
-                       else
-                               hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
+                       char filename[MAX_QPATH];
+                       modeinfo = &shadermodeinfo[language][i];
+                       modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
+                       modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
+                       dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
+                       modeinfo->filename = Mem_strdup(r_main_mempool, filename);
                }
-               shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
-               memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
-               return shaderstring;
        }
-       // we don't have builtin strings for any other files
-       if (builtinonly)
-               return NULL;
-       shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
+}
+
+static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
+{
+       char *shaderstring;
+       // if the mode has no filename we have to return the builtin string
+       if (builtinonly || !modeinfo->filename)
+               return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
+       // note that FS_LoadFile appends a 0 byte to make it a valid string
+       shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
        if (shaderstring)
        {
                if (printfromdisknotice)
-                       Con_DPrintf("from disk %s... ", filename);
+                       Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
                return shaderstring;
        }
-       return shaderstring;
+       // fall back to builtinstring
+       return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
 }
 
-static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
+static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
 {
        int i;
        int ubibind;
        int sampler;
-       shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
+       shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
        char *sourcestring;
        char permutationname[256];
        int vertstrings_count = 0;
@@ -1100,7 +1100,7 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode
        p->program = 0;
 
        permutationname[0] = 0;
-       sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
+       sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
 
        strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
 
@@ -1124,6 +1124,27 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode
                geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
                fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
        }
+       // if we can do #version 120, we should (this adds the invariant keyword)
+       else if(vid.support.glshaderversion >= 120)
+       {
+               vertstrings_list[vertstrings_count++] = "#version 120\n";
+               geomstrings_list[geomstrings_count++] = "#version 120\n";
+               fragstrings_list[fragstrings_count++] = "#version 120\n";
+               vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
+               geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
+               fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
+       }
+       // GLES also adds several things from GLSL120
+       switch(vid.renderpath)
+       {
+       case RENDERPATH_GLES2:
+               vertstrings_list[vertstrings_count++] = "#define GLES\n";
+               geomstrings_list[geomstrings_count++] = "#define GLES\n";
+               fragstrings_list[fragstrings_count++] = "#define GLES\n";
+               break;
+       default:
+               break;
+       }
 
        // the first pretext is which type of shader to compile as
        // (later these will all be bound together as a program object)
@@ -1140,7 +1161,7 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode
        // now add all the permutation pretexts
        for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
        {
-               if (permutation & (1<<i))
+               if (permutation & (1ll<<i))
                {
                        vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
                        geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
@@ -1373,7 +1394,7 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode
                Mem_Free(sourcestring);
 }
 
-static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
+static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
 {
        r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
        if (r_glsl_permutation != perm)
@@ -1393,7 +1414,7 @@ static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int per
                                for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
                                {
                                        // reduce i more quickly whenever it would not remove any bits
-                                       int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
+                                       dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
                                        if (!(permutation & j))
                                                continue;
                                        permutation -= j;
@@ -1435,7 +1456,7 @@ typedef struct r_hlsl_permutation_s
        /// hash lookup data
        struct r_hlsl_permutation_s *hashnext;
        unsigned int mode;
-       unsigned int permutation;
+       dpuint64 permutation;
 
        /// indicates if we have tried compiling this permutation already
        qboolean compiled;
@@ -1522,7 +1543,7 @@ r_hlsl_permutation_t *r_hlsl_permutation;
 /// storage for permutations linked in the hash table
 memexpandablearray_t r_hlsl_permutationarray;
 
-static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
+static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
 {
        //unsigned int hashdepth = 0;
        unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
@@ -1699,10 +1720,10 @@ static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, c
        psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
 }
 
-static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
+static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
 {
        int i;
-       shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
+       shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
        int vertstring_length = 0;
        int geomstring_length = 0;
        int fragstring_length = 0;
@@ -1726,7 +1747,7 @@ static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode
 
        permutationname[0] = 0;
        cachename[0] = 0;
-       sourcestring = R_GetShaderText(modeinfo->filename, true, false);
+       sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
 
        strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
        strlcat(cachename, "hlsl/", sizeof(cachename));
@@ -1755,7 +1776,7 @@ static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode
        // now add all the permutation pretexts
        for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
        {
-               if (permutation & (1<<i))
+               if (permutation & (1ll<<i))
                {
                        vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
                        geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
@@ -1845,7 +1866,7 @@ static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, flo
 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
 
-void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
+void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
 {
        r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
        if (r_hlsl_permutation != perm)
@@ -1862,7 +1883,7 @@ void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutatio
                                for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
                                {
                                        // reduce i more quickly whenever it would not remove any bits
-                                       int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
+                                       dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
                                        if (!(permutation & j))
                                                continue;
                                        permutation -= j;
@@ -1889,7 +1910,7 @@ void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutatio
 }
 #endif
 
-static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
+static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
 {
        DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
        DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
@@ -1900,12 +1921,6 @@ static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int per
 void R_GLSL_Restart_f(void)
 {
        unsigned int i, limit;
-       if (glslshaderstring)
-               Mem_Free(glslshaderstring);
-       glslshaderstring = NULL;
-       if (hlslshaderstring)
-               Mem_Free(hlslshaderstring);
-       hlslshaderstring = NULL;
        switch(vid.renderpath)
        {
        case RENDERPATH_D3D9:
@@ -1968,9 +1983,9 @@ static void R_GLSL_DumpShader_f(void)
        shadermodeinfo_t *modeinfo;
        qfile_t *file;
 
-       for (language = 0;language < 2;language++)
+       for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
        {
-               modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
+               modeinfo = shadermodeinfo[language];
                for (mode = 0;mode < SHADERMODE_COUNT;mode++)
                {
                        // don't dump the same file multiple times (most or all shaders come from the same file)
@@ -1979,7 +1994,7 @@ static void R_GLSL_DumpShader_f(void)
                                        break;
                        if (dupe >= 0)
                                continue;
-                       text = R_GetShaderText(modeinfo[mode].filename, false, true);
+                       text = modeinfo[mode].builtinstring;
                        if (!text)
                                continue;
                        file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
@@ -1998,14 +2013,13 @@ static void R_GLSL_DumpShader_f(void)
                        }
                        else
                                Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
-                       Mem_Free(text);
                }
        }
 }
 
 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
 {
-       unsigned int permutation = 0;
+       dpuint64 permutation = 0;
        if (r_trippy.integer && !notrippy)
                permutation |= SHADERPERMUTATION_TRIPPY;
        permutation |= SHADERPERMUTATION_VIEWTINT;
@@ -2019,7 +2033,7 @@ void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemod
                permutation |= SHADERPERMUTATION_GLOW;
        else if (texturemode == GL_DECAL)
                permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
-       if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
+       if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
                permutation |= SHADERPERMUTATION_GAMMARAMPS;
        if (suppresstexalpha)
                permutation |= SHADERPERMUTATION_REFLECTCUBE;
@@ -2035,7 +2049,7 @@ void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemod
                R_Mesh_TexBind(GL20TU_FIRST , first );
                R_Mesh_TexBind(GL20TU_SECOND, second);
                if (permutation & SHADERPERMUTATION_GAMMARAMPS)
-                       R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
+                       R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
 #endif
                break;
        case RENDERPATH_D3D10:
@@ -2086,7 +2100,7 @@ void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
 
 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
 {
-       unsigned int permutation = 0;
+       dpuint64 permutation = 0;
        if (r_trippy.integer && !notrippy)
                permutation |= SHADERPERMUTATION_TRIPPY;
        if (depthrgb)
@@ -2198,37 +2212,36 @@ static int R_BlendFuncFlags(int src, int dst)
        return r;
 }
 
-void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
+void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdiffuse[3], const float rtlightspecular[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
 {
        // select a permutation of the lighting shader appropriate to this
        // combination of texture, entity, light source, and fogging, only use the
        // minimum features necessary to avoid wasting rendering time in the
        // fragment shader on features that are not being used
-       unsigned int permutation = 0;
+       dpuint64 permutation = 0;
        unsigned int mode = 0;
        int blendfuncflags;
-       static float dummy_colormod[3] = {1, 1, 1};
-       float *colormod = rsurface.colormod;
+       texture_t *t = rsurface.texture;
        float m16f[16];
        matrix4x4_t tempmatrix;
        r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
        if (r_trippy.integer && !notrippy)
                permutation |= SHADERPERMUTATION_TRIPPY;
-       if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
+       if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
                permutation |= SHADERPERMUTATION_ALPHAKILL;
-       if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
+       if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
                permutation |= SHADERPERMUTATION_OCCLUDE;
-       if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
+       if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
                permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
        if (rsurfacepass == RSURFPASS_BACKGROUND)
        {
                // distorted background
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
+               if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
                {
                        mode = SHADERMODE_WATER;
-                       if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
+                       if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
                                permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
-                       if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
+                       if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
                        {
                                // this is the right thing to do for wateralpha
                                GL_BlendFunc(GL_ONE, GL_ZERO);
@@ -2241,10 +2254,10 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                                blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                        }
                }
-               else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
+               else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
                {
                        mode = SHADERMODE_REFRACTION;
-                       if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
+                       if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
                                permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
                        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                        blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -2261,9 +2274,9 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
        }
        else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
        {
-               if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
+               if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
                {
-                       switch(rsurface.texture->offsetmapping)
+                       switch(t->offsetmapping)
                        {
                        case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
                        case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
@@ -2271,7 +2284,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        case OFFSETMAPPING_OFF: break;
                        }
                }
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+               if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
                        permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
                // normalmap (deferred prepass), may use alpha test on diffuse
                mode = SHADERMODE_DEFERREDGEOMETRY;
@@ -2282,9 +2295,9 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
        }
        else if (rsurfacepass == RSURFPASS_RTLIGHT)
        {
-               if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
+               if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
                {
-                       switch(rsurface.texture->offsetmapping)
+                       switch(t->offsetmapping)
                        {
                        case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
                        case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
@@ -2292,21 +2305,21 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        case OFFSETMAPPING_OFF: break;
                        }
                }
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+               if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
                        permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
+               if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
                        permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
                // light source
                mode = SHADERMODE_LIGHTSOURCE;
                if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
                        permutation |= SHADERPERMUTATION_CUBEFILTER;
-               if (diffusescale > 0)
+               if (VectorLength2(rtlightdiffuse) > 0)
                        permutation |= SHADERPERMUTATION_DIFFUSE;
-               if (specularscale > 0)
+               if (VectorLength2(rtlightspecular) > 0)
                        permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
                if (r_refdef.fogenabled)
                        permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
-               if (rsurface.texture->colormapping)
+               if (t->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
                if (r_shadow_usingshadowmap2d)
                {
@@ -2317,69 +2330,18 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        if (r_shadow_shadowmap2ddepthbuffer)
                                permutation |= SHADERPERMUTATION_DEPTHRGB;
                }
-               if (rsurface.texture->reflectmasktexture)
+               if (t->reflectmasktexture)
                        permutation |= SHADERPERMUTATION_REFLECTCUBE;
                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
                blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
                if (vid.allowalphatocoverage)
                        GL_AlphaToCoverage(false);
        }
-       else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
-       {
-               if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
-               {
-                       switch(rsurface.texture->offsetmapping)
-                       {
-                       case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
-                       case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
-                       case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
-                       case OFFSETMAPPING_OFF: break;
-                       }
-               }
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
-                       permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
-                       permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
-               // unshaded geometry (fullbright or ambient model lighting)
-               mode = SHADERMODE_FLATCOLOR;
-               ambientscale = diffusescale = specularscale = 0;
-               if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
-                       permutation |= SHADERPERMUTATION_GLOW;
-               if (r_refdef.fogenabled)
-                       permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
-               if (rsurface.texture->colormapping)
-                       permutation |= SHADERPERMUTATION_COLORMAPPING;
-               if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
-               {
-                       permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
-                       permutation |= SHADERPERMUTATION_SHADOWMAP2D;
-
-                       if (r_shadow_shadowmap2ddepthbuffer)
-                               permutation |= SHADERPERMUTATION_DEPTHRGB;
-               }
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
-                       permutation |= SHADERPERMUTATION_REFLECTION;
-               if (rsurface.texture->reflectmasktexture)
-                       permutation |= SHADERPERMUTATION_REFLECTCUBE;
-               GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
-               blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
-               // when using alphatocoverage, we don't need alphakill
-               if (vid.allowalphatocoverage)
-               {
-                       if (r_transparent_alphatocoverage.integer)
-                       {
-                               GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
-                               permutation &= ~SHADERPERMUTATION_ALPHAKILL;
-                       }
-                       else
-                               GL_AlphaToCoverage(false);
-               }
-       }
-       else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
+       else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
        {
-               if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
+               if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
                {
-                       switch(rsurface.texture->offsetmapping)
+                       switch(t->offsetmapping)
                        {
                        case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
                        case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
@@ -2387,78 +2349,21 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        case OFFSETMAPPING_OFF: break;
                        }
                }
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+               if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
                        permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
+               if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
                        permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
                // directional model lighting
                mode = SHADERMODE_LIGHTDIRECTION;
-               if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
+               if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
                        permutation |= SHADERPERMUTATION_GLOW;
-               permutation |= SHADERPERMUTATION_DIFFUSE;
-               if (specularscale > 0)
+               if (VectorLength2(t->render_modellight_diffuse))
+                       permutation |= SHADERPERMUTATION_DIFFUSE;
+               if (VectorLength2(t->render_modellight_specular) > 0)
                        permutation |= SHADERPERMUTATION_SPECULAR;
                if (r_refdef.fogenabled)
                        permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
-               if (rsurface.texture->colormapping)
-                       permutation |= SHADERPERMUTATION_COLORMAPPING;
-               if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
-               {
-                       permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
-                       permutation |= SHADERPERMUTATION_SHADOWMAP2D;
-
-                       if (r_shadow_shadowmap2ddepthbuffer)
-                               permutation |= SHADERPERMUTATION_DEPTHRGB;
-               }
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
-                       permutation |= SHADERPERMUTATION_REFLECTION;
-               if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
-                       permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
-               if (rsurface.texture->reflectmasktexture)
-                       permutation |= SHADERPERMUTATION_REFLECTCUBE;
-               if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
-               {
-                       permutation |= SHADERPERMUTATION_BOUNCEGRID;
-                       if (r_shadow_bouncegrid_state.directional)
-                               permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
-               }
-               GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
-               blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
-               // when using alphatocoverage, we don't need alphakill
-               if (vid.allowalphatocoverage)
-               {
-                       if (r_transparent_alphatocoverage.integer)
-                       {
-                               GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
-                               permutation &= ~SHADERPERMUTATION_ALPHAKILL;
-                       }
-                       else
-                               GL_AlphaToCoverage(false);
-               }
-       }
-       else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
-       {
-               if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
-               {
-                       switch(rsurface.texture->offsetmapping)
-                       {
-                       case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
-                       case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
-                       case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
-                       case OFFSETMAPPING_OFF: break;
-                       }
-               }
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
-                       permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
-                       permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
-               // ambient model lighting
-               mode = SHADERMODE_LIGHTDIRECTION;
-               if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
-                       permutation |= SHADERPERMUTATION_GLOW;
-               if (r_refdef.fogenabled)
-                       permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
-               if (rsurface.texture->colormapping)
+               if (t->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
                if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
                {
@@ -2468,11 +2373,11 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        if (r_shadow_shadowmap2ddepthbuffer)
                                permutation |= SHADERPERMUTATION_DEPTHRGB;
                }
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
+               if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
                        permutation |= SHADERPERMUTATION_REFLECTION;
-               if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
+               if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
                        permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
-               if (rsurface.texture->reflectmasktexture)
+               if (t->reflectmasktexture)
                        permutation |= SHADERPERMUTATION_REFLECTCUBE;
                if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
                {
@@ -2480,14 +2385,14 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        if (r_shadow_bouncegrid_state.directional)
                                permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
                }
-               GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
-               blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+               GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
+               blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
                // when using alphatocoverage, we don't need alphakill
                if (vid.allowalphatocoverage)
                {
                        if (r_transparent_alphatocoverage.integer)
                        {
-                               GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+                               GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
                                permutation &= ~SHADERPERMUTATION_ALPHAKILL;
                        }
                        else
@@ -2496,9 +2401,9 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
        }
        else
        {
-               if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
+               if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
                {
-                       switch(rsurface.texture->offsetmapping)
+                       switch(t->offsetmapping)
                        {
                        case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
                        case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
@@ -2506,16 +2411,16 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        case OFFSETMAPPING_OFF: break;
                        }
                }
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+               if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
                        permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
+               if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
                        permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
                // lightmapped wall
-               if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
+               if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
                        permutation |= SHADERPERMUTATION_GLOW;
                if (r_refdef.fogenabled)
                        permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
-               if (rsurface.texture->colormapping)
+               if (t->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
                if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
                {
@@ -2525,18 +2430,18 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        if (r_shadow_shadowmap2ddepthbuffer)
                                permutation |= SHADERPERMUTATION_DEPTHRGB;
                }
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
+               if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
                        permutation |= SHADERPERMUTATION_REFLECTION;
-               if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
+               if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
                        permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
-               if (rsurface.texture->reflectmasktexture)
+               if (t->reflectmasktexture)
                        permutation |= SHADERPERMUTATION_REFLECTCUBE;
                if (FAKELIGHT_ENABLED)
                {
                        // fake lightmapping (q1bsp, q3bsp, fullbright map)
                        mode = SHADERMODE_FAKELIGHT;
                        permutation |= SHADERPERMUTATION_DIFFUSE;
-                       if (specularscale > 0)
+                       if (VectorLength2(t->render_lightmap_specular) > 0)
                                permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
                }
                else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
@@ -2547,7 +2452,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        else
                                mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
                        permutation |= SHADERPERMUTATION_DIFFUSE;
-                       if (specularscale > 0)
+                       if (VectorLength2(t->render_lightmap_specular) > 0)
                                permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
                }
                else if (r_glsl_deluxemapping.integer >= 2)
@@ -2558,7 +2463,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        else
                                mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
                        permutation |= SHADERPERMUTATION_DIFFUSE;
-                       if (specularscale > 0)
+                       if (VectorLength2(t->render_lightmap_specular) > 0)
                                permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
                }
                else if (rsurface.uselightmaptexture)
@@ -2577,22 +2482,20 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        if (r_shadow_bouncegrid_state.directional)
                                permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
                }
-               GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
-               blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+               GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
+               blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
                // when using alphatocoverage, we don't need alphakill
                if (vid.allowalphatocoverage)
                {
                        if (r_transparent_alphatocoverage.integer)
                        {
-                               GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+                               GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
                                permutation &= ~SHADERPERMUTATION_ALPHAKILL;
                        }
                        else
                                GL_AlphaToCoverage(false);
                }
        }
-       if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
-               colormod = dummy_colormod;
        if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
                permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
        if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
@@ -2614,11 +2517,11 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                {
                        if (mode == SHADERMODE_LIGHTDIRECTION)
                        {
-                               hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
+                               hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
                        }
                }
-               Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
-               Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
+               Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
+               Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
                Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
                hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
                hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
@@ -2626,54 +2529,52 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                if (mode == SHADERMODE_LIGHTSOURCE)
                {
                        hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
-                       hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
-                       hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
-                       hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
-                       hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
+                       hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
+                       hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
+                       hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
+                       hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
 
                        // additive passes are only darkened by fog, not tinted
                        hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
-                       hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
+                       hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
                }
                else
                {
+                       hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
+                       hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
                        if (mode == SHADERMODE_FLATCOLOR)
                        {
-                               hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
+                               hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
                        }
                        else if (mode == SHADERMODE_LIGHTDIRECTION)
                        {
-                               hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
-                               hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
-                               hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
-                               hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
-                               hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
-                               hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
-                               hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
+                               hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
+                               hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
+                               hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
+                               hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
+                               hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
                        }
                        else
                        {
-                               hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
-                               hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
-                               hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
-                               hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
-                               hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
+                               hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
+                               hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
+                               hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
                        }
                        // additive passes are only darkened by fog, not tinted
                        if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
                                hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
                        else
                                hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
-                       hlslPSSetParameter4f(D3DPSREGISTER_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);
+                       hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
                        hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
                        hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
-                       hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
-                       hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
-                       hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
-                       hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
-                       hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
+                       hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
+                       hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
+                       hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
+                       hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
+                       hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
                        if (mode == SHADERMODE_WATER)
-                               hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
+                               hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
                }
                if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
                {
@@ -2685,15 +2586,15 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
                        hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
                }
-               hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
-               hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
+               hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
+               hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
                hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
-               if (rsurface.texture->pantstexture)
-                       hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
+               if (t->pantstexture)
+                       hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
                else
                        hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
-               if (rsurface.texture->shirttexture)
-                       hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
+               if (t->shirttexture)
+                       hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
                else
                        hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
                hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
@@ -2701,28 +2602,28 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
                hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
                hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
-                               r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
+                               r_glsl_offsetmapping_scale.value*t->offsetscale,
                                max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
                                1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
                                max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
                        );
                hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
-               hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
+               hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
                hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
                hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
 
-               R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
-               R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
-               R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
-               R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
-               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
-               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
-               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
-               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
-               if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
-               if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
-               if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
-               if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
+               R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
+               R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
+               R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
+               R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
+               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
+               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
+               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
+               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
+               if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
+               if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
+               if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
+               if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
                if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
                if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
                R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
@@ -2791,39 +2692,39 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                {
                        if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
                        if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
-                       if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
-                       if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
-                       if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
-                       if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
+                       if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
+                       if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
+                       if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
+                       if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
        
                        // additive passes are only darkened by fog, not tinted
                        if (r_glsl_permutation->loc_FogColor >= 0)
                                qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
-                       if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
+                       if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
                }
                else
                {
                        if (mode == SHADERMODE_FLATCOLOR)
                        {
-                               if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
+                               if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
                        }
                        else if (mode == SHADERMODE_LIGHTDIRECTION)
                        {
-                               if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
-                               if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
-                               if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
-                               if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
-                               if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
-                               if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
-                               if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
+                               if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
+                               if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
+                               if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
+                               if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
+                               if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
+                               if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
+                               if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
                        }
                        else
                        {
-                               if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
-                               if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
-                               if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
-                               if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
-                               if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
+                               if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
+                               if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
+                               if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
+                               if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
+                               if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
                        }
                        // additive passes are only darkened by fog, not tinted
                        if (r_glsl_permutation->loc_FogColor >= 0)
@@ -2833,18 +2734,18 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                                else
                                        qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
                        }
-                       if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(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_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
                        if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
                        if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
-                       if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
-                       if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
-                       if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
-                       if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
-                       if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
-                       if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
-               }
-               if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
-               if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
+                       if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
+                       if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
+                       if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
+                       if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
+                       if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
+                       if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
+               }
+               if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
+               if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
                if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
                if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
                {
@@ -2857,20 +2758,20 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
                }
 
-               if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
-               if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
+               if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
+               if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
                if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
                if (r_glsl_permutation->loc_Color_Pants >= 0)
                {
-                       if (rsurface.texture->pantstexture)
-                               qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
+                       if (t->pantstexture)
+                               qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
                        else
                                qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
                }
                if (r_glsl_permutation->loc_Color_Shirt >= 0)
                {
-                       if (rsurface.texture->shirttexture)
-                               qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
+                       if (t->shirttexture)
+                               qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
                        else
                                qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
                }
@@ -2879,13 +2780,13 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
                if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
                if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
-                               r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
+                               r_glsl_offsetmapping_scale.value*t->offsetscale,
                                max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
                                1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
                                max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
                        );
                if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
-               if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
+               if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
                if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
                if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
                if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegrid_state.matrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
@@ -2894,18 +2795,18 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
                if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
                if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
-               if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
-               if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
-               if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
-               if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
-               if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
-               if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
-               if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
-               if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
-               if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
-               if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
-               if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
-               if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
+               if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
+               if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
+               if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
+               if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
+               if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
+               if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
+               if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
+               if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
+               if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
+               if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
+               if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
+               if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
                if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
                if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
                if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
@@ -2949,56 +2850,54 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                {
                        {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
                        DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
-                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
-                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
-                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
-                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
+                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
+                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
+                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
+                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
        
                        // additive passes are only darkened by fog, not tinted
                        DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
-                       DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
+                       DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
                }
                else
                {
                        if (mode == SHADERMODE_FLATCOLOR)
                        {
-                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
                        }
                        else if (mode == SHADERMODE_LIGHTDIRECTION)
                        {
-                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
-                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
-                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
-                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
-                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
-                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
-                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
                        }
                        else
                        {
-                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
-                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
-                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
-                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
-                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
                        }
+                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
+                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
                        // additive passes are only darkened by fog, not tinted
                        if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
                                DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
                        else
                                DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
-                       DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_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);
+                       DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
                        DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
                        DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
-                       DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
-                       DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
-                       DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
-                       DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
-                       DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
-                       DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
-               }
-               {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
-               {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
+                       DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
+                       DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
+                       DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
+                       DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
+                       DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
+                       DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
+               }
+               {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
+               {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
                {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
                if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
                {
@@ -3011,20 +2910,20 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
                }
 
-               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
-               DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
+               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
+               DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
                DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
                if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
                {
-                       if (rsurface.texture->pantstexture)
-                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
+                       if (t->pantstexture)
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
                        else
                                DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
                }
                if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
                {
-                       if (rsurface.texture->shirttexture)
-                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
+                       if (t->shirttexture)
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
                        else
                                DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
                }
@@ -3033,28 +2932,28 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
                DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
                DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
-                               r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
+                               r_glsl_offsetmapping_scale.value*t->offsetscale,
                                max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
                                1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
                                max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
                        );
                DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
-               DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
+               DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
                DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
                DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
 
-               R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
-               R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
-               R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
-               R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
-               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
-               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
-               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
-               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
-               if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
-               if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
-               if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
-               if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
+               R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
+               R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
+               R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
+               R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
+               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
+               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
+               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
+               if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
+               if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
+               if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
+               if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
+               if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
                if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
                if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
                R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
@@ -3092,7 +2991,7 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
        // combination of texture, entity, light source, and fogging, only use the
        // minimum features necessary to avoid wasting rendering time in the
        // fragment shader on features that are not being used
-       unsigned int permutation = 0;
+       dpuint64 permutation = 0;
        unsigned int mode = 0;
        const float *lightcolorbase = rtlight->currentcolor;
        float ambientscale = rtlight->ambientscale;
@@ -3229,6 +3128,23 @@ void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
        skinframe->loadsequence = r_skinframe.loadsequence;
 }
 
+void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
+{
+       if (s->merged == s->base)
+               s->merged = NULL;
+       R_PurgeTexture(s->stain); s->stain = NULL;
+       R_PurgeTexture(s->merged); s->merged = NULL;
+       R_PurgeTexture(s->base); s->base = NULL;
+       R_PurgeTexture(s->pants); s->pants = NULL;
+       R_PurgeTexture(s->shirt); s->shirt = NULL;
+       R_PurgeTexture(s->nmap); s->nmap = NULL;
+       R_PurgeTexture(s->gloss); s->gloss = NULL;
+       R_PurgeTexture(s->glow); s->glow = NULL;
+       R_PurgeTexture(s->fog); s->fog = NULL;
+       R_PurgeTexture(s->reflect); s->reflect = NULL;
+       s->loadsequence = 0;
+}
+
 void R_SkinFrame_Purge(void)
 {
        int i;
@@ -3238,22 +3154,7 @@ void R_SkinFrame_Purge(void)
                for (s = r_skinframe.hash[i];s;s = s->next)
                {
                        if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
-                       {
-                               if (s->merged == s->base)
-                                       s->merged = NULL;
-                               // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
-                               R_PurgeTexture(s->stain );s->stain  = NULL;
-                               R_PurgeTexture(s->merged);s->merged = NULL;
-                               R_PurgeTexture(s->base  );s->base   = NULL;
-                               R_PurgeTexture(s->pants );s->pants  = NULL;
-                               R_PurgeTexture(s->shirt );s->shirt  = NULL;
-                               R_PurgeTexture(s->nmap  );s->nmap   = NULL;
-                               R_PurgeTexture(s->gloss );s->gloss  = NULL;
-                               R_PurgeTexture(s->glow  );s->glow   = NULL;
-                               R_PurgeTexture(s->fog   );s->fog    = NULL;
-                               R_PurgeTexture(s->reflect);s->reflect = NULL;
-                               s->loadsequence = 0;
-                       }
+                               R_SkinFrame_PurgeSkinFrame(s);
                }
        }
 }
@@ -3318,20 +3219,7 @@ skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewid
                dyntexture = CL_GetDynTexture( basename );
                if (!add && !dyntexture)
                        return NULL;
-               if (item->merged == item->base)
-                       item->merged = NULL;
-               // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
-               R_PurgeTexture(item->stain );item->stain  = NULL;
-               R_PurgeTexture(item->merged);item->merged = NULL;
-               R_PurgeTexture(item->base  );item->base   = NULL;
-               R_PurgeTexture(item->pants );item->pants  = NULL;
-               R_PurgeTexture(item->shirt );item->shirt  = NULL;
-               R_PurgeTexture(item->nmap  );item->nmap   = NULL;
-               R_PurgeTexture(item->gloss );item->gloss  = NULL;
-               R_PurgeTexture(item->glow  );item->glow   = NULL;
-               R_PurgeTexture(item->fog   );item->fog    = NULL;
-       R_PurgeTexture(item->reflect);item->reflect = NULL;
-               item->loadsequence = 0;
+               R_SkinFrame_PurgeSkinFrame(item);
        }
        else if( item->base == NULL )
        {
@@ -3536,9 +3424,10 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        }
 
        // _luma is supported only for tenebrae compatibility
+       // _blend and .blend are supported only for Q3 & QL compatibility, this hack can be removed if better Q3 shader support is implemented
        // _glow is the preferred name
        mymiplevel = savemiplevel;
-       if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
+       if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s.blend", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_blend", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
        {
                skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
 #ifndef USE_GLES2
@@ -4151,13 +4040,11 @@ static void gl_main_start(void)
        r_glsl_permutation = NULL;
        memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
        Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
-       glslshaderstring = NULL;
 #ifdef SUPPORTD3D
        r_hlsl_permutation = NULL;
        memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
        Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
 #endif
-       hlslshaderstring = NULL;
        memset(&r_svbsp, 0, sizeof (r_svbsp));
 
        memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
@@ -4253,13 +4140,11 @@ static void gl_main_shutdown(void)
        r_glsl_permutation = NULL;
        memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
        Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
-       glslshaderstring = NULL;
 #ifdef SUPPORTD3D
        r_hlsl_permutation = NULL;
        memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
        Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
 #endif
-       hlslshaderstring = NULL;
 }
 
 static void gl_main_newmap(void)
@@ -4292,6 +4177,7 @@ void GL_Main_Init(void)
 {
        int i;
        r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
+       R_InitShaderModeInfo();
 
        Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
        Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
@@ -4335,6 +4221,7 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_transparent_useplanardistance);
        Cvar_RegisterVariable(&r_showoverdraw);
        Cvar_RegisterVariable(&r_showbboxes);
+       Cvar_RegisterVariable(&r_showbboxes_client);
        Cvar_RegisterVariable(&r_showsurfaces);
        Cvar_RegisterVariable(&r_showtris);
        Cvar_RegisterVariable(&r_shownormals);
@@ -4349,10 +4236,12 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_draw2d);
        Cvar_RegisterVariable(&r_drawworld);
        Cvar_RegisterVariable(&r_cullentities_trace);
+       Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
        Cvar_RegisterVariable(&r_cullentities_trace_samples);
        Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
        Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
        Cvar_RegisterVariable(&r_cullentities_trace_delay);
+       Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
        Cvar_RegisterVariable(&r_sortentities);
        Cvar_RegisterVariable(&r_drawviewmodel);
        Cvar_RegisterVariable(&r_drawexteriormodel);
@@ -4362,6 +4251,11 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_dynamic);
        Cvar_RegisterVariable(&r_fakelight);
        Cvar_RegisterVariable(&r_fakelight_intensity);
+       Cvar_RegisterVariable(&r_fullbright_directed);
+       Cvar_RegisterVariable(&r_fullbright_directed_ambient);
+       Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
+       Cvar_RegisterVariable(&r_fullbright_directed_pitch);
+       Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
        Cvar_RegisterVariable(&r_fullbright);
        Cvar_RegisterVariable(&r_shadows);
        Cvar_RegisterVariable(&r_shadows_darken);
@@ -4708,7 +4602,13 @@ void *R_FrameData_Alloc(size_t size)
        while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
        {
                // emergency - we ran out of space, allocate more memory
-               newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
+               // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
+               newvalue = r_framedatasize.value * 2.0f;
+               // upper bound based on architecture - if we try to allocate more than this we could overflow, better to loop until we error out on allocation failure
+               if (sizeof(size_t) >= 8)
+                       newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
+               else
+                       newvalue = bound(0.25f, newvalue, (float)(1 << 10));
                // this might not be a growing it, but we'll allocate another buffer every time
                Cvar_SetValueQuick(&r_framedatasize, newvalue);
                R_FrameData_Resize(true);
@@ -5097,155 +4997,88 @@ void R_AnimCache_CacheVisibleEntities(void)
 
 //==================================================================================
 
-extern cvar_t r_overheadsprites_pushback;
-
-static void R_View_UpdateEntityLighting (void)
-{
-       int i;
-       entity_render_t *ent;
-       vec3_t tempdiffusenormal, avg;
-       vec_t f, fa, fd, fdd;
-       qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
-
-       for (i = 0;i < r_refdef.scene.numentities;i++)
-       {
-               ent = r_refdef.scene.entities[i];
-
-               // skip unseen models
-               if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
-                       continue;
-
-               // skip bsp models
-               if (ent->model && ent->model == cl.worldmodel)
-               {
-                       // TODO: use modellight for r_ambient settings on world?
-                       VectorSet(ent->modellight_ambient, 0, 0, 0);
-                       VectorSet(ent->modellight_diffuse, 0, 0, 0);
-                       VectorSet(ent->modellight_lightdir, 0, 0, 1);
-                       continue;
-               }
-               
-               if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
-               {
-                       // aleady updated by CSQC
-                       // TODO: force modellight on BSP models in this case?
-                       VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
-               }
-               else
-               {
-                       // fetch the lighting from the worldmodel data
-                       VectorClear(ent->modellight_ambient);
-                       VectorClear(ent->modellight_diffuse);
-                       VectorClear(tempdiffusenormal);
-                       if (ent->flags & RENDER_LIGHT)
-                       {
-                               vec3_t org;
-                               Matrix4x4_OriginFromMatrix(&ent->matrix, org);
-
-                               // complete lightning for lit sprites
-                               // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
-                               if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
-                               {
-                                       if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
-                                               org[2] = org[2] + r_overheadsprites_pushback.value;
-                                       R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
-                               }
-                               else
-                                       R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
-
-                               if(ent->flags & RENDER_EQUALIZE)
-                               {
-                                       // first fix up ambient lighting...
-                                       if(r_equalize_entities_minambient.value > 0)
-                                       {
-                                               fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
-                                               if(fd > 0)
-                                               {
-                                                       fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
-                                                       if(fa < r_equalize_entities_minambient.value * fd)
-                                                       {
-                                                               // solve:
-                                                               //   fa'/fd' = minambient
-                                                               //   fa'+0.25*fd' = fa+0.25*fd
-                                                               //   ...
-                                                               //   fa' = fd' * minambient
-                                                               //   fd'*(0.25+minambient) = fa+0.25*fd
-                                                               //   ...
-                                                               //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
-                                                               //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
-                                                               //   ...
-                                                               fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
-                                                               f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
-                                                               VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
-                                                               VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
-                                                       }
-                                               }
-                                       }
-
-                                       if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
-                                       {
-                                               fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
-                                               fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
-                                               f = fa + 0.25 * fd;
-                                               if(f > 0)
-                                               {
-                                                       // adjust brightness and saturation to target
-                                                       avg[0] = avg[1] = avg[2] = fa / f;
-                                                       VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
-                                                       avg[0] = avg[1] = avg[2] = fd / f;
-                                                       VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
-                                               }
-                                       }
-                               }
-                       }
-                       else // highly rare
-                               VectorSet(ent->modellight_ambient, 1, 1, 1);
-               }
-
-               // move the light direction into modelspace coordinates for lighting code
-               Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
-               if(VectorLength2(ent->modellight_lightdir) == 0)
-                       VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
-               VectorNormalize(ent->modellight_lightdir);
-       }
-}
-
-#define MAX_LINEOFSIGHTTRACES 64
-
-static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
+qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
 {
        int i;
+       vec3_t eyemins, eyemaxs;
        vec3_t boxmins, boxmaxs;
        vec3_t start;
        vec3_t end;
        dp_model_t *model = r_refdef.scene.worldmodel;
+       static vec3_t positions[] = {
+               { 0.5f, 0.5f, 0.5f },
+               { 0.0f, 0.0f, 0.0f },
+               { 0.0f, 0.0f, 1.0f },
+               { 0.0f, 1.0f, 0.0f },
+               { 0.0f, 1.0f, 1.0f },
+               { 1.0f, 0.0f, 0.0f },
+               { 1.0f, 0.0f, 1.0f },
+               { 1.0f, 1.0f, 0.0f },
+               { 1.0f, 1.0f, 1.0f },
+       };
+
+       // sample count can be set to -1 to skip this logic, for flicker-prone objects
+       if (numsamples < 0)
+               return true;
+
+       // view origin is not used for culling in portal/reflection/refraction renders or isometric views
+       if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
+               return true;
 
-       if (!model || !model->brush.TraceLineOfSight)
+       if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
                return true;
 
+       // expand the eye box a little
+       eyemins[0] = eye[0] - eyejitter;
+       eyemaxs[0] = eye[0] + eyejitter;
+       eyemins[1] = eye[1] - eyejitter;
+       eyemaxs[1] = eye[1] + eyejitter;
+       eyemins[2] = eye[2] - eyejitter;
+       eyemaxs[2] = eye[2] + eyejitter;
        // expand the box a little
-       boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
-       boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
-       boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
-       boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
-       boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
-       boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
-
-       // return true if eye is inside enlarged box
-       if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
+       boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
+       boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
+       boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
+       boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
+       boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
+       boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
+
+       // return true if eye overlaps enlarged box
+       if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
                return true;
 
-       // try center
-       VectorCopy(eye, start);
-       VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
-       if (model->brush.TraceLineOfSight(model, start, end))
+       // try specific positions in the box first - note that these can be cached
+       if (r_cullentities_trace_entityocclusion.integer)
+       {
+               for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
+               {
+                       VectorCopy(eye, start);
+                       end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
+                       end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
+                       end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
+                       //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
+                       trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
+                       // not picky - if the trace ended anywhere in the box we're good
+                       if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
+                               return true;
+               }
+       }
+       else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
                return true;
 
        // try various random positions
-       for (i = 0;i < numsamples;i++)
+       for (i = 0; i < numsamples; i++)
        {
+               VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
                VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
-               if (model->brush.TraceLineOfSight(model, start, end))
+               if (r_cullentities_trace_entityocclusion.integer)
+               {
+                       trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
+                       // not picky - if the trace ended anywhere in the box we're good
+                       if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
+                               return true;
+               }
+               else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
                        return true;
        }
 
@@ -5294,22 +5127,19 @@ static void R_View_UpdateEntityVisible (void)
                                r_refdef.viewcache.entityvisible[i] = true;
                }
        }
-       if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
-               // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
+       if (r_cullentities_trace.integer)
        {
                for (i = 0;i < r_refdef.scene.numentities;i++)
                {
                        if (!r_refdef.viewcache.entityvisible[i])
                                continue;
                        ent = r_refdef.scene.entities[i];
-                       if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
+                       if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
                        {
-                               samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
-                               if (samples < 0)
-                                       continue; // temp entities do pvs only
-                               if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
+                               samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
+                               if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
                                        ent->last_trace_visibility = realtime;
-                               if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
+                               if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
                                        r_refdef.viewcache.entityvisible[i] = 0;
                        }
                }
@@ -5433,7 +5263,7 @@ void R_HDR_UpdateIrisAdaptation(const vec3_t point)
                        p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
                        p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
                        p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
-                       R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
+                       R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
                        d = DotProduct(forward, diffusenormal);
                        brightness += VectorLength(ambient);
                        if (d > 0)
@@ -5664,7 +5494,6 @@ static void R_View_UpdateWithScissor(const int *myscissor)
        R_View_SetFrustum(myscissor);
        R_View_WorldVisibility(r_refdef.view.useclipplane);
        R_View_UpdateEntityVisible();
-       R_View_UpdateEntityLighting();
 }
 
 static void R_View_Update(void)
@@ -5673,7 +5502,6 @@ static void R_View_Update(void)
        R_View_SetFrustum(NULL);
        R_View_WorldVisibility(r_refdef.view.useclipplane);
        R_View_UpdateEntityVisible();
-       R_View_UpdateEntityLighting();
 }
 
 float viewscalefpsadjusted = 1.0f;
@@ -6398,6 +6226,7 @@ static void R_Bloom_StartFrame(void)
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GLES1:
+               return; // don't bother
        case RENDERPATH_GLES2:
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
@@ -6474,7 +6303,7 @@ static void R_Bloom_StartFrame(void)
                Cvar_SetValueQuick(&r_damageblur, 0);
        }
 
-       if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
+       if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || !vid_gammatables_trivial)
         && !r_bloom.integer
         && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
         && !useviewfbo
@@ -6638,6 +6467,7 @@ static void R_Bloom_MakeTexture(void)
        r_fb.bloomindex = 0;
        R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
        R_SetViewport(&r_fb.bloomviewport);
+       GL_CullFace(GL_NONE);
        GL_DepthTest(false);
        GL_BlendFunc(GL_ONE, GL_ZERO);
        GL_Color(colorscale, colorscale, colorscale, 1);
@@ -6761,7 +6591,7 @@ static void R_Bloom_MakeTexture(void)
 
 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
 {
-       unsigned int permutation;
+       dpuint64 permutation;
        float uservecs[4][4];
 
        R_EntityMatrix(&identitymatrix);
@@ -6777,7 +6607,7 @@ static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortext
                permutation =
                          (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
                        | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
-                       | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
+                       | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
                        | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
                        | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
 
@@ -7080,7 +6910,7 @@ void R_UpdateVariables(void)
 {
        R_Textures_Frame();
 
-       r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
+       r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
 
        r_refdef.farclip = r_farclip_base.value;
        if (r_refdef.scene.worldmodel)
@@ -7098,14 +6928,14 @@ void R_UpdateVariables(void)
        r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
        r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
        r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
-       r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
+       r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
        if (FAKELIGHT_ENABLED)
        {
-               r_refdef.lightmapintensity *= r_fakelight_intensity.value;
+               r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
        }
        else if (r_refdef.scene.worldmodel)
        {
-               r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
+               r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
        }
        if (r_showsurfaces.integer)
        {
@@ -7113,7 +6943,7 @@ void R_UpdateVariables(void)
                r_refdef.scene.rtworldshadows = false;
                r_refdef.scene.rtdlight = false;
                r_refdef.scene.rtdlightshadows = false;
-               r_refdef.lightmapintensity = 0;
+               r_refdef.scene.lightmapintensity = 0;
        }
 
        r_gpuskeletal = false;
@@ -7126,7 +6956,7 @@ void R_UpdateVariables(void)
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
        case RENDERPATH_GLES2:
-               if(v_glslgamma.integer && !vid_gammatables_trivial)
+               if(!vid_gammatables_trivial)
                {
                        if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
                        {
@@ -7250,7 +7080,7 @@ void R_RenderView(void)
        if (r_timereport_active)
                R_TimeReport("start");
        r_textureframe++; // used only by R_GetCurrentTexture
-       rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
+       rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
 
        if(R_CompileShader_CheckStaticParms())
                R_GLSL_Restart_f();
@@ -7393,7 +7223,7 @@ void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortex
 
 extern cvar_t cl_locs_show;
 static void R_DrawLocs(void);
-static void R_DrawEntityBBoxes(void);
+static void R_DrawEntityBBoxes(prvm_prog_t *prog);
 static void R_DrawModelDecals(void);
 extern cvar_t cl_decals_newsystem;
 extern qboolean r_shadow_usingdeferredprepass;
@@ -7500,7 +7330,7 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
        if (r_refdef.scene.extraupdate)
                S_ExtraUpdate ();
 
-       if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
+       if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
        {
                R_ResetViewRendering3D(fbo, depthtexture, colortexture);
                R_Shadow_DrawModelShadows();
@@ -7521,7 +7351,7 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
        if (r_refdef.scene.extraupdate)
                S_ExtraUpdate ();
 
-       if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
+       if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
        {
                R_ResetViewRendering3D(fbo, depthtexture, colortexture);
                R_Shadow_DrawModelShadows();
@@ -7553,10 +7383,6 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
                R_DrawExplosions();
                if (r_timereport_active)
                        R_TimeReport("explosions");
-
-               R_DrawLightningBeams();
-               if (r_timereport_active)
-                       R_TimeReport("lightning");
        }
 
        if (cl.csqc_loaded)
@@ -7578,11 +7404,17 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
                                R_TimeReport("portals");
                }
 
+               if (r_showbboxes_client.value > 0)
+               {
+                       R_DrawEntityBBoxes(CLVM_prog);
+                       if (r_timereport_active)
+                               R_TimeReport("clbboxes");
+               }
                if (r_showbboxes.value > 0)
                {
-                       R_DrawEntityBBoxes();
+                       R_DrawEntityBBoxes(SVVM_prog);
                        if (r_timereport_active)
-                               R_TimeReport("bboxes");
+                               R_TimeReport("svbboxes");
                }
        }
 
@@ -7646,31 +7478,66 @@ static const unsigned short bboxelements[36] =
        1, 0, 2, 1, 2, 3,
 };
 
+#define BBOXEDGES 13
+static const float bboxedges[BBOXEDGES][6] = 
+{
+       // whole box
+       { 0, 0, 0, 1, 1, 1 },
+       // bottom edges
+       { 0, 0, 0, 0, 1, 0 },
+       { 0, 0, 0, 1, 0, 0 },
+       { 0, 1, 0, 1, 1, 0 },
+       { 1, 0, 0, 1, 1, 0 },
+       // top edges
+       { 0, 0, 1, 0, 1, 1 },
+       { 0, 0, 1, 1, 0, 1 },
+       { 0, 1, 1, 1, 1, 1 },
+       { 1, 0, 1, 1, 1, 1 },
+       // vertical edges
+       { 0, 0, 0, 0, 0, 1 },
+       { 1, 0, 0, 1, 0, 1 },
+       { 0, 1, 0, 0, 1, 1 },
+       { 1, 1, 0, 1, 1, 1 },
+};
+
 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
 {
-       int i;
-       float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
+       int numvertices = BBOXEDGES * 8;
+       float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
+       int numtriangles = BBOXEDGES * 12;
+       unsigned short elements[BBOXEDGES * 36];
+       int i, edge;
+       float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
 
-       RSurf_ActiveWorldEntity();
+       RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
 
        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        GL_DepthMask(false);
        GL_DepthRange(0, 1);
        GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
-//     R_Mesh_ResetTextureState();
 
-       vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
-       vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
-       vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
-       vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
-       vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
-       vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
-       vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
-       vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
-       R_FillColors(color4f, 8, cr, cg, cb, ca);
+       for (edge = 0; edge < BBOXEDGES; edge++)
+       {
+               for (i = 0; i < 3; i++)
+               {
+                       edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
+                       edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
+               }
+               vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
+               vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
+               vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
+               vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
+               vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
+               vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
+               vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
+               vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
+               for (i = 0; i < 36; i++)
+                       elements[edge * 36 + i] = edge * 8 + bboxelements[i];
+       }
+       R_FillColors(color4f, numvertices, cr, cg, cb, ca);
        if (r_refdef.fogenabled)
        {
-               for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
+               for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
                {
                        f1 = RSurf_FogVertex(v);
                        f2 = 1 - f1;
@@ -7679,23 +7546,20 @@ static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float c
                        c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
                }
        }
-       R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
+       R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
        R_Mesh_ResetTextureState();
        R_SetupShader_Generic_NoTexture(false, false);
-       R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
+       R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
 }
 
 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
-       prvm_prog_t *prog = SVVM_prog;
+       // hacky overloading of the parameters
+       prvm_prog_t *prog = (prvm_prog_t *)rtlight;
        int i;
        float color[4];
        prvm_edict_t *edict;
 
-       // this function draws bounding boxes of server entities
-       if (!sv.active)
-               return;
-
        GL_CullFace(GL_NONE);
        R_SetupShader_Generic_NoTexture(false, false);
 
@@ -7712,37 +7576,37 @@ static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtligh
                        case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
                        default:             Vector4Set(color, 0, 0, 0, 0.50);break;
                }
-               color[3] *= r_showbboxes.value;
+               if (prog == CLVM_prog)
+                       color[3] *= r_showbboxes_client.value;
+               else
+                       color[3] *= r_showbboxes.value;
                color[3] = bound(0, color[3], 1);
                GL_DepthTest(!r_showdisabledepthtest.integer);
-               GL_CullFace(r_refdef.view.cullface_front);
                R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
        }
 }
 
-static void R_DrawEntityBBoxes(void)
+static void R_DrawEntityBBoxes(prvm_prog_t *prog)
 {
        int i;
        prvm_edict_t *edict;
        vec3_t center;
-       prvm_prog_t *prog = SVVM_prog;
 
-       // this function draws bounding boxes of server entities
-       if (!sv.active)
+       if (prog == NULL)
                return;
 
-       for (i = 0;i < prog->num_edicts;i++)
+       for (i = 0; i < prog->num_edicts; i++)
        {
                edict = PRVM_EDICT_NUM(i);
                if (edict->priv.server->free)
                        continue;
                // exclude the following for now, as they don't live in world coordinate space and can't be solid:
-               if(PRVM_serveredictedict(edict, tag_entity) != 0)
+               if (PRVM_serveredictedict(edict, tag_entity) != 0)
                        continue;
-               if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
+               if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
                        continue;
                VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
-               R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
+               R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
        }
 }
 
@@ -7806,7 +7670,7 @@ static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const
                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
                GL_DepthMask(false);
        }
-       else if (rsurface.colormod[3] < 1)
+       else if (ent->alpha < 1)
        {
                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                GL_DepthMask(false);
@@ -7823,10 +7687,10 @@ static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const
        memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
        for (i = 0, c = color4f;i < 6;i++, c += 4)
        {
-               c[0] *= rsurface.colormod[0];
-               c[1] *= rsurface.colormod[1];
-               c[2] *= rsurface.colormod[2];
-               c[3] *= rsurface.colormod[3];
+               c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
+               c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
+               c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
+               c[3] *= ent->alpha;
        }
        if (r_refdef.fogenabled)
        {
@@ -8169,10 +8033,11 @@ static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
 
 texture_t *R_GetCurrentTexture(texture_t *t)
 {
-       int i;
+       int i, q;
        const entity_render_t *ent = rsurface.entity;
        dp_model_t *model = ent->model; // when calling this, ent must not be NULL
        q3shaderinfo_layer_tcmod_t *tcmod;
+       float specularscale = 0.0f;
 
        if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
                return t->currentframe;
@@ -8227,36 +8092,124 @@ texture_t *R_GetCurrentTexture(texture_t *t)
                if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
                        R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
                t->currentskinframe = r_qwskincache[i].skinframe;
-               if (t->currentskinframe == NULL)
-                       t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
+               if (t->materialshaderpass && t->currentskinframe == NULL)
+                       t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
        }
-       else if (t->numskinframes >= 2)
-               t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
-       if (t->backgroundnumskinframes >= 2)
-               t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
+       else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
+               t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
+       if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
+               t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
 
        t->currentmaterialflags = t->basematerialflags;
-       t->currentalpha = rsurface.colormod[3] * t->basealpha;
+       t->currentalpha = rsurface.entity->alpha * t->basealpha;
        if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
                t->currentalpha *= r_wateralpha.value;
        if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
                t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
        if(!r_fb.water.enabled || r_refdef.view.isoverlay)
                t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
-       if (!(rsurface.ent_flags & RENDER_LIGHT))
-               t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
+
+       // decide on which type of lighting to use for this surface
+       if (rsurface.entity->render_modellight_forced)
+               t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
+       if (rsurface.entity->render_rtlight_disabled)
+               t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
+       if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
+       {
+               // some CUSTOMBLEND blendfuncs are too weird for anything but fullbright rendering, and even then we have to ignore colormod and view colorscale
+               t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NORTLIGHT;
+               for (q = 0; q < 3; q++)
+               {
+                       t->render_glowmod[q] = rsurface.entity->glowmod[q];
+                       t->render_modellight_lightdir[q] = q == 2;
+                       t->render_modellight_ambient[q] = 1;
+                       t->render_modellight_diffuse[q] = 0;
+                       t->render_modellight_specular[q] = 0;
+                       t->render_lightmap_ambient[q] = 0;
+                       t->render_lightmap_diffuse[q] = 0;
+                       t->render_lightmap_specular[q] = 0;
+                       t->render_rtlight_diffuse[q] = 0;
+                       t->render_rtlight_specular[q] = 0;
+               }
+       }
+       else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
+       {
+               // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
+               t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
+               for (q = 0; q < 3; q++)
+               {
+                       t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
+                       t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
+                       t->render_modellight_lightdir[q] = q == 2;
+                       t->render_modellight_diffuse[q] = 0;
+                       t->render_modellight_specular[q] = 0;
+                       t->render_lightmap_ambient[q] = 0;
+                       t->render_lightmap_diffuse[q] = 0;
+                       t->render_lightmap_specular[q] = 0;
+                       t->render_rtlight_diffuse[q] = 0;
+                       t->render_rtlight_specular[q] = 0;
+               }
+       }
        else if (FAKELIGHT_ENABLED)
        {
                // no modellight if using fakelight for the map
+               t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
+               for (q = 0; q < 3; q++)
+               {
+                       t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
+                       t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
+                       t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
+                       t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
+                       t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
+                       t->render_lightmap_ambient[q] = 0;
+                       t->render_lightmap_diffuse[q] = 0;
+                       t->render_lightmap_specular[q] = 0;
+                       t->render_rtlight_diffuse[q] = 0;
+                       t->render_rtlight_specular[q] = 0;
+               }
+       }
+       else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
+       {
+               // ambient + single direction light (modellight)
+               t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
+               for (q = 0; q < 3; q++)
+               {
+                       t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
+                       t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
+                       t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
+                       t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
+                       t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
+                       t->render_lightmap_ambient[q] = 0;
+                       t->render_lightmap_diffuse[q] = 0;
+                       t->render_lightmap_specular[q] = 0;
+                       t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
+                       t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
+               }
        }
-       else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
+       else
        {
-               // pick a model lighting mode
-               if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
-                       t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
-               else
-                       t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
+               // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
+               for (q = 0; q < 3; q++)
+               {
+                       t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
+                       t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q] * r_refdef.view.colorscale;
+                       t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
+                       t->render_modellight_diffuse[q] = 0;
+                       t->render_modellight_specular[q] = 0;
+                       t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
+                       t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
+                       t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
+                       t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
+                       t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
+               }
+       }
+
+       for (q = 0; q < 3; q++)
+       {
+               t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
+               t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
        }
+
        if (rsurface.ent_flags & RENDER_ADDITIVE)
                t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
        else if (t->currentalpha < 1)
@@ -8268,7 +8221,7 @@ texture_t *R_GetCurrentTexture(texture_t *t)
                t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
        if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
                t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
-       if (t->backgroundnumskinframes)
+       if (t->backgroundshaderpass)
                t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
        if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
        {
@@ -8297,12 +8250,11 @@ texture_t *R_GetCurrentTexture(texture_t *t)
                Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
        }
 
-       for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
-               R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
-       for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
-               R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
+       if (t->materialshaderpass)
+               for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
+                       R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
 
-       t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
+       t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
        if (t->currentskinframe->qpixels)
                R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
        t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
@@ -8317,8 +8269,10 @@ texture_t *R_GetCurrentTexture(texture_t *t)
        t->glowtexture = t->currentskinframe->glow;
        t->fogtexture = t->currentskinframe->fog;
        t->reflectmasktexture = t->currentskinframe->reflect;
-       if (t->backgroundnumskinframes)
+       if (t->backgroundshaderpass)
        {
+               for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
+                       R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
                t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
                t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
                t->backgroundglosstexture = r_texture_black;
@@ -8340,7 +8294,6 @@ texture_t *R_GetCurrentTexture(texture_t *t)
        }
        t->specularpower = r_shadow_glossexponent.value;
        // TODO: store reference values for these in the texture?
-       t->specularscale = 0;
        if (r_shadow_gloss.integer > 0)
        {
                if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
@@ -8349,20 +8302,19 @@ texture_t *R_GetCurrentTexture(texture_t *t)
                        {
                                t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
                                t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
-                               t->specularscale = r_shadow_glossintensity.value;
+                               specularscale = r_shadow_glossintensity.value;
                        }
                }
                else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
                {
                        t->glosstexture = r_texture_white;
                        t->backgroundglosstexture = r_texture_white;
-                       t->specularscale = r_shadow_gloss2intensity.value;
+                       specularscale = r_shadow_gloss2intensity.value;
                        t->specularpower = r_shadow_gloss2exponent.value;
                }
        }
-       t->specularscale *= t->specularscalemod;
+       specularscale *= t->specularscalemod;
        t->specularpower *= t->specularpowermod;
-       t->rtlightambient = 0;
 
        // lightmaps mode looks bad with dlights using actual texturing, so turn
        // off the colormap and glossmap, but leave the normalmap on as it still
@@ -8383,12 +8335,20 @@ texture_t *R_GetCurrentTexture(texture_t *t)
                        t->backgroundnmaptexture = r_texture_blanknormalmap;
                t->backgroundglosstexture = r_texture_black;
                t->backgroundglowtexture = NULL;
-               t->specularscale = 0;
-               t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
+               specularscale = 0;
+               t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
+       }
+
+       if (specularscale != 1.0f)
+       {
+               for (q = 0; q < 3; q++)
+               {
+                       t->render_modellight_specular[q] *= specularscale;
+                       t->render_lightmap_specular[q] *= specularscale;
+                       t->render_rtlight_specular[q] *= specularscale;
+               }
        }
 
-       Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
-       VectorClear(t->dlightcolor);
        t->currentnumlayers = 0;
        if (t->currentmaterialflags & MATERIALFLAG_WALL)
        {
@@ -8414,54 +8374,38 @@ texture_t *R_GetCurrentTexture(texture_t *t)
                        blendfunc1 = GL_ONE;
                        blendfunc2 = GL_ZERO;
                }
-               // don't colormod evilblend textures
-               if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
-                       VectorSet(t->lightmapcolor, 1, 1, 1);
                depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
-               if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
+               if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
                {
-                       // fullbright is not affected by r_refdef.lightmapintensity
-                       R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
-                       if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
-                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
-                       if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
-                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
+                       // basic lit geometry
+                       R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
+                       // add pants/shirt if needed
+                       if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
+                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2] * t->render_lightmap_diffuse[2], t->currentalpha);
+                       if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
+                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
                }
                else
                {
-                       vec3_t ambientcolor;
-                       float colorscale;
-                       // set the color tint used for lights affecting this surface
-                       VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
-                       colorscale = 2;
-                       // q3bsp has no lightmap updates, so the lightstylevalue that
-                       // would normally be baked into the lightmap must be
-                       // applied to the color
-                       // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
-                       if (model->type == mod_brushq3)
-                               colorscale *= r_refdef.scene.rtlightstylevalue[0];
-                       colorscale *= r_refdef.lightmapintensity;
-                       VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
-                       VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
                        // basic lit geometry
-                       R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
+                       R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
                        // add pants/shirt if needed
-                       if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
-                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
-                       if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
-                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
+                       if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
+                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2]  * t->render_lightmap_diffuse[2], t->currentalpha);
+                       if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
+                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
                        // now add ambient passes if needed
-                       if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
+                       if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
                        {
-                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
-                               if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
-                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
-                               if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
-                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
+                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2], t->currentalpha);
+                               if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
+                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_ambient[0], t->render_colormap_pants[1] * t->render_lightmap_ambient[1], t->render_colormap_pants[2] * t->render_lightmap_ambient[2], t->currentalpha);
+                               if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
+                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_ambient[0], t->render_colormap_shirt[1] * t->render_lightmap_ambient[1], t->render_colormap_shirt[2] * t->render_lightmap_ambient[2], t->currentalpha);
                        }
                }
                if (t->glowtexture != NULL && !gl_lightmaps.integer)
-                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
+                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2], t->currentalpha);
                if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
                {
                        // if this is opaque use alpha blend which will darken the earlier
@@ -8475,7 +8419,7 @@ texture_t *R_GetCurrentTexture(texture_t *t)
                        // were darkened by fog already, and we should not add fog color
                        // (because the background was not darkened, there is no fog color
                        // that was lost behind it).
-                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
+                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
                }
        }
 
@@ -8484,168 +8428,33 @@ texture_t *R_GetCurrentTexture(texture_t *t)
 
 rsurfacestate_t rsurface;
 
-void RSurf_ActiveWorldEntity(void)
+void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
 {
-       dp_model_t *model = r_refdef.scene.worldmodel;
-       //if (rsurface.entity == r_refdef.scene.worldentity)
+       dp_model_t *model = ent->model;
+       //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
        //      return;
-       rsurface.entity = r_refdef.scene.worldentity;
-       rsurface.skeleton = NULL;
-       memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
-       rsurface.ent_skinnum = 0;
-       rsurface.ent_qwskin = -1;
-       rsurface.ent_flags = r_refdef.scene.worldentity->flags;
-       rsurface.shadertime = r_refdef.scene.time;
-       rsurface.matrix = identitymatrix;
-       rsurface.inversematrix = identitymatrix;
-       rsurface.matrixscale = 1;
-       rsurface.inversematrixscale = 1;
-       R_EntityMatrix(&identitymatrix);
-       VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
-       Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
-       rsurface.fograngerecip = r_refdef.fograngerecip;
-       rsurface.fogheightfade = r_refdef.fogheightfade;
-       rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
+       rsurface.entity = (entity_render_t *)ent;
+       rsurface.skeleton = ent->skeleton;
+       memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
+       rsurface.ent_skinnum = ent->skinnum;
+       rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
+       rsurface.ent_flags = ent->flags;
+       if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
+               rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
+       rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
+       rsurface.matrix = ent->matrix;
+       rsurface.inversematrix = ent->inversematrix;
+       rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
+       rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
+       R_EntityMatrix(&rsurface.matrix);
+       Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
+       Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
+       rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
+       rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
+       rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
        rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
-       VectorSet(rsurface.modellight_ambient, 0, 0, 0);
-       VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
-       VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
-       VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
-       VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
-       VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
-       rsurface.colormod[3] = 1;
-       VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
-       memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
-       rsurface.frameblend[0].lerp = 1;
-       rsurface.ent_alttextures = false;
-       rsurface.basepolygonfactor = r_refdef.polygonfactor;
-       rsurface.basepolygonoffset = r_refdef.polygonoffset;
-       rsurface.entityskeletaltransform3x4 = NULL;
-       rsurface.entityskeletaltransform3x4buffer = NULL;
-       rsurface.entityskeletaltransform3x4offset = 0;
-       rsurface.entityskeletaltransform3x4size = 0;;
-       rsurface.entityskeletalnumtransforms = 0;
-       rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
-       rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
-       rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
-       rsurface.modelsvector3f = model->surfmesh.data_svector3f;
-       rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
-       rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
-       rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
-       rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
-       rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
-       rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
-       rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
-       rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
-       rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
-       rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
-       rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
-       rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
-       rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
-       rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
-       rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
-       rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
-       rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
-       rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
-       rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
-       rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
-       rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
-       rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
-       rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
-       rsurface.modelelement3i = model->surfmesh.data_element3i;
-       rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
-       rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
-       rsurface.modelelement3s = model->surfmesh.data_element3s;
-       rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
-       rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
-       rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
-       rsurface.modelnumvertices = model->surfmesh.num_vertices;
-       rsurface.modelnumtriangles = model->surfmesh.num_triangles;
-       rsurface.modelsurfaces = model->data_surfaces;
-       rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
-       rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
-       rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
-       rsurface.modelgeneratedvertex = false;
-       rsurface.batchgeneratedvertex = false;
-       rsurface.batchfirstvertex = 0;
-       rsurface.batchnumvertices = 0;
-       rsurface.batchfirsttriangle = 0;
-       rsurface.batchnumtriangles = 0;
-       rsurface.batchvertex3f  = NULL;
-       rsurface.batchvertex3f_vertexbuffer = NULL;
-       rsurface.batchvertex3f_bufferoffset = 0;
-       rsurface.batchsvector3f = NULL;
-       rsurface.batchsvector3f_vertexbuffer = NULL;
-       rsurface.batchsvector3f_bufferoffset = 0;
-       rsurface.batchtvector3f = NULL;
-       rsurface.batchtvector3f_vertexbuffer = NULL;
-       rsurface.batchtvector3f_bufferoffset = 0;
-       rsurface.batchnormal3f  = NULL;
-       rsurface.batchnormal3f_vertexbuffer = NULL;
-       rsurface.batchnormal3f_bufferoffset = 0;
-       rsurface.batchlightmapcolor4f = NULL;
-       rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
-       rsurface.batchlightmapcolor4f_bufferoffset = 0;
-       rsurface.batchtexcoordtexture2f = NULL;
-       rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
-       rsurface.batchtexcoordtexture2f_bufferoffset = 0;
-       rsurface.batchtexcoordlightmap2f = NULL;
-       rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
-       rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
-       rsurface.batchskeletalindex4ub = NULL;
-       rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
-       rsurface.batchskeletalindex4ub_bufferoffset = 0;
-       rsurface.batchskeletalweight4ub = NULL;
-       rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
-       rsurface.batchskeletalweight4ub_bufferoffset = 0;
-       rsurface.batchvertexmesh = NULL;
-       rsurface.batchvertexmesh_vertexbuffer = NULL;
-       rsurface.batchvertexmesh_bufferoffset = 0;
-       rsurface.batchelement3i = NULL;
-       rsurface.batchelement3i_indexbuffer = NULL;
-       rsurface.batchelement3i_bufferoffset = 0;
-       rsurface.batchelement3s = NULL;
-       rsurface.batchelement3s_indexbuffer = NULL;
-       rsurface.batchelement3s_bufferoffset = 0;
-       rsurface.passcolor4f = NULL;
-       rsurface.passcolor4f_vertexbuffer = NULL;
-       rsurface.passcolor4f_bufferoffset = 0;
-       rsurface.forcecurrenttextureupdate = false;
-}
-
-void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
-{
-       dp_model_t *model = ent->model;
-       //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
-       //      return;
-       rsurface.entity = (entity_render_t *)ent;
-       rsurface.skeleton = ent->skeleton;
-       memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
-       rsurface.ent_skinnum = ent->skinnum;
-       rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
-       rsurface.ent_flags = ent->flags;
-       rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
-       rsurface.matrix = ent->matrix;
-       rsurface.inversematrix = ent->inversematrix;
-       rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
-       rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
-       R_EntityMatrix(&rsurface.matrix);
-       Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
-       Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
-       rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
-       rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
-       rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
-       rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
-       VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
-       VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
-       VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
-       VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
-       VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
-       VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
-       rsurface.colormod[3] = ent->alpha;
-       VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
-       memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
-       rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
+       memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
+       rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
        rsurface.basepolygonfactor = r_refdef.polygonfactor;
        rsurface.basepolygonoffset = r_refdef.polygonoffset;
        if (ent->model->brush.submodel && !prepass)
@@ -8868,6 +8677,24 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q
 void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
 {
        rsurface.entity = r_refdef.scene.worldentity;
+       if (r != 1.0f || g != 1.0f || b != 1.0f || a != 1.0f) {
+               // HACK to provide a valid entity with modded colors to R_GetCurrentTexture.
+               // A better approach could be making this copy only once per frame.
+               static entity_render_t custom_entity;
+               int q;
+               custom_entity = *rsurface.entity;
+               for (q = 0; q < 3; ++q) {
+                       float colormod = q == 0 ? r : q == 1 ? g : b;
+                       custom_entity.render_fullbright[q] *= colormod;
+                       custom_entity.render_modellight_ambient[q] *= colormod;
+                       custom_entity.render_modellight_diffuse[q] *= colormod;
+                       custom_entity.render_lightmap_ambient[q] *= colormod;
+                       custom_entity.render_lightmap_diffuse[q] *= colormod;
+                       custom_entity.render_rtlight_diffuse[q] *= colormod;
+               }
+               custom_entity.alpha *= a;
+               rsurface.entity = &custom_entity;
+       }
        rsurface.skeleton = NULL;
        rsurface.ent_skinnum = 0;
        rsurface.ent_qwskin = -1;
@@ -8886,13 +8713,6 @@ void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inve
        rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
        rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
        rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
-       VectorSet(rsurface.modellight_ambient, 0, 0, 0);
-       VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
-       VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
-       VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
-       VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
-       Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
-       VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
        memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
        rsurface.frameblend[0].lerp = 1;
        rsurface.ent_alttextures = false;
@@ -9261,60 +9081,63 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                        break;
                }
        }
-       switch(rsurface.texture->tcgen.tcgen)
+       if (rsurface.texture->materialshaderpass)
        {
-       default:
-       case Q3TCGEN_TEXTURE:
-               break;
-       case Q3TCGEN_LIGHTMAP:
-               if (!dynamicvertex)
-               {
-                       r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
-                       r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
-                       r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
-                       r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
-               }
-               dynamicvertex = true;
-               batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
-               needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
-               break;
-       case Q3TCGEN_VECTOR:
-               if (!dynamicvertex)
+               switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
                {
-                       r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
-                       r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
-                       r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
-                       r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
-               }
-               dynamicvertex = true;
-               batchneed |= BATCHNEED_ARRAY_VERTEX;
-               needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
-               break;
-       case Q3TCGEN_ENVIRONMENT:
-               if (!dynamicvertex)
-               {
-                       r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
-                       r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
-                       r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
-                       r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
+               default:
+               case Q3TCGEN_TEXTURE:
+                       break;
+               case Q3TCGEN_LIGHTMAP:
+                       if (!dynamicvertex)
+                       {
+                               r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
+                               r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
+                               r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
+                               r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
+                       }
+                       dynamicvertex = true;
+                       batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
+                       needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
+                       break;
+               case Q3TCGEN_VECTOR:
+                       if (!dynamicvertex)
+                       {
+                               r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
+                               r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
+                               r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
+                               r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
+                       }
+                       dynamicvertex = true;
+                       batchneed |= BATCHNEED_ARRAY_VERTEX;
+                       needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
+                       break;
+               case Q3TCGEN_ENVIRONMENT:
+                       if (!dynamicvertex)
+                       {
+                               r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
+                               r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
+                               r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
+                               r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
+                       }
+                       dynamicvertex = true;
+                       batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
+                       needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
+                       break;
                }
-               dynamicvertex = true;
-               batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
-               needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
-               break;
-       }
-       if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
-       {
-               if (!dynamicvertex)
+               if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
                {
-                       r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
-                       r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
-                       r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
-                       r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
+                       if (!dynamicvertex)
+                       {
+                               r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
+                               r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
+                               r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
+                               r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
+                       }
+                       dynamicvertex = true;
+                       batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
+                       needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
                }
-               dynamicvertex = true;
-               batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
-               needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
        }
 
        if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
@@ -10157,10 +9980,10 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                }
        }
 
-       if (rsurface.batchtexcoordtexture2f)
+       if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
        {
        // generate texcoords based on the chosen texcoord source
-               switch(rsurface.texture->tcgen.tcgen)
+               switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
                {
                default:
                case Q3TCGEN_TEXTURE:
@@ -10178,8 +10001,8 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
        //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
                        for (j = 0;j < batchnumvertices;j++)
                        {
-                               rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
-                               rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
+                               rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
+                               rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
                        }
                        break;
                case Q3TCGEN_ENVIRONMENT:
@@ -10219,10 +10042,10 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                // and we only support that as the first one
                // (handling a mixture of turbulent and other tcmods would be problematic
                //  without punting it entirely to a software path)
-               if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
+               if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
                {
-                       amplitude = rsurface.texture->tcmods[0].parms[1];
-                       animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
+                       amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
+                       animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
        //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
        //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
        //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
@@ -10510,9 +10333,9 @@ static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
        rsurface.passcolor4f_bufferoffset = 0;
        for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
        {
-               c2[0] = c[0] + r_refdef.scene.ambient;
-               c2[1] = c[1] + r_refdef.scene.ambient;
-               c2[2] = c[2] + r_refdef.scene.ambient;
+               c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
+               c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
+               c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
                c2[3] = c[3];
        }
 }
@@ -10576,7 +10399,7 @@ static void RSurf_DrawBatch_GL11_ClampColor(void)
        }
 }
 
-static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
+static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
 {
        int i;
        float f;
@@ -10594,14 +10417,14 @@ static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
                f = -DotProduct(r_refdef.view.forward, n);
                f = max(0, f);
                f = f * 0.85 + 0.15; // work around so stuff won't get black
-               f *= r_refdef.lightmapintensity;
+               f *= fakelightintensity;
                Vector4Set(c, f, f, f, 1);
        }
 }
 
 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
 {
-       RSurf_DrawBatch_GL11_ApplyFakeLight();
+       RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
        if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
        if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
        R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
@@ -10609,7 +10432,7 @@ static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, q
        RSurf_DrawBatch();
 }
 
-static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
+static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
 {
        int i;
        float f;
@@ -10622,14 +10445,14 @@ static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b,
        vec3_t lightdir;
        // TODO: optimize
        // model lighting
-       VectorCopy(rsurface.modellight_lightdir, lightdir);
-       f = 0.5f * r_refdef.lightmapintensity;
-       ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
-       ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
-       ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
-       diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
-       diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
-       diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
+       VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
+       f = 0.5f * lightmapintensity;
+       ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
+       ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
+       ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
+       diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
+       diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
+       diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
        alpha = *a;
        if (VectorLength2(diffusecolor) > 0)
        {
@@ -10664,7 +10487,7 @@ static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b,
 
 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
 {
-       RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
+       RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
        if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
        if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
        R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
@@ -10707,6 +10530,7 @@ void RSurf_SetupDepthAndCulling(void)
 
 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
 {
+       int i, j;
        // transparent sky would be ridiculous
        if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
                return;
@@ -10714,20 +10538,75 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_
        skyrenderlater = true;
        RSurf_SetupDepthAndCulling();
        GL_DepthMask(true);
-       // LordHavoc: HalfLife maps have freaky skypolys so don't use
+
+       // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
+       if (r_sky_scissor.integer)
+       {
+               RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
+               for (i = 0; i < texturenumsurfaces; i++)
+               {
+                       const msurface_t *surf = texturesurfacelist[i];
+                       const float *v;
+                       float p[3];
+                       float mins[3], maxs[3];
+                       int scissor[4];
+                       for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
+                       {
+                               Matrix4x4_Transform(&rsurface.matrix, v, p);
+                               if (j > 0)
+                               {
+                                       if (mins[0] > p[0]) mins[0] = p[0];
+                                       if (mins[1] > p[1]) mins[1] = p[1];
+                                       if (mins[2] > p[2]) mins[2] = p[2];
+                                       if (maxs[0] < p[0]) maxs[0] = p[0];
+                                       if (maxs[1] < p[1]) maxs[1] = p[1];
+                                       if (maxs[2] < p[2]) maxs[2] = p[2];
+                               }
+                               else
+                               {
+                                       VectorCopy(p, mins);
+                                       VectorCopy(p, maxs);
+                               }
+                       }
+                       if (!R_ScissorForBBox(mins, maxs, scissor))
+                       {
+                               if (skyscissor[2])
+                               {
+                                       if (skyscissor[0] > scissor[0])
+                                       {
+                                               skyscissor[2] += skyscissor[0] - scissor[0];
+                                               skyscissor[0] = scissor[0];
+                                       }
+                                       if (skyscissor[1] > scissor[1])
+                                       {
+                                               skyscissor[3] += skyscissor[1] - scissor[1];
+                                               skyscissor[1] = scissor[1];
+                                       }
+                                       if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
+                                               skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
+                                       if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
+                                               skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
+                               }
+                               else
+                                       Vector4Copy(scissor, skyscissor);
+                       }
+               }
+       }
+
+       // LadyHavoc: HalfLife maps have freaky skypolys so don't use
        // skymasking on them, and Quake3 never did sky masking (unlike
        // software Quake and software Quake2), so disable the sky masking
        // 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.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
+       if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && (r_refdef.scene.worldmodel->brush.isq3bsp ? r_q3bsp_renderskydepth.integer : r_q1bsp_skymasking.integer) && !r_refdef.viewcache.world_novis && !r_trippy.integer)
        {
                R_Mesh_ResetTextureState();
                if (skyrendermasked)
                {
                        R_SetupShader_DepthOrShadow(false, false, false);
                        // depth-only (masking)
-                       GL_ColorMask(0,0,0,0);
+                       GL_ColorMask(0, 0, 0, 0);
                        // just to make sure that braindead drivers don't draw
                        // anything despite that colormask...
                        GL_BlendFunc(GL_ZERO, GL_ONE);
@@ -10761,7 +10640,7 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface
        {
                // render screenspace normalmap to texture
                GL_DepthMask(true);
-               R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
+               R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
                RSurf_DrawBatch();
                return;
        }
@@ -10789,18 +10668,18 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface
                        {
                                // render water or distortion background
                                GL_DepthMask(true);
-                               R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
+                               R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
                                RSurf_DrawBatch();
                                // blend surface on top
                                GL_DepthMask(false);
-                               R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
+                               R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
                                RSurf_DrawBatch();
                        }
                        else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
                        {
                                // render surface with reflection texture as input
                                GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
-                               R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
+                               R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
                                RSurf_DrawBatch();
                        }
                }
@@ -10809,7 +10688,7 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface
 
        // render surface batch normally
        GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
-       R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
+       R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
        RSurf_DrawBatch();
 }
 
@@ -10820,7 +10699,7 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface
        qboolean applyfog;
        int layerindex;
        const texturelayer_t *layer;
-       RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+       RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
        R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
 
        for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
@@ -10927,7 +10806,7 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface
        qboolean applyfog;
        int layerindex;
        const texturelayer_t *layer;
-       RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+       RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
        R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
 
        for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
@@ -11032,14 +10911,15 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const
        int j;
        r_vertexgeneric_t *batchvertex;
        float c[4];
+       texture_t *t = rsurface.texture;
 
 //     R_Mesh_ResetTextureState();
        R_SetupShader_Generic_NoTexture(false, false);
 
-       if(rsurface.texture && rsurface.texture->currentskinframe)
+       if(t && t->currentskinframe)
        {
-               memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
-               c[3] *= rsurface.texture->currentalpha;
+               memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
+               c[3] *= t->currentalpha;
        }
        else
        {
@@ -11049,11 +10929,11 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const
                c[3] = 1;
        }
 
-       if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
+       if (t->pantstexture || t->shirttexture)
        {
-               c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
-               c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
-               c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
+               c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
+               c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
+               c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
        }
 
        // brighten it up (as texture value 127 means "unlit")
@@ -11061,27 +10941,27 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const
        c[1] *= 2 * r_refdef.view.colorscale;
        c[2] *= 2 * r_refdef.view.colorscale;
 
-       if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
+       if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
                c[3] *= r_wateralpha.value;
 
-       if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
+       if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
        {
                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                GL_DepthMask(false);
        }
-       else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
+       else if(t->currentmaterialflags & MATERIALFLAG_ADD)
        {
                GL_BlendFunc(GL_ONE, GL_ONE);
                GL_DepthMask(false);
        }
-       else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
+       else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
        {
                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
                GL_DepthMask(false);
        }
-       else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
+       else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
        {
-               GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
+               GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
                GL_DepthMask(false);
        }
        else
@@ -11094,32 +10974,20 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const
        {
                rsurface.passcolor4f = NULL;
 
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
-               {
-                       RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
-
-                       rsurface.passcolor4f = NULL;
-                       rsurface.passcolor4f_vertexbuffer = 0;
-                       rsurface.passcolor4f_bufferoffset = 0;
-               }
-               else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
+               if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
                {
                        qboolean applycolor = true;
                        float one = 1.0;
 
                        RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
 
-                       r_refdef.lightmapintensity = 1;
-                       RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
-                       r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
+                       RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
                }
                else if (FAKELIGHT_ENABLED)
                {
                        RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
 
-                       r_refdef.lightmapintensity = r_fakelight_intensity.value;
-                       RSurf_DrawBatch_GL11_ApplyFakeLight();
-                       r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
+                       RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
                }
                else
                {
@@ -11128,12 +10996,12 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const
                        rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
                        rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
                        rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
+                       RSurf_DrawBatch_GL11_ApplyAmbient();
                }
 
                if(!rsurface.passcolor4f)
                        RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
 
-               RSurf_DrawBatch_GL11_ApplyAmbient();
                RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
                if(r_refdef.fogenabled)
                        RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
@@ -11212,36 +11080,6 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const
        }
 }
 
-static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
-{
-       CHECKGLERROR
-       RSurf_SetupDepthAndCulling();
-       if (r_showsurfaces.integer)
-       {
-               R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
-               return;
-       }
-       switch (vid.renderpath)
-       {
-       case RENDERPATH_GL20:
-       case RENDERPATH_D3D9:
-       case RENDERPATH_D3D10:
-       case RENDERPATH_D3D11:
-       case RENDERPATH_SOFT:
-       case RENDERPATH_GLES2:
-               R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
-               break;
-       case RENDERPATH_GL13:
-       case RENDERPATH_GLES1:
-               R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
-               break;
-       case RENDERPATH_GL11:
-               R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
-               break;
-       }
-       CHECKGLERROR
-}
-
 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
 {
        CHECKGLERROR
@@ -11280,12 +11118,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const
        const msurface_t *surface;
        const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
 
-       // 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.scene.worldentity)
-               RSurf_ActiveWorldEntity();
-       else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
+       if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
                RSurf_ActiveModelEntity(ent, false, false, false);
        else
        {
@@ -11390,12 +11223,9 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const
                        }
                }
                // render the range of surfaces
-               if (ent == r_refdef.scene.worldentity)
-                       R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
-               else
-                       R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
+               R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
        }
-       rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
+       rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
 }
 
 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
@@ -11443,84 +11273,6 @@ static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msu
        RSurf_DrawBatch();
 }
 
-static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
-{
-       CHECKGLERROR
-       if (depthonly)
-               R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
-       else if (prepass)
-       {
-               if (!rsurface.texture->currentnumlayers)
-                       return;
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
-                       R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
-               else
-                       R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
-       }
-       else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
-               R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
-       else if (!rsurface.texture->currentnumlayers)
-               return;
-       else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
-       {
-               // in the deferred case, transparent surfaces were queued during prepass
-               if (!r_shadow_usingdeferredprepass)
-                       R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
-       }
-       else
-       {
-               // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
-               R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
-       }
-       CHECKGLERROR
-}
-
-static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
-{
-       int i, j;
-       texture_t *texture;
-       R_FrameData_SetMark();
-       // break the surface list down into batches by texture and use of lightmapping
-       for (i = 0;i < numsurfaces;i = j)
-       {
-               j = i + 1;
-               // texture is the base texture pointer, rsurface.texture is the
-               // current frame/skin the texture is directing us to use (for example
-               // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
-               // use skin 1 instead)
-               texture = surfacelist[i]->texture;
-               rsurface.texture = R_GetCurrentTexture(texture);
-               if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
-               {
-                       // if this texture is not the kind we want, skip ahead to the next one
-                       for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
-                               ;
-                       continue;
-               }
-               if(FAKELIGHT_ENABLED || depthonly || prepass)
-               {
-                       rsurface.lightmaptexture = NULL;
-                       rsurface.deluxemaptexture = NULL;
-                       rsurface.uselightmaptexture = false;
-                       // simply scan ahead until we find a different texture or lightmap state
-                       for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
-                               ;
-               }
-               else
-               {
-                       rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
-                       rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
-                       rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
-                       // simply scan ahead until we find a different texture or lightmap state
-                       for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
-                               ;
-               }
-               // render the range of surfaces
-               R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
-       }
-       R_FrameData_ReturnToMark();
-}
-
 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
 {
        CHECKGLERROR
@@ -12186,10 +11938,7 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent)
        // 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.scene.worldentity)
-               RSurf_ActiveWorldEntity();
-       else
-               RSurf_ActiveModelEntity(ent, false, false, false);
+       RSurf_ActiveModelEntity(ent, false, false, false);
 
        decalsystem->lastupdatetime = r_refdef.scene.time;
 
@@ -12542,101 +12291,6 @@ static void R_DrawDebugModel(void)
 
 int r_maxsurfacelist = 0;
 const msurface_t **r_surfacelist = NULL;
-void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
-{
-       int i, j, endj, flagsmask;
-       dp_model_t *model = r_refdef.scene.worldmodel;
-       msurface_t *surfaces;
-       unsigned char *update;
-       int numsurfacelist = 0;
-       if (model == NULL)
-               return;
-
-       if (r_maxsurfacelist < model->num_surfaces)
-       {
-               r_maxsurfacelist = model->num_surfaces;
-               if (r_surfacelist)
-                       Mem_Free((msurface_t**)r_surfacelist);
-               r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
-       }
-
-       RSurf_ActiveWorldEntity();
-
-       surfaces = model->data_surfaces;
-       update = model->brushq1.lightmapupdateflags;
-
-       // update light styles on this submodel
-       if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
-       {
-               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.scene.lightstylevalue[style->style])
-                       {
-                               int *list = style->surfacelist;
-                               style->value = r_refdef.scene.lightstylevalue[style->style];
-                               for (j = 0;j < style->numsurfaces;j++)
-                                       update[list[j]] = true;
-                       }
-               }
-       }
-
-       flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
-
-       if (debug)
-       {
-               R_DrawDebugModel();
-               rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
-               return;
-       }
-
-       rsurface.lightmaptexture = NULL;
-       rsurface.deluxemaptexture = NULL;
-       rsurface.uselightmaptexture = false;
-       rsurface.texture = NULL;
-       rsurface.rtlight = NULL;
-       numsurfacelist = 0;
-       // add visible surfaces to draw list
-       for (i = 0;i < model->nummodelsurfaces;i++)
-       {
-               j = model->sortedmodelsurfaces[i];
-               if (r_refdef.viewcache.world_surfacevisible[j])
-                       r_surfacelist[numsurfacelist++] = surfaces + j;
-       }
-       // update lightmaps if needed
-       if (model->brushq1.firstrender)
-       {
-               model->brushq1.firstrender = false;
-               for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
-                       if (update[j])
-                               R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
-       }
-       else if (update)
-       {
-               for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
-                       if (r_refdef.viewcache.world_surfacevisible[j])
-                               if (update[j])
-                                       R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
-       }
-       // don't do anything if there were no surfaces
-       if (!numsurfacelist)
-       {
-               rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
-               return;
-       }
-       R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
-
-       // add to stats if desired
-       if (r_speeds.integer && !skysurfaces && !depthonly)
-       {
-               r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
-               for (j = 0;j < numsurfacelist;j++)
-                       r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
-       }
-
-       rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
-}
-
 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
 {
        int i, j, endj, flagsmask;
@@ -12655,12 +12309,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
                r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
        }
 
-       // 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.scene.worldentity)
-               RSurf_ActiveWorldEntity();
-       else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
+       if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
                RSurf_ActiveModelEntity(ent, false, false, false);
        else if (prepass)
                RSurf_ActiveModelEntity(ent, true, true, true);
@@ -12707,7 +12356,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
        update = model->brushq1.lightmapupdateflags;
 
        // update light styles
-       if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
+       if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
        {
                model_brush_lightstyleinfo_t *style;
                for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
@@ -12727,7 +12376,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
        if (debug)
        {
                R_DrawDebugModel();
-               rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
+               rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
                return;
        }
 
@@ -12738,12 +12387,26 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
        rsurface.rtlight = NULL;
        numsurfacelist = 0;
        // add visible surfaces to draw list
-       for (i = 0;i < model->nummodelsurfaces;i++)
-               r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
+       if (ent == r_refdef.scene.worldentity)
+       {
+               // for the world entity, check surfacevisible
+               for (i = 0;i < model->nummodelsurfaces;i++)
+               {
+                       j = model->sortedmodelsurfaces[i];
+                       if (r_refdef.viewcache.world_surfacevisible[j])
+                               r_surfacelist[numsurfacelist++] = surfaces + j;
+               }
+       }
+       else
+       {
+               // add all surfaces
+               for (i = 0; i < model->nummodelsurfaces; i++)
+                       r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
+       }
        // don't do anything if there were no surfaces
        if (!numsurfacelist)
        {
-               rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
+               rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
                return;
        }
        // update lightmaps if needed
@@ -12770,11 +12433,12 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
                        r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
        }
 
-       rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
+       rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
 }
 
 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
 {
+       int q;
        static texture_t texture;
        static msurface_t surface;
        const msurface_t *surfacelist = &surface;
@@ -12791,21 +12455,8 @@ void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, i
        texture.specularscalemod = 1;
        texture.specularpowermod = 1;
        texture.transparentsort = TRANSPARENTSORT_DISTANCE;
-       // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
-       // JUST GREP FOR "specularscalemod = 1".
 
-       surface.texture = &texture;
-       surface.num_triangles = numtriangles;
-       surface.num_firsttriangle = firsttriangle;
-       surface.num_vertices = numvertices;
-       surface.num_firstvertex = firstvertex;
-
-       // now render it
-       rsurface.texture = R_GetCurrentTexture(surface.texture);
-       rsurface.lightmaptexture = NULL;
-       rsurface.deluxemaptexture = NULL;
-       rsurface.uselightmaptexture = false;
-       R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
+       R_DrawCustomSurface_Texture(&texture, texmatrix, materialflags, firstvertex, numvertices, firsttriangle, numtriangles, writedepth, prepass);
 }
 
 void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)