From: havoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Date: Mon, 9 Apr 2018 04:39:19 +0000 (+0000)
Subject: Refactored R_UpdateEntityLighting to CL_UpdateEntityShading, which sets fields like... 
X-Git-Tag: xonotic-v0.8.5~16
X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=b761eb6b6ce3048307c587f097d0c4f13f6cc0c4;p=xonotic%2Fdarkplaces.git

Refactored R_UpdateEntityLighting to CL_UpdateEntityShading, which sets fields like ent->render_modellight_ambient.

Added texture->render_modellight_ambient and similar fields which concretely define how the material is to be rendered, so all of the various tweaks and modifiers are no longer buried in R_SetupShader_Surface which has now been refactored heavily.

Removed R_LightPoint as it's really not necessary - this change will make lit particles a little bit slower as R_CompleteLightPoint is a slightly more expensive function.

Refactored R_CompleteLightPoint to have more consistent code, changed the final color math so that it passes q1bsp/q2bsp lighting through unmodified.

Changed shading of tag_entity attachments - they now use the root entity's origin for shading, this fixes r_shadows where the shadows could go in different directions on CSQC entities (r_shadows code already contained a hack to work around this problem for network entities).

Renamed r_refdef.lightmapintensity and ambient to r_refdef.scene.lightmapintensity and ambientintensity.

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12376 d7cf8633-e32d-0410-b094-e92efae38249
::stable-branch::merge=4e1f3f76d5fe7befe20034a730630c314d45956b
---

diff --git a/cl_main.c b/cl_main.c
index d5707029..8753a5eb 100644
--- a/cl_main.c
+++ b/cl_main.c
@@ -2406,14 +2406,14 @@ void CL_MeshEntities_Init(void)
 		ent->state_current.active = true;
 		ent->render.model = cl_meshentitymodels + i;
 		ent->render.alpha = 1;
-		ent->render.flags = RENDER_SHADOW | RENDER_LIGHT;
+		ent->render.flags = RENDER_SHADOW | RENDER_LIGHT | RENDER_CUSTOMIZEDMODELLIGHT;
 		ent->render.framegroupblend[0].lerp = 1;
 		ent->render.frameblend[0].lerp = 1;
 		VectorSet(ent->render.colormod, 1, 1, 1);
 		VectorSet(ent->render.glowmod, 1, 1, 1);
-		VectorSet(ent->render.modellight_ambient, 1, 1, 1);
-		VectorSet(ent->render.modellight_diffuse, 0, 0, 0);
-		VectorSet(ent->render.modellight_lightdir, 0, 0, 1);
+		VectorSet(ent->render.custommodellight_ambient, 1, 1, 1);
+		VectorSet(ent->render.custommodellight_diffuse, 0, 0, 0);
+		VectorSet(ent->render.custommodellight_lightdir, 0, 0, 1);
 		Matrix4x4_CreateIdentity(&ent->render.matrix);
 		CL_UpdateRenderEntity(&ent->render);
 	}
@@ -2451,6 +2451,221 @@ void CL_MeshEntities_Shutdown(void)
 {
 }
 
+extern cvar_t r_overheadsprites_pushback;
+extern cvar_t r_fullbright_directed_pitch_relative;
+extern cvar_t r_fullbright_directed_pitch;
+extern cvar_t r_fullbright_directed_ambient;
+extern cvar_t r_fullbright_directed_diffuse;
+extern cvar_t r_fullbright_directed;
+extern cvar_t r_equalize_entities_minambient;
+extern cvar_t r_equalize_entities_to;
+extern cvar_t r_equalize_entities_by;
+extern cvar_t r_hdr_glowintensity;
+
+static void CL_UpdateEntityShading_GetDirectedFullbright(vec3_t ambient, vec3_t diffuse, vec3_t worldspacenormal)
+{
+	vec3_t angles;
+
+	VectorSet(ambient, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value);
+	VectorSet(diffuse, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value);
+
+	// Use cl.viewangles and not r_refdef.view.forward here so it is the
+	// same for all stereo views, and to better handle pitches outside
+	// [-90, 90] (in_pitch_* cvars allow that).
+	VectorCopy(cl.viewangles, angles);
+	if (r_fullbright_directed_pitch_relative.integer) {
+		angles[PITCH] += r_fullbright_directed_pitch.value;
+	}
+	else {
+		angles[PITCH] = r_fullbright_directed_pitch.value;
+	}
+	AngleVectors(angles, worldspacenormal, NULL, NULL);
+	VectorNegate(worldspacenormal, worldspacenormal);
+}
+
+static void CL_UpdateEntityShading_Entity(entity_render_t *ent)
+{
+	float shadingorigin[3], f, fa, fd, fdd, a[3], c[3], dir[3];
+	int q;
+
+	for (q = 0; q < 3; q++)
+		a[q] = c[q] = dir[q] = 0;
+
+	ent->render_modellight_forced = false;
+	ent->render_rtlight_disabled = false;
+
+	// pick an appropriate value for render_modellight_origin - if this is an
+	// attachment we want to use the parent's render_modellight_origin so that
+	// shading is the same (also important for r_shadows to cast shadows in the
+	// same direction)
+	if (VectorLength2(ent->custommodellight_origin))
+	{
+		// CSQC entities always provide this (via CL_GetTagMatrix)
+		for (q = 0; q < 3; q++)
+			shadingorigin[q] = ent->custommodellight_origin[q];
+	}
+	else if (ent->entitynumber > 0 && ent->entitynumber < cl.num_entities)
+	{
+		// network entity - follow attachment chain back to a root entity,
+		int entnum = ent->entitynumber, recursion;
+		for (recursion = 32; recursion > 0; --recursion)
+		{
+			int parentnum = cl.entities[entnum].state_current.tagentity;
+			if (parentnum < 1 || parentnum >= cl.num_entities || !cl.entities_active[parentnum])
+				break;
+			entnum = parentnum;
+		}
+		// grab the root entity's origin
+		Matrix4x4_OriginFromMatrix(&cl.entities[entnum].render.matrix, shadingorigin);
+	}
+	else
+	{
+		// not a CSQC entity (which sets custommodellight_origin), not a network
+		// entity - so it's probably not attached to anything
+		Matrix4x4_OriginFromMatrix(&ent->matrix, shadingorigin);
+	}
+
+	if (!(ent->flags & RENDER_LIGHT) || r_fullbright.integer)
+	{
+		// intentionally EF_FULLBRIGHT entity
+		// the only type that is not scaled by r_refdef.scene.lightmapintensity
+		// CSQC can still provide its own customized modellight values
+		ent->render_rtlight_disabled = true;
+		ent->render_modellight_forced = true;
+		if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
+		{
+			// custom colors provided by CSQC
+			for (q = 0; q < 3; q++)
+			{
+				a[q] = ent->custommodellight_ambient[q];
+				c[q] = ent->custommodellight_diffuse[q];
+				dir[q] = ent->custommodellight_lightdir[q];
+			}
+		}
+		else if (r_fullbright_directed.integer)
+			CL_UpdateEntityShading_GetDirectedFullbright(a, c, dir);
+		else
+			for (q = 0; q < 3; q++)
+				a[q] = 1;
+	}
+	else
+	{
+		// fetch the lighting from the worldmodel data
+
+		// CSQC can provide its own customized modellight values
+		if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
+		{
+			ent->render_modellight_forced = true;
+			for (q = 0; q < 3; q++)
+			{
+				a[q] = ent->custommodellight_ambient[q];
+				c[q] = ent->custommodellight_diffuse[q];
+				dir[q] = ent->custommodellight_lightdir[q];
+			}
+		}
+		else 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
+				shadingorigin[2] = shadingorigin[2] + r_overheadsprites_pushback.value;
+			R_CompleteLightPoint(a, c, dir, shadingorigin, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
+			ent->render_modellight_forced = true;
+			ent->render_rtlight_disabled = true;
+		}
+		else if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
+			R_CompleteLightPoint(a, c, dir, shadingorigin, LP_LIGHTMAP, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
+		else if (r_fullbright_directed.integer)
+			CL_UpdateEntityShading_GetDirectedFullbright(a, c, dir);
+		else
+			R_CompleteLightPoint(a, c, dir, shadingorigin, LP_LIGHTMAP, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
+
+		if (ent->flags & RENDER_EQUALIZE)
+		{
+			// first fix up ambient lighting...
+			if (r_equalize_entities_minambient.value > 0)
+			{
+				fd = 0.299f * ent->render_modellight_diffuse[0] + 0.587f * ent->render_modellight_diffuse[1] + 0.114f * ent->render_modellight_diffuse[2];
+				if (fd > 0)
+				{
+					fa = (0.299f * ent->render_modellight_ambient[0] + 0.587f * ent->render_modellight_ambient[1] + 0.114f * ent->render_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
+						for (q = 0; q < 3; q++)
+						{
+							a[q] = (1 - f)*0.25f * c[q];
+							c[q] *= f;
+						}
+					}
+				}
+			}
+
+			if (r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
+			{
+				fa = 0.299f * a[0] + 0.587f * a[1] + 0.114f * a[2];
+				fd = 0.299f * c[0] + 0.587f * c[1] + 0.114f * c[2];
+				f = fa + 0.25 * fd;
+				if (f > 0)
+				{
+					// adjust brightness and saturation to target
+					float l2 = r_equalize_entities_by.value, l1 = 1 - l2;
+					for (q = 0; q < 3; q++)
+					{
+						a[q] = l1 * a[q] + l2 * (fa / f);
+						c[q] = l1 * c[q] + l2 * (fd / f);
+					}
+				}
+			}
+		}
+	}
+
+	for (q = 0; q < 3; q++)
+	{
+		ent->render_fullbright[q] = ent->colormod[q];
+		ent->render_glowmod[q] = ent->glowmod[q] * r_hdr_glowintensity.value;
+		ent->render_modellight_ambient[q] = a[q] * ent->colormod[q];
+		ent->render_modellight_diffuse[q] = c[q] * ent->colormod[q];
+		ent->render_modellight_specular[q] = c[q];
+		ent->render_modellight_lightdir[q] = dir[q];
+		ent->render_lightmap_ambient[q] = ent->colormod[q] * r_refdef.scene.ambientintensity;
+		ent->render_lightmap_diffuse[q] = ent->colormod[q] * r_refdef.scene.lightmapintensity;
+		ent->render_lightmap_specular[q] = r_refdef.scene.lightmapintensity;
+		ent->render_rtlight_diffuse[q] = ent->colormod[q];
+		ent->render_rtlight_specular[q] = 1;
+	}
+
+	// these flags disable code paths, make sure it's obvious if they're ignored by storing 0 1 2
+	if (ent->render_modellight_forced)
+		for (q = 0; q < 3; q++)
+			ent->render_lightmap_ambient[q] = ent->render_lightmap_diffuse[q] = ent->render_lightmap_specular[q] = q;
+	if (ent->render_rtlight_disabled)
+		for (q = 0; q < 3; q++)
+			ent->render_rtlight_diffuse[q] = ent->render_rtlight_specular[q] = q;
+
+	if (VectorLength2(ent->render_modellight_lightdir) == 0)
+		VectorSet(ent->render_modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
+	VectorNormalize(ent->render_modellight_lightdir);
+}
+
+
+void CL_UpdateEntityShading(void)
+{
+	int i;
+	CL_UpdateEntityShading_Entity(r_refdef.scene.worldentity);
+	for (i = 0; i < r_refdef.scene.numentities; i++)
+		CL_UpdateEntityShading_Entity(r_refdef.scene.entities[i]);
+}
+
 /*
 ===========
 CL_Shutdown
diff --git a/cl_particles.c b/cl_particles.c
index 5e873998..9d64080b 100644
--- a/cl_particles.c
+++ b/cl_particles.c
@@ -2723,10 +2723,14 @@ static void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const
 			// note: lighting is not cheap!
 			if (particletype[p->typeindex].lighting)
 			{
+				float a[3], c[3], dir[3];
 				vecorg[0] = p->org[0];
 				vecorg[1] = p->org[1];
 				vecorg[2] = p->org[2];
-				R_LightPoint(c4f, vecorg, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
+				R_CompleteLightPoint(a, c, dir, vecorg, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
+				c4f[0] = p->color[0] * colormultiplier[0] * (a[0] + 0.25f * c[0]);
+				c4f[1] = p->color[1] * colormultiplier[1] * (a[1] + 0.25f * c[1]);
+				c4f[2] = p->color[2] * colormultiplier[2] * (a[2] + 0.25f * c[2]);
 			}
 			// mix in the fog color
 			if (r_refdef.fogenabled)
diff --git a/cl_screen.c b/cl_screen.c
index a2bbf496..abde7491 100644
--- a/cl_screen.c
+++ b/cl_screen.c
@@ -1894,6 +1894,7 @@ static void R_Envmap_f (void)
 	buffer1 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 4);
 	buffer2 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
 
+	CL_UpdateEntityShading();
 	for (j = 0;j < 12;j++)
 	{
 		dpsnprintf(filename, sizeof(filename), "env/%s%s.tga", basename, envmapinfo[j].name);
@@ -2186,7 +2187,10 @@ static void SCR_DrawScreen (void)
 		if (cl.csqc_loaded)
 			CL_VM_UpdateView(r_stereo_side ? 0.0 : max(0.0, cl.time - cl.oldtime));
 		else
+		{
+			CL_UpdateEntityShading();
 			R_RenderView();
+		}
 	}
 
 	if (!r_stereo_sidebyside.integer && !r_stereo_horizontal.integer && !r_stereo_vertical.integer)
diff --git a/client.h b/client.h
index 5486b1bf..6be9d5a5 100644
--- a/client.h
+++ b/client.h
@@ -573,10 +573,37 @@ typedef struct entity_render_s
 	int animcache_skeletaltransform3x4offset;
 	int animcache_skeletaltransform3x4size;
 
-	// current lighting from map (updated ONLY by client code, not renderer)
-	vec3_t modellight_ambient;
-	vec3_t modellight_diffuse; // q3bsp
-	vec3_t modellight_lightdir; // q3bsp
+	// CL_UpdateEntityShading reads these fields
+	// used only if RENDER_CUSTOMIZEDMODELLIGHT is set
+	vec3_t custommodellight_ambient;
+	vec3_t custommodellight_diffuse;
+	vec3_t custommodellight_lightdir;
+	// CSQC entities get their shading from the root of their attachment chain
+	float custommodellight_origin[3];
+
+	// derived lighting parameters (CL_UpdateEntityShading)
+
+	// used by MATERIALFLAG_FULLBRIGHT which is MATERIALFLAG_MODELLIGHT with
+	// this as ambient color, along with MATERIALFLAG_NORTLIGHT
+	float render_fullbright[3];
+	// color tint for the base pass glow textures if any
+	float render_glowmod[3];
+	// MATERIALFLAG_MODELLIGHT uses these parameters
+	float render_modellight_ambient[3];
+	float render_modellight_diffuse[3];
+	float render_modellight_lightdir[3];
+	float render_modellight_specular[3];
+	// lightmap rendering (not MATERIALFLAG_MODELLIGHT)
+	float render_lightmap_ambient[3];
+	float render_lightmap_diffuse[3];
+	float render_lightmap_specular[3];
+	// rtlights use these colors for the materials on this entity
+	float render_rtlight_diffuse[3];
+	float render_rtlight_specular[3];
+	// ignore lightmap and use lightgrid on this entity (e.g. FULLBRIGHT)
+	qboolean render_modellight_forced;
+	// do not process per pixel lights on this entity at all (like MATERIALFLAG_NORTLIGHT)
+	qboolean render_rtlight_disabled;
 
 	// storage of decals on this entity
 	// (note: if allowdecals is set, be sure to call R_DecalSystem_Reset on removal!)
@@ -1886,7 +1913,12 @@ typedef struct r_refdef_scene_s {
 	// controls intensity lightmap layers
 	unsigned short lightstylevalue[MAX_LIGHTSTYLES];	// 8.8 fraction of base light value
 
-	float ambient;
+	// adds brightness to the whole scene, separate from lightmapintensity
+	// see CL_UpdateEntityShading
+	float ambientintensity;
+	// brightness of lightmap and modellight lighting on materials
+	// see CL_UpdateEntityShading
+	float lightmapintensity;
 
 	qboolean rtworld;
 	qboolean rtworldshadows;
@@ -1956,9 +1988,6 @@ typedef struct r_refdef_s
 	// true during envmap command capture
 	qboolean envmap;
 
-	// brightness of world lightmaps and related lighting
-	// (often reduced when world rtlights are enabled)
-	float lightmapintensity;
 	// whether to draw world lights realtime, dlights realtime, and their shadows
 	float polygonfactor;
 	float polygonoffset;
@@ -2032,6 +2061,7 @@ extern const char *cl_meshentitynames[NUM_MESHENTITIES];
 #define CL_Mesh_UI() (&cl_meshentitymodels[MESH_UI])
 void CL_MeshEntities_AddToScene(void);
 void CL_MeshEntities_Reset(void);
+void CL_UpdateEntityShading(void);
 
 void CL_NewFrameReceived(int num);
 void CL_ParseEntityLump(char *entitystring);
diff --git a/clvm_cmds.c b/clvm_cmds.c
index 10fee13a..54848d8e 100644
--- a/clvm_cmds.c
+++ b/clvm_cmds.c
@@ -696,17 +696,12 @@ static void VM_CL_getlight (prvm_prog_t *prog)
 {
 	vec3_t ambientcolor, diffusecolor, diffusenormal;
 	vec3_t p;
+	int flags = prog->argc >= 2 ? PRVM_G_FLOAT(OFS_PARM1) : LP_LIGHTMAP;
 
 	VM_SAFEPARMCOUNTRANGE(1, 3, VM_CL_getlight);
 
 	VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
-	VectorClear(ambientcolor);
-	VectorClear(diffusecolor);
-	VectorClear(diffusenormal);
-	if (prog->argc >= 2)
-		R_CompleteLightPoint(ambientcolor, diffusecolor, diffusenormal, p, PRVM_G_FLOAT(OFS_PARM1));
-	else if (cl.worldmodel && cl.worldmodel->brush.LightPoint)
-		cl.worldmodel->brush.LightPoint(cl.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
+	R_CompleteLightPoint(ambientcolor, diffusecolor, diffusenormal, p, flags, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
 	VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
 	if (PRVM_clientglobalvector(getlight_ambient))
 		VectorCopy(ambientcolor, PRVM_clientglobalvector(getlight_ambient));
@@ -2453,7 +2448,7 @@ static int CL_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int
 extern cvar_t cl_bob;
 extern cvar_t cl_bobcycle;
 extern cvar_t cl_bobup;
-int CL_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
+int CL_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex, prvm_vec_t *shadingorigin)
 {
 	int ret;
 	int attachloop;
@@ -2526,6 +2521,16 @@ int CL_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int
 			Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
 		}
 		*/
+
+		// return the origin of the view
+		if (shadingorigin)
+			Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, shadingorigin);
+	}
+	else
+	{
+		// return the origin of the root entity in the chain
+		if (shadingorigin)
+			Matrix4x4_OriginFromMatrix(out, shadingorigin);
 	}
 	return 0;
 }
@@ -2582,7 +2587,7 @@ static void VM_CL_gettaginfo (prvm_prog_t *prog)
 
 	e = PRVM_G_EDICT(OFS_PARM0);
 	tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
-	returncode = CL_GetTagMatrix(prog, &tag_matrix, e, tagindex);
+	returncode = CL_GetTagMatrix(prog, &tag_matrix, e, tagindex, NULL);
 	Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
 	VectorCopy(forward, PRVM_clientglobalvector(v_forward));
 	VectorScale(left, -1, PRVM_clientglobalvector(v_right));
@@ -3230,7 +3235,7 @@ static void VM_CL_GetEntity (prvm_prog_t *prog)
 			VectorAdd(cl.entities[entnum].render.maxs, org, PRVM_G_VECTOR(OFS_RETURN));		
 			break;
 		case 16: // light
-			VectorMA(cl.entities[entnum].render.modellight_ambient, 0.5, cl.entities[entnum].render.modellight_diffuse, PRVM_G_VECTOR(OFS_RETURN));
+			VectorMA(cl.entities[entnum].render.render_modellight_ambient, 0.5, cl.entities[entnum].render.render_modellight_diffuse, PRVM_G_VECTOR(OFS_RETURN));
 			break;	
 		default:
 			PRVM_G_FLOAT(OFS_RETURN) = 0;
@@ -3266,6 +3271,7 @@ static void VM_CL_R_RenderScene (prvm_prog_t *prog)
 	// we need to update any RENDER_VIEWMODEL entities at this point because
 	// csqc supplies its own view matrix
 	CL_UpdateViewEntities();
+	CL_UpdateEntityShading();
 
 	// now draw stuff!
 	R_RenderView();
@@ -4250,7 +4256,7 @@ static void VM_CL_V_CalcRefdef(prvm_prog_t *prog)
 	flags = PRVM_G_FLOAT(OFS_PARM1);
 
 	// use the CL_GetTagMatrix function on self to ensure consistent behavior (duplicate code would be bad)
-	CL_GetTagMatrix(prog, &entrendermatrix, ent, 0);
+	CL_GetTagMatrix(prog, &entrendermatrix, ent, 0, NULL);
 
 	VectorCopy(cl.csqc_viewangles, clviewangles);
 	teleported = (flags & REFDEFFLAG_TELEPORTED) != 0;
diff --git a/csprogs.c b/csprogs.c
index 5f73c6ec..8d54fc0f 100644
--- a/csprogs.c
+++ b/csprogs.c
@@ -346,8 +346,9 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed, int edictnum)
 	if (!VectorLength2(entrender->glowmod))
 		VectorSet(entrender->glowmod, 1, 1, 1);
 
-	// LordHavoc: use the CL_GetTagMatrix function on self to ensure consistent behavior (duplicate code would be bad)
-	CL_GetTagMatrix(prog, &entrender->matrix, ed, 0);
+	// LadyHavoc: use the CL_GetTagMatrix function on self to ensure consistent behavior (duplicate code would be bad)
+	// this also sets the custommodellight_origin for us
+	CL_GetTagMatrix(prog, &entrender->matrix, ed, 0, entrender->custommodellight_origin);
 
 	// set up the animation data
 	VM_GenerateFrameGroupBlend(prog, ed->priv.server->framegroupblend, ed);
@@ -363,9 +364,9 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed, int edictnum)
 	// model light
 	if (renderflags & RF_MODELLIGHT)
 	{
-		if (PRVM_clientedictvector(ed, modellight_ambient)) VectorCopy(PRVM_clientedictvector(ed, modellight_ambient), entrender->modellight_ambient); else VectorClear(entrender->modellight_ambient);
-		if (PRVM_clientedictvector(ed, modellight_diffuse)) VectorCopy(PRVM_clientedictvector(ed, modellight_diffuse), entrender->modellight_diffuse); else VectorClear(entrender->modellight_diffuse);
-		if (PRVM_clientedictvector(ed, modellight_dir))     VectorCopy(PRVM_clientedictvector(ed, modellight_dir), entrender->modellight_lightdir);    else VectorClear(entrender->modellight_lightdir);
+		if (PRVM_clientedictvector(ed, modellight_ambient)) VectorCopy(PRVM_clientedictvector(ed, modellight_ambient), entrender->custommodellight_ambient); else VectorClear(entrender->custommodellight_ambient);
+		if (PRVM_clientedictvector(ed, modellight_diffuse)) VectorCopy(PRVM_clientedictvector(ed, modellight_diffuse), entrender->custommodellight_diffuse); else VectorClear(entrender->custommodellight_diffuse);
+		if (PRVM_clientedictvector(ed, modellight_dir))     VectorCopy(PRVM_clientedictvector(ed, modellight_dir), entrender->custommodellight_lightdir);    else VectorClear(entrender->custommodellight_lightdir);
 		entrender->flags |= RENDER_CUSTOMIZEDMODELLIGHT;
 	}
 
@@ -1189,15 +1190,13 @@ qboolean CL_VM_GetEntitySoundOrigin(int entnum, vec3_t out)
 
 	CSQC_BEGIN;
 
-	// FIXME consider attachments here!
-
 	ed = PRVM_EDICT_NUM(entnum - MAX_EDICTS);
 
 	if(!ed->priv.required->free)
 	{
 		mod = CL_GetModelFromEdict(ed);
 		VectorCopy(PRVM_clientedictvector(ed, origin), out);
-		if(CL_GetTagMatrix(prog, &matrix, ed, 0) == 0)
+		if(CL_GetTagMatrix(prog, &matrix, ed, 0, NULL) == 0)
 			Matrix4x4_OriginFromMatrix(&matrix, out);
 		if (mod && mod->soundfromcenter)
 			VectorMAMAM(1.0f, out, 0.5f, mod->normalmins, 0.5f, mod->normalmaxs, out);
diff --git a/csprogs.h b/csprogs.h
index 56761014..226cf96c 100644
--- a/csprogs.h
+++ b/csprogs.h
@@ -98,7 +98,7 @@ qboolean CL_VM_Parse_TempEntity(void);
 void CL_VM_Parse_StuffCmd(const char *msg);
 void CL_VM_Parse_CenterPrint(const char *msg);
 int CL_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent);
-int CL_GetTagMatrix(prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex);
+int CL_GetTagMatrix(prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex, prvm_vec_t *shadingorigin);
 void CL_GetEntityMatrix(prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix);
 /* VMs exposing the polygon calls must call this on Init/Reset */
 void VM_Polygons_Reset(prvm_prog_t *prog);
diff --git a/gl_rmain.c b/gl_rmain.c
index ce44d68b..4e35c2ed 100644
--- a/gl_rmain.c
+++ b/gl_rmain.c
@@ -2212,7 +2212,7 @@ 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
@@ -2221,28 +2221,27 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
 	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);
@@ -2255,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);
@@ -2275,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;
@@ -2285,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;
@@ -2296,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;
@@ -2306,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)
 		{
@@ -2331,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;
@@ -2401,20 +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)
+		if (t->colormapping)
 			permutation |= SHADERPERMUTATION_COLORMAPPING;
 		if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
 		{
@@ -2424,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)
 		{
@@ -2436,72 +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);
-				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)
-			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);
+				GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
 				permutation &= ~SHADERPERMUTATION_ALPHAKILL;
 			}
 			else
@@ -2510,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;
@@ -2520,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))
 		{
@@ -2539,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)
@@ -2561,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)
@@ -2572,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)
@@ -2591,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)
@@ -2628,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]);
@@ -2640,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)
 		{
@@ -2699,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]);
@@ -2715,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);
@@ -2805,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)
@@ -2847,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)
 		{
@@ -2871,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);
 		}
@@ -2893,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);}
@@ -2908,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);
@@ -2963,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)
 		{
@@ -3025,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);
 		}
@@ -3047,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);
@@ -5111,171 +4996,6 @@ void R_AnimCache_CacheVisibleEntities(void)
 
 //==================================================================================
 
-extern cvar_t r_overheadsprites_pushback;
-
-static void R_GetDirectedFullbright(vec3_t ambient, vec3_t diffuse, vec3_t worldspacenormal)
-{
-	vec3_t angles;
-
-	VectorSet(ambient, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value);
-	VectorSet(diffuse, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value);
-
-	// Use cl.viewangles and not r_refdef.view.forward here so it is the
-	// same for all stereo views, and to better handle pitches outside
-	// [-90, 90] (in_pitch_* cvars allow that).
-	VectorCopy(cl.viewangles, angles);
-	if (r_fullbright_directed_pitch_relative.integer) {
-		angles[PITCH] += r_fullbright_directed_pitch.value;
-	} else {
-		angles[PITCH] = r_fullbright_directed_pitch.value;
-	}
-	AngleVectors(angles, worldspacenormal, NULL, NULL);
-	VectorNegate(worldspacenormal, worldspacenormal);
-}
-
-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?
-			// The logic here currently matches RSurf_ActiveWorldEntity.
-			if (r_fullbright_directed.integer && (r_fullbright.integer || !ent->model || !ent->model->lit))
-			{
-				R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
-				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);
-			}
-			else
-			{
-				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 if (!r_fullbright.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
-				{
-					R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
-				}
-				else if (r_fullbright_directed.integer)
-				{
-					R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
-				}
-				else
-				{
-					VectorSet(ent->modellight_ambient, 1, 1, 1);
-				}
-
-				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
-			{
-				// EF_FULLBRIGHT entity.
-				if (r_fullbright_directed.integer)
-				{
-					R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
-				}
-				else
-				{
-					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);
-	}
-}
-
 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
 {
 	int i;
@@ -5542,7 +5262,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)
@@ -5773,7 +5493,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)
@@ -5782,7 +5501,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;
@@ -7191,7 +6909,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)
@@ -7209,14 +6927,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)
 	{
@@ -7224,7 +6942,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;
@@ -7361,7 +7079,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();
@@ -7611,7 +7329,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();
@@ -7632,7 +7350,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();
@@ -7790,7 +7508,7 @@ static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float c
 	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);
@@ -7951,7 +7669,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);
@@ -7968,10 +7686,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)
 	{
@@ -8314,10 +8032,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;
@@ -8381,27 +8100,115 @@ texture_t *R_GetCurrentTexture(texture_t *t)
 		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)
@@ -8446,7 +8253,7 @@ texture_t *R_GetCurrentTexture(texture_t *t)
 		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;
@@ -8486,7 +8293,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))
@@ -8495,20 +8301,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
@@ -8529,12 +8334,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)
 	{
@@ -8560,54 +8373,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
@@ -8621,7 +8418,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);
 		}
 	}
 
@@ -8630,143 +8427,6 @@ texture_t *R_GetCurrentTexture(texture_t *t)
 
 rsurfacestate_t rsurface;
 
-void RSurf_ActiveWorldEntity(void)
-{
-	dp_model_t *model = r_refdef.scene.worldmodel;
-	//if (rsurface.entity == r_refdef.scene.worldentity)
-	//	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.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
-	if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
-	{
-		R_GetDirectedFullbright(rsurface.modellight_ambient, rsurface.modellight_diffuse, rsurface.modellight_lightdir);
-		rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
-	}
-	else
-	{
-		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;
@@ -8779,9 +8439,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q
 	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;
@@ -8794,14 +8452,6 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q
 	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;
 	rsurface.basepolygonfactor = r_refdef.polygonfactor;
@@ -9044,13 +8694,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;
@@ -10671,9 +10314,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];
 	}
 }
@@ -10737,7 +10380,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;
@@ -10755,14 +10398,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);
@@ -10770,7 +10413,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;
@@ -10783,14 +10426,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)
 	{
@@ -10825,7 +10468,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);
@@ -10978,7 +10621,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;
 	}
@@ -11006,18 +10649,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();
 			}
 		}
@@ -11026,7 +10669,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();
 }
 
@@ -11037,7 +10680,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++)
@@ -11144,7 +10787,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++)
@@ -11249,14 +10892,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
 	{
@@ -11266,11 +10910,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")
@@ -11278,27 +10922,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
@@ -11311,32 +10955,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
 		{
@@ -11345,12 +10977,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();
@@ -11429,36 +11061,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
@@ -11497,12 +11099,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
 	{
@@ -11607,12 +11204,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)
@@ -11660,84 +11254,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
@@ -12403,10 +11919,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;
 
@@ -12759,101 +12272,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;
@@ -12872,12 +12290,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);
@@ -12924,7 +12337,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++)
@@ -12944,7 +12357,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;
 	}
 
@@ -12955,12 +12368,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
@@ -12987,11 +12414,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;
@@ -13011,6 +12439,21 @@ void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, i
 	// WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
 	// JUST GREP FOR "specularscalemod = 1".
 
+	for (q = 0; q < 3; q++)
+	{
+		texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
+		texture.render_modellight_lightdir[q] = q == 2;
+		texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
+		texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
+		texture.render_modellight_specular[q] = r_refdef.view.colorscale;
+		texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
+		texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
+		texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
+		texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
+		texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
+	}
+	texture.currentalpha = 1.0f;
+
 	surface.texture = &texture;
 	surface.num_triangles = numtriangles;
 	surface.num_firsttriangle = firsttriangle;
diff --git a/gl_rsurf.c b/gl_rsurf.c
index 0c9e85dc..0bec0bde 100644
--- a/gl_rsurf.c
+++ b/gl_rsurf.c
@@ -583,10 +583,7 @@ void R_Q1BSP_DrawSky(entity_render_t *ent)
 {
 	if (ent->model == NULL)
 		return;
-	if (ent == r_refdef.scene.worldentity)
-		R_DrawWorldSurfaces(true, true, false, false, false);
-	else
-		R_DrawModelSurfaces(ent, true, true, false, false, false);
+	R_DrawModelSurfaces(ent, true, true, false, false, false);
 }
 
 void R_Q1BSP_DrawAddWaterPlanes(entity_render_t *ent)
@@ -597,10 +594,7 @@ void R_Q1BSP_DrawAddWaterPlanes(entity_render_t *ent)
 	if (model == NULL)
 		return;
 
-	if (ent == r_refdef.scene.worldentity)
-		RSurf_ActiveWorldEntity();
-	else
-		RSurf_ActiveModelEntity(ent, true, false, false);
+	RSurf_ActiveModelEntity(ent, true, false, false);
 
 	surfaces = model->data_surfaces;
 	flagsmask = MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA;
@@ -629,7 +623,7 @@ void R_Q1BSP_DrawAddWaterPlanes(entity_render_t *ent)
 				R_Water_AddWaterPlane(surfaces + j, n);
 		}
 	}
-	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_Q1BSP_Draw(entity_render_t *ent)
@@ -637,10 +631,7 @@ void R_Q1BSP_Draw(entity_render_t *ent)
 	dp_model_t *model = ent->model;
 	if (model == NULL)
 		return;
-	if (ent == r_refdef.scene.worldentity)
-		R_DrawWorldSurfaces(false, true, false, false, false);
-	else
-		R_DrawModelSurfaces(ent, false, true, false, false, false);
+	R_DrawModelSurfaces(ent, false, true, false, false, false);
 }
 
 void R_Q1BSP_DrawDepth(entity_render_t *ent)
@@ -654,10 +645,7 @@ void R_Q1BSP_DrawDepth(entity_render_t *ent)
 	GL_BlendFunc(GL_ONE, GL_ZERO);
 	GL_DepthMask(true);
 //	R_Mesh_ResetTextureState();
-	if (ent == r_refdef.scene.worldentity)
-		R_DrawWorldSurfaces(false, false, true, false, false);
-	else
-		R_DrawModelSurfaces(ent, false, false, true, false, false);
+	R_DrawModelSurfaces(ent, false, false, true, false, false);
 	GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
 }
 
@@ -665,10 +653,7 @@ void R_Q1BSP_DrawDebug(entity_render_t *ent)
 {
 	if (ent->model == NULL)
 		return;
-	if (ent == r_refdef.scene.worldentity)
-		R_DrawWorldSurfaces(false, false, false, true, false);
-	else
-		R_DrawModelSurfaces(ent, false, false, false, true, false);
+	R_DrawModelSurfaces(ent, false, false, false, true, false);
 }
 
 void R_Q1BSP_DrawPrepass(entity_render_t *ent)
@@ -676,10 +661,7 @@ void R_Q1BSP_DrawPrepass(entity_render_t *ent)
 	dp_model_t *model = ent->model;
 	if (model == NULL)
 		return;
-	if (ent == r_refdef.scene.worldentity)
-		R_DrawWorldSurfaces(false, true, false, false, true);
-	else
-		R_DrawModelSurfaces(ent, false, true, false, false, true);
+	R_DrawModelSurfaces(ent, false, true, false, false, true);
 }
 
 typedef struct r_q1bsp_getlightinfo_s
@@ -1257,7 +1239,7 @@ void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, floa
 		info.pvs = info.model->brush.GetPVS(info.model, info.relativelightorigin);
 	else
 		info.pvs = NULL;
-	RSurf_ActiveWorldEntity();
+	RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
 
 	if (!info.noocclusion && r_shadow_compilingrtlight && r_shadow_realtime_world_compileportalculling.integer && info.model->brush.data_portals)
 	{
@@ -1278,7 +1260,7 @@ void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, floa
 		R_Q1BSP_CallRecursiveGetLightInfo(&info, !info.noocclusion && (r_shadow_compilingrtlight ? r_shadow_realtime_world_compilesvbsp.integer : r_shadow_realtime_dlight_svbspculling.integer) != 0);
 	}
 
-	rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
+	rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
 
 	// limit combined leaf box to light boundaries
 	outmins[0] = max(info.outmins[0] - 1, info.lightmins[0]);
@@ -1518,7 +1500,7 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, int numsurfaces, const int *surface
 				;
 			// now figure out what to do with this particular range of surfaces
 			// VorteX: added MATERIALFLAG_NORTLIGHT
-			if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NORTLIGHT)) != MATERIALFLAG_WALL)
+			if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_NORTLIGHT)) != MATERIALFLAG_WALL)
 				continue;
 			if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
 				continue;
diff --git a/model_brush.h b/model_brush.h
index fb167321..2eb38470 100644
--- a/model_brush.h
+++ b/model_brush.h
@@ -115,15 +115,13 @@ mplane_t;
 #define MATERIALFLAG_REFLECTION 0x00100000
 // use model lighting on this material (q1bsp lightmap sampling or q3bsp lightgrid, implies FULLBRIGHT is false)
 #define MATERIALFLAG_MODELLIGHT 0x00200000
-// add directional model lighting to this material (q3bsp lightgrid only)
-#define MATERIALFLAG_MODELLIGHT_DIRECTIONAL 0x00400000
 // causes RSurf_GetCurrentTexture to leave alone certain fields
 #define MATERIALFLAG_CUSTOMSURFACE 0x00800000
 // causes MATERIALFLAG_BLENDED to render a depth pass before rendering, hiding backfaces and other hidden geometry
 #define MATERIALFLAG_TRANSDEPTH 0x01000000
 // like refraction, but doesn't distort etc.
 #define MATERIALFLAG_CAMERA 0x02000000
-// disable rtlight on surface, use R_LightPoint instead
+// disable rtlight on surface - does not disable other types of lighting (LIGHTMAP, MODELLIGHT)
 #define MATERIALFLAG_NORTLIGHT 0x04000000
 // alphagen vertex
 #define MATERIALFLAG_ALPHAGEN_VERTEX 0x08000000
diff --git a/model_shared.h b/model_shared.h
index d2c765c5..f913e4bd 100644
--- a/model_shared.h
+++ b/model_shared.h
@@ -614,14 +614,29 @@ typedef struct texture_s
 	rtexture_t *backgroundnmaptexture; // normalmap (bumpmap for dot3)
 	rtexture_t *backgroundglosstexture; // glossmap (for dot3)
 	rtexture_t *backgroundglowtexture; // glow only (fullbrights)
-	float specularscale;
 	float specularpower;
-	// color tint (colormod * currentalpha) used for rtlighting this material
-	float dlightcolor[3];
-	// color tint (colormod * 2) used for lightmapped lighting on this material
-	// includes alpha as 4th component
-	// replaces role of gl_Color in GLSL shader
-	float lightmapcolor[4];
+
+	// rendering parameters - updated by R_GetCurrentTexture using rsurface.render_* fields
+	// (almost) all map textures are lightmap (no MATERIALFLAG_MODELLIGHT set),
+	// (almost) all model textures are MATERIALFLAG_MODELLIGHT,
+	// MATERIALFLAG_FULLBRIGHT is rendered as a forced MATERIALFLAG_MODELLIGHT with rtlights disabled
+	float render_glowmod[3];
+	// MATERIALFLAG_MODELLIGHT uses these parameters
+	float render_modellight_ambient[3];
+	float render_modellight_diffuse[3];
+	float render_modellight_lightdir[3];
+	float render_modellight_specular[3];
+	// lightmap rendering (not MATERIALFLAG_MODELLIGHT)
+	float render_lightmap_ambient[3];
+	float render_lightmap_diffuse[3];
+	float render_lightmap_specular[3];
+	// rtlights use these colors for the materials on this entity
+	float render_rtlight_diffuse[3];
+	float render_rtlight_specular[3];
+	// tint applied on top of render_*_diffuse for pants layer
+	float render_colormap_pants[3];
+	// tint applied on top of render_*_diffuse for shirt layer
+	float render_colormap_shirt[3];
 
 	// from q3 shaders
 	int customblendfunc[2];
diff --git a/mvm_cmds.c b/mvm_cmds.c
index ace22bfa..a310b0e7 100644
--- a/mvm_cmds.c
+++ b/mvm_cmds.c
@@ -1624,7 +1624,8 @@ void MVM_init_cmd(prvm_prog_t *prog)
 	scene->maxentities = MAX_EDICTS + 256 + 512;
 	scene->entities = (entity_render_t **)Mem_Alloc(prog->progs_mempool, sizeof(entity_render_t *) * scene->maxentities);
 
-	scene->ambient = 32.0f;
+	// LadyHavoc: what is this for?
+	scene->ambientintensity = 32.0f;
 }
 
 void MVM_reset_cmd(prvm_prog_t *prog)
diff --git a/r_shadow.c b/r_shadow.c
index 2d173461..44fd8f29 100644
--- a/r_shadow.c
+++ b/r_shadow.c
@@ -3884,10 +3884,10 @@ static void R_Shadow_RenderLighting_VisibleLighting(int texturenumsurfaces, cons
 	RSurf_DrawBatch();
 }
 
-static void R_Shadow_RenderLighting_Light_GLSL(int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t lightcolor, float ambientscale, float diffusescale, float specularscale)
+static void R_Shadow_RenderLighting_Light_GLSL(int texturenumsurfaces, const msurface_t **texturesurfacelist, const float ambientcolor[3], const float diffusecolor[3], const float specularcolor[3])
 {
 	// ARB2 GLSL shader path (GFFX5200, Radeon 9500)
-	R_SetupShader_Surface(lightcolor, false, ambientscale, diffusescale, specularscale, RSURFPASS_RTLIGHT, texturenumsurfaces, texturesurfacelist, NULL, false);
+	R_SetupShader_Surface(ambientcolor, diffusecolor, specularcolor, RSURFPASS_RTLIGHT, texturenumsurfaces, texturesurfacelist, NULL, false);
 	RSurf_DrawBatch();
 }
 
@@ -3980,29 +3980,26 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve
 	}
 }
 
-static void R_Shadow_RenderLighting_Light_Vertex(int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t lightcolor, float ambientscale, float diffusescale)
+static void R_Shadow_RenderLighting_Light_Vertex(int texturenumsurfaces, const msurface_t **texturesurfacelist, const float ambientcolor[3], const float diffusecolor[3])
 {
 	// OpenGL 1.1 path (anything)
 	float ambientcolorbase[3], diffusecolorbase[3];
 	float ambientcolorpants[3], diffusecolorpants[3];
 	float ambientcolorshirt[3], diffusecolorshirt[3];
-	const float *surfacecolor = rsurface.texture->dlightcolor;
-	const float *surfacepants = rsurface.colormap_pantscolor;
-	const float *surfaceshirt = rsurface.colormap_shirtcolor;
+	const float *surfacepants = rsurface.texture->render_colormap_pants;
+	const float *surfaceshirt = rsurface.texture->render_colormap_shirt;
 	rtexture_t *basetexture = rsurface.texture->basetexture;
 	rtexture_t *pantstexture = rsurface.texture->pantstexture;
 	rtexture_t *shirttexture = rsurface.texture->shirttexture;
 	qboolean dopants = pantstexture && VectorLength2(surfacepants) >= (1.0f / 1048576.0f);
 	qboolean doshirt = shirttexture && VectorLength2(surfaceshirt) >= (1.0f / 1048576.0f);
-	ambientscale *= 2 * r_refdef.view.colorscale;
-	diffusescale *= 2 * r_refdef.view.colorscale;
-	ambientcolorbase[0] = lightcolor[0] * ambientscale * surfacecolor[0];ambientcolorbase[1] = lightcolor[1] * ambientscale * surfacecolor[1];ambientcolorbase[2] = lightcolor[2] * ambientscale * surfacecolor[2];
-	diffusecolorbase[0] = lightcolor[0] * diffusescale * surfacecolor[0];diffusecolorbase[1] = lightcolor[1] * diffusescale * surfacecolor[1];diffusecolorbase[2] = lightcolor[2] * diffusescale * surfacecolor[2];
+	VectorCopy(ambientcolor, ambientcolorbase);
+	VectorCopy(diffusecolor, diffusecolorbase);
 	ambientcolorpants[0] = ambientcolorbase[0] * surfacepants[0];ambientcolorpants[1] = ambientcolorbase[1] * surfacepants[1];ambientcolorpants[2] = ambientcolorbase[2] * surfacepants[2];
 	diffusecolorpants[0] = diffusecolorbase[0] * surfacepants[0];diffusecolorpants[1] = diffusecolorbase[1] * surfacepants[1];diffusecolorpants[2] = diffusecolorbase[2] * surfacepants[2];
 	ambientcolorshirt[0] = ambientcolorbase[0] * surfaceshirt[0];ambientcolorshirt[1] = ambientcolorbase[1] * surfaceshirt[1];ambientcolorshirt[2] = ambientcolorbase[2] * surfaceshirt[2];
 	diffusecolorshirt[0] = diffusecolorbase[0] * surfaceshirt[0];diffusecolorshirt[1] = diffusecolorbase[1] * surfaceshirt[1];diffusecolorshirt[2] = diffusecolorbase[2] * surfaceshirt[2];
-	RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | (diffusescale > 0 ? BATCHNEED_ARRAY_NORMAL : 0) | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+	RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | (VectorLength2(diffusecolor) > 0 ? BATCHNEED_ARRAY_NORMAL : 0) | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
 	rsurface.passcolor4f = (float *)R_FrameData_Alloc((rsurface.batchfirstvertex + rsurface.batchnumvertices) * sizeof(float[4]));
 	R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
 	R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
@@ -4052,25 +4049,28 @@ static void R_Shadow_RenderLighting_Light_Vertex(int texturenumsurfaces, const m
 extern cvar_t gl_lightmaps;
 void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist)
 {
-	float ambientscale, diffusescale, specularscale;
 	qboolean negated;
-	float lightcolor[3];
-	VectorCopy(rsurface.rtlight->currentcolor, lightcolor);
-	ambientscale = rsurface.rtlight->ambientscale + rsurface.texture->rtlightambient;
-	diffusescale = rsurface.rtlight->diffusescale * max(0, 1.0 - rsurface.texture->rtlightambient);
-	specularscale = rsurface.rtlight->specularscale * rsurface.texture->specularscale;
+	float ambientcolor[3], diffusecolor[3], specularcolor[3];
+	VectorM(rsurface.rtlight->ambientscale + rsurface.texture->rtlightambient, rsurface.texture->render_rtlight_diffuse, ambientcolor);
+	VectorM(rsurface.rtlight->diffusescale * max(0, 1.0 - rsurface.texture->rtlightambient), rsurface.texture->render_rtlight_diffuse, diffusecolor);
+	VectorM(rsurface.rtlight->specularscale, rsurface.texture->render_rtlight_specular, specularcolor);
 	if (!r_shadow_usenormalmap.integer)
 	{
-		ambientscale += 1.0f * diffusescale;
-		diffusescale = 0;
-		specularscale = 0;
+		VectorMAM(1.0f, ambientcolor, 1.0f, diffusecolor, ambientcolor);
+		VectorClear(diffusecolor);
+		VectorClear(specularcolor);
 	}
-	if ((ambientscale + diffusescale) * VectorLength2(lightcolor) + specularscale * VectorLength2(lightcolor) < (1.0f / 1048576.0f))
+	VectorMultiply(ambientcolor, rsurface.rtlight->currentcolor, ambientcolor);
+	VectorMultiply(diffusecolor, rsurface.rtlight->currentcolor, diffusecolor);
+	VectorMultiply(specularcolor, rsurface.rtlight->currentcolor, specularcolor);
+	if (VectorLength2(ambientcolor) + VectorLength2(diffusecolor) + VectorLength2(specularcolor) < (1.0f / 1048576.0f))
 		return;
-	negated = (lightcolor[0] + lightcolor[1] + lightcolor[2] < 0) && vid.support.ext_blend_subtract;
+	negated = (rsurface.rtlight->currentcolor[0] + rsurface.rtlight->currentcolor[1] + rsurface.rtlight->currentcolor[2] < 0) && vid.support.ext_blend_subtract;
 	if(negated)
 	{
-		VectorNegate(lightcolor, lightcolor);
+		VectorNegate(ambientcolor, ambientcolor);
+		VectorNegate(diffusecolor, diffusecolor);
+		VectorNegate(specularcolor, specularcolor);
 		GL_BlendEquationSubtract(true);
 	}
 	RSurf_SetupDepthAndCulling();
@@ -4081,13 +4081,13 @@ void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **textures
 		R_Shadow_RenderLighting_VisibleLighting(texturenumsurfaces, texturesurfacelist);
 		break;
 	case R_SHADOW_RENDERMODE_LIGHT_GLSL:
-		R_Shadow_RenderLighting_Light_GLSL(texturenumsurfaces, texturesurfacelist, lightcolor, ambientscale, diffusescale, specularscale);
+		R_Shadow_RenderLighting_Light_GLSL(texturenumsurfaces, texturesurfacelist, ambientcolor, diffusecolor, specularcolor);
 		break;
 	case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
 	case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
 	case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
 	case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
-		R_Shadow_RenderLighting_Light_Vertex(texturenumsurfaces, texturesurfacelist, lightcolor, ambientscale, diffusescale);
+		R_Shadow_RenderLighting_Light_Vertex(texturenumsurfaces, texturesurfacelist, ambientcolor, diffusecolor);
 		break;
 	default:
 		Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
@@ -4464,7 +4464,7 @@ static void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist
 {
 	shadowmesh_t *mesh;
 
-	RSurf_ActiveWorldEntity();
+	RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
 
 	if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
 	{
@@ -4484,7 +4484,7 @@ static void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist
 	else if (r_refdef.scene.worldentity->model)
 		r_refdef.scene.worldmodel->DrawShadowMap(r_shadow_shadowmapside, r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, surfacesides, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs);
 
-	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_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, const unsigned char *trispvs)
@@ -4499,7 +4499,7 @@ static void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacel
 	if (r_refdef.scene.worldmodel->brush.shadowmesh ? !r_refdef.scene.worldmodel->brush.shadowmesh->neighbor3i : !r_refdef.scene.worldmodel->surfmesh.data_neighbor3i)
 		return;
 
-	RSurf_ActiveWorldEntity();
+	RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
 
 	if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
 	{
@@ -4556,7 +4556,7 @@ static void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacel
 		r_refdef.scene.worldmodel->DrawShadowVolume(r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs);
 	}
 
-	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_Shadow_DrawEntityShadow(entity_render_t *ent)
@@ -4582,7 +4582,7 @@ static void R_Shadow_DrawEntityShadow(entity_render_t *ent)
 		ent->model->DrawShadowVolume(ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
 		break;
 	}
-	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_Shadow_SetupEntityLight(const entity_render_t *ent)
@@ -4601,7 +4601,7 @@ static void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const uns
 		return;
 
 	// set up properties for rendering light onto this entity
-	RSurf_ActiveWorldEntity();
+	RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
 	rsurface.entitytolight = rsurface.rtlight->matrix_worldtolight;
 	Matrix4x4_Concat(&rsurface.entitytoattenuationxyz, &matrix_attenuationxyz, &rsurface.entitytolight);
 	Matrix4x4_Concat(&rsurface.entitytoattenuationz, &matrix_attenuationz, &rsurface.entitytolight);
@@ -4609,7 +4609,7 @@ static void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const uns
 
 	r_refdef.scene.worldmodel->DrawLight(r_refdef.scene.worldentity, numsurfaces, surfacelist, lighttrispvs);
 
-	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_Shadow_DrawEntityLight(entity_render_t *ent)
@@ -4622,7 +4622,7 @@ static void R_Shadow_DrawEntityLight(entity_render_t *ent)
 
 	model->DrawLight(ent, model->nummodelsurfaces, model->sortedmodelsurfaces, NULL);
 
-	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_Shadow_PrepareLight(rtlight_t *rtlight)
@@ -5572,7 +5572,7 @@ void R_Shadow_PrepareModelShadows(void)
 	r_shadow_nummodelshadows = 0;
 	r_shadow_shadowmapatlas_modelshadows_size = 0;
 
-	if (!r_refdef.scene.numentities || r_refdef.lightmapintensity <= 0.0f || r_shadows.integer <= 0)
+	if (!r_refdef.scene.numentities || r_refdef.scene.lightmapintensity <= 0.0f || r_shadows.integer <= 0)
 		return;
 
 	switch (r_shadow_shadowmode)
@@ -5740,7 +5740,7 @@ static void R_Shadow_DrawModelShadowMaps(void)
 		relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
 		RSurf_ActiveModelEntity(ent, false, false, false);
 		ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
-		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 0
@@ -5837,45 +5837,14 @@ void R_Shadow_DrawModelShadows(void)
 			Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
 		else
 		{
-			if(ent->entitynumber != 0)
-			{
-				if(ent->entitynumber >= MAX_EDICTS) // csqc entity
-				{
-					// FIXME handle this
-					VectorNegate(ent->modellight_lightdir, relativelightdirection);
-				}
-				else
-				{
-					// networked entity - might be attached in some way (then we should use the parent's light direction, to not tear apart attached entities)
-					int entnum, entnum2, recursion;
-					entnum = entnum2 = ent->entitynumber;
-					for(recursion = 32; recursion > 0; --recursion)
-					{
-						entnum2 = cl.entities[entnum].state_current.tagentity;
-						if(entnum2 >= 1 && entnum2 < cl.num_entities && cl.entities_active[entnum2])
-							entnum = entnum2;
-						else
-							break;
-					}
-					if(recursion && recursion != 32) // if we followed a valid non-empty attachment chain
-					{
-						VectorNegate(cl.entities[entnum].render.modellight_lightdir, relativelightdirection);
-						// transform into modelspace of OUR entity
-						Matrix4x4_Transform3x3(&cl.entities[entnum].render.matrix, relativelightdirection, tmp);
-						Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection);
-					}
-					else
-						VectorNegate(ent->modellight_lightdir, relativelightdirection);
-				}
-			}
-			else
-				VectorNegate(ent->modellight_lightdir, relativelightdirection);
+			VectorNegate(ent->render_modellight_lightdir, tmp);
+			Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection);
 		}
 
 		VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin);
 		RSurf_ActiveModelEntity(ent, false, false, false);
 		ent->model->DrawShadowVolume(ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
-		rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
+		rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
 	}
 
 	// not really the right mode, but this will disable any silly stencil features
@@ -6110,7 +6079,7 @@ void R_Shadow_DrawCoronas(void)
 				qglGenQueriesARB(r_maxqueries - i, r_queries + i);
 				CHECKGLERROR
 			}
-			RSurf_ActiveWorldEntity();
+			RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
 			GL_BlendFunc(GL_ONE, GL_ZERO);
 			GL_CullFace(GL_NONE);
 			GL_DepthMask(false);
@@ -7574,141 +7543,48 @@ LIGHT SAMPLING
 =============================================================================
 */
 
-void R_LightPoint(float *color, const vec3_t p, const int flags)
+void R_CompleteLightPoint(float *ambient, float *diffuse, float *lightdir, const vec3_t p, const int flags, float lightmapintensity, float ambientintensity)
 {
-	int i, numlights, flag;
-	float f, relativepoint[3], dist, dist2, lightradius2;
-	vec3_t diffuse, n;
-	rtlight_t *light;
-	dlight_t *dlight;
-
-	if (r_fullbright.integer)
-	{
-		VectorSet(color, 1, 1, 1);
-		return;
-	}
-
-	VectorClear(color);
-
-	if (flags & LP_LIGHTMAP)
-	{
-		if (!r_fullbright.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
-		{
-			VectorClear(diffuse);
-			r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, color, diffuse, n);
-			VectorAdd(color, diffuse, color);
-		}
-		else
-			VectorSet(color, 1, 1, 1);
-		color[0] += r_refdef.scene.ambient;
-		color[1] += r_refdef.scene.ambient;
-		color[2] += r_refdef.scene.ambient;
-	}
-
-	if (flags & LP_RTWORLD)
-	{
-		flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
-		numlights = (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
-		for (i = 0; i < numlights; i++)
-		{
-			dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i);
-			if (!dlight)
-				continue;
-			light = &dlight->rtlight;
-			if (!(light->flags & flag))
-				continue;
-			// sample
-			lightradius2 = light->radius * light->radius;
-			VectorSubtract(light->shadoworigin, p, relativepoint);
-			dist2 = VectorLength2(relativepoint);
-			if (dist2 >= lightradius2)
-				continue;
-			dist = sqrt(dist2) / light->radius;
-			f = dist < 1 ? (r_shadow_lightintensityscale.value * ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist))) : 0;
-			if (f <= 0)
-				continue;
-			// todo: add to both ambient and diffuse
-			if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1)
-				VectorMA(color, f, light->currentcolor, color);
-		}
-	}
-	if (flags & LP_DYNLIGHT)
-	{
-		// sample dlights
-		for (i = 0;i < r_refdef.scene.numlights;i++)
-		{
-			light = r_refdef.scene.lights[i];
-			// sample
-			lightradius2 = light->radius * light->radius;
-			VectorSubtract(light->shadoworigin, p, relativepoint);
-			dist2 = VectorLength2(relativepoint);
-			if (dist2 >= lightradius2)
-				continue;
-			dist = sqrt(dist2) / light->radius;
-			f = dist < 1 ? (r_shadow_lightintensityscale.value * ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist))) : 0;
-			if (f <= 0)
-				continue;
-			// todo: add to both ambient and diffuse
-			if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1)
-				VectorMA(color, f, light->color, color);
-		}
-	}
-}
-
-void R_CompleteLightPoint(vec3_t ambient, vec3_t diffuse, vec3_t lightdir, const vec3_t p, const int flags)
-{
-	int i, numlights, flag;
+	int i, numlights, flag, q;
 	rtlight_t *light;
 	dlight_t *dlight;
 	float relativepoint[3];
 	float color[3];
-	float dir[3];
 	float dist;
 	float dist2;
 	float intensity;
-	float sample[5*3];
+	float sa[3], sx[3], sy[3], sz[3], sd[3];
 	float lightradius2;
 
-	if (r_fullbright.integer)
-	{
-		VectorSet(ambient, 1, 1, 1);
-		VectorClear(diffuse);
-		VectorClear(lightdir);
-		return;
-	}
+	// use first order spherical harmonics to combine directional lights
+	for (q = 0; q < 3; q++)
+		sa[q] = sx[q] = sy[q] = sz[q] = sd[q] = 0;
 
-	if (flags == LP_LIGHTMAP)
+	if (flags & LP_LIGHTMAP)
 	{
-		VectorSet(ambient, r_refdef.scene.ambient, r_refdef.scene.ambient, r_refdef.scene.ambient);
-		VectorClear(diffuse);
-		VectorClear(lightdir);
 		if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
-			r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, ambient, diffuse, lightdir);
+		{
+			float tempambient[3];
+			for (q = 0; q < 3; q++)
+				tempambient[q] = color[q] = relativepoint[q] = 0;
+			r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, tempambient, color, relativepoint);
+			// calculate a weighted average light direction as well
+			intensity = VectorLength(color);
+			for (q = 0; q < 3; q++)
+			{
+				sa[q] += (0.5f * color[q] + tempambient[q]) * lightmapintensity;
+				sx[q] += (relativepoint[0] * color[q]) * lightmapintensity;
+				sy[q] += (relativepoint[1] * color[q]) * lightmapintensity;
+				sz[q] += (relativepoint[2] * color[q]) * lightmapintensity;
+				sd[q] += (intensity * relativepoint[q]) * lightmapintensity;
+			}
+		}
 		else
-			VectorSet(ambient, 1, 1, 1);
-		return;
-	}
-
-	memset(sample, 0, sizeof(sample));
-	VectorSet(sample, r_refdef.scene.ambient, r_refdef.scene.ambient, r_refdef.scene.ambient);
-
-	if ((flags & LP_LIGHTMAP) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
-	{
-		vec3_t tempambient;
-		VectorClear(tempambient);
-		VectorClear(color);
-		VectorClear(relativepoint);
-		r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, tempambient, color, relativepoint);
-		VectorScale(tempambient, r_refdef.lightmapintensity, tempambient);
-		VectorScale(color, r_refdef.lightmapintensity, color);
-		VectorAdd(sample, tempambient, sample);
-		VectorMA(sample    , 0.5f            , color, sample    );
-		VectorMA(sample + 3, relativepoint[0], color, sample + 3);
-		VectorMA(sample + 6, relativepoint[1], color, sample + 6);
-		VectorMA(sample + 9, relativepoint[2], color, sample + 9);
-		// calculate a weighted average light direction as well
-		intensity = VectorLength(color);
-		VectorMA(sample + 12, intensity, relativepoint, sample + 12);
+		{
+			// unlit map - fullbright but scaled by lightmapintensity
+			for (q = 0; q < 3; q++)
+				sa[q] += lightmapintensity;
+		}
 	}
 
 	if (flags & LP_RTWORLD)
@@ -7735,17 +7611,18 @@ void R_CompleteLightPoint(vec3_t ambient, vec3_t diffuse, vec3_t lightdir, const
 				continue;
 			if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
 				continue;
-			// scale down intensity to add to both ambient and diffuse
-			//intensity *= 0.5f;
+			for (q = 0; q < 3; q++)
+				color[q] = light->currentcolor[q] * intensity;
+			intensity = VectorLength(color);
 			VectorNormalize(relativepoint);
-			VectorScale(light->currentcolor, intensity, color);
-			VectorMA(sample    , 0.5f            , color, sample    );
-			VectorMA(sample + 3, relativepoint[0], color, sample + 3);
-			VectorMA(sample + 6, relativepoint[1], color, sample + 6);
-			VectorMA(sample + 9, relativepoint[2], color, sample + 9);
-			// calculate a weighted average light direction as well
-			intensity *= VectorLength(color);
-			VectorMA(sample + 12, intensity, relativepoint, sample + 12);
+			for (q = 0; q < 3; q++)
+			{
+				sa[q] += 0.5f * color[q];
+				sx[q] += relativepoint[0] * color[q];
+				sy[q] += relativepoint[1] * color[q];
+				sz[q] += relativepoint[2] * color[q];
+				sd[q] += intensity * relativepoint[q];
+			}
 		}
 		// FIXME: sample bouncegrid too!
 	}
@@ -7768,30 +7645,30 @@ void R_CompleteLightPoint(vec3_t ambient, vec3_t diffuse, vec3_t lightdir, const
 				continue;
 			if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
 				continue;
-			// scale down intensity to add to both ambient and diffuse
-			//intensity *= 0.5f;
+			for (q = 0; q < 3; q++)
+				color[q] = light->currentcolor[q] * intensity;
+			intensity = VectorLength(color);
 			VectorNormalize(relativepoint);
-			VectorScale(light->currentcolor, intensity, color);
-			VectorMA(sample    , 0.5f            , color, sample    );
-			VectorMA(sample + 3, relativepoint[0], color, sample + 3);
-			VectorMA(sample + 6, relativepoint[1], color, sample + 6);
-			VectorMA(sample + 9, relativepoint[2], color, sample + 9);
-			// calculate a weighted average light direction as well
-			intensity *= VectorLength(color);
-			VectorMA(sample + 12, intensity, relativepoint, sample + 12);
+			for (q = 0; q < 3; q++)
+			{
+				sa[q] += 0.5f * color[q];
+				sx[q] += relativepoint[0] * color[q];
+				sy[q] += relativepoint[1] * color[q];
+				sz[q] += relativepoint[2] * color[q];
+				sd[q] += intensity * relativepoint[q];
+			}
 		}
 	}
 
-	// calculate the direction we'll use to reduce the sample to a directional light source
-	VectorCopy(sample + 12, dir);
-	//VectorSet(dir, sample[3] + sample[4] + sample[5], sample[6] + sample[7] + sample[8], sample[9] + sample[10] + sample[11]);
-	VectorNormalize(dir);
-	// extract the diffuse color along the chosen direction and scale it
-	diffuse[0] = (dir[0]*sample[3] + dir[1]*sample[6] + dir[2]*sample[ 9] + sample[ 0]);
-	diffuse[1] = (dir[0]*sample[4] + dir[1]*sample[7] + dir[2]*sample[10] + sample[ 1]);
-	diffuse[2] = (dir[0]*sample[5] + dir[1]*sample[8] + dir[2]*sample[11] + sample[ 2]);
-	// subtract some of diffuse from ambient
-	VectorMA(sample, -0.333f, diffuse, ambient);
-	// store the normalized lightdir
-	VectorCopy(dir, lightdir);
+	// calculate the weighted-average light direction (bentnormal)
+	for (q = 0; q < 3; q++)
+		lightdir[q] = sd[q];
+	VectorNormalize(lightdir);
+	for (q = 0; q < 3; q++)
+	{
+		// extract the diffuse color along the chosen direction and scale it
+		diffuse[q] = (lightdir[0] * sx[q] + lightdir[1] * sy[q] + lightdir[2] * sz[q]);
+		// subtract some of diffuse from ambient
+		ambient[q] = sa[q] + -0.333f * diffuse[q] + ambientintensity;
+	}
 }
diff --git a/r_shadow.h b/r_shadow.h
index 3346b77e..809805eb 100644
--- a/r_shadow.h
+++ b/r_shadow.h
@@ -159,8 +159,7 @@ void R_Shadow_PrepareModelShadows(void);
 #define LP_LIGHTMAP		1
 #define LP_RTWORLD		2
 #define LP_DYNLIGHT		4
-void R_LightPoint(float *color, const vec3_t p, const int flags);
-void R_CompleteLightPoint(float *ambientcolor, float *diffusecolor, float *diffusenormal, const vec3_t p, const int flags);
+void R_CompleteLightPoint(float *ambient, float *diffuse, float *lightdir, const vec3_t p, const int flags, float lightmapintensity, float ambientintensity);
 
 void R_Shadow_DrawShadowMaps(void);
 void R_Shadow_DrawModelShadows(void);
diff --git a/r_sprites.c b/r_sprites.c
index a45a3e73..d72bee10 100644
--- a/r_sprites.c
+++ b/r_sprites.c
@@ -392,9 +392,15 @@ static void R_Model_Sprite_Draw_TransparentCallback(const entity_render_t *ent,
 			frame = model->sprite.sprdata_frames + ent->frameblend[i].subframe;
 			texture = R_GetCurrentTexture(model->data_textures + ent->frameblend[i].subframe);
 		
-			// lit sprite by lightgrid if it is not fullbright, lit only ambient
+			// sprites are fullbright by default, but if this one is not fullbright we
+			// need to combine the lighting into ambient as sprite lighting is not
+			// directional
 			if (!(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
-				VectorAdd(ent->modellight_ambient, ent->modellight_diffuse, rsurface.modellight_ambient); // sprites dont use lightdirection
+			{
+				VectorMAM(1.0f, texture->render_modellight_ambient, 0.25f, texture->render_modellight_diffuse, texture->render_modellight_ambient);
+				VectorClear(texture->render_modellight_diffuse);
+				VectorClear(texture->render_modellight_specular);
+			}
 
 			// SPR_LABEL should not use depth test AT ALL
 			if(model->sprite.sprnum_type == SPR_LABEL || model->sprite.sprnum_type == SPR_LABEL_SCALE)
diff --git a/render.h b/render.h
index 52e3e705..8f387103 100644
--- a/render.h
+++ b/render.h
@@ -127,7 +127,7 @@ extern cvar_t r_wateralpha;
 extern cvar_t r_dynamic;
 
 void R_UpdateVariables(void); // must call after setting up most of r_refdef, but before calling R_RenderView
-void R_RenderView(void); // must set r_refdef and call R_UpdateVariables first
+void R_RenderView(void); // must set r_refdef and call R_UpdateVariables and CL_UpdateEntityShading first
 void R_RenderView_UpdateViewVectors(void); // just updates r_refdef.view.{forward,left,up,origin,right,inverse_matrix}
 
 typedef enum r_refdef_scene_type_s {
@@ -404,18 +404,6 @@ typedef struct rsurfacestate_s
 	// animation blending state from entity
 	frameblend_t frameblend[MAX_FRAMEBLENDS];
 	skeleton_t *skeleton;
-	// directional model shading state from entity
-	vec3_t modellight_ambient;
-	vec3_t modellight_diffuse;
-	vec3_t modellight_lightdir;
-	// colormapping state from entity (these are black if colormapping is off)
-	vec3_t colormap_pantscolor;
-	vec3_t colormap_shirtcolor;
-	// special coloring of ambient/diffuse textures (gloss not affected)
-	// colormod[3] is the alpha of the entity
-	float colormod[4];
-	// special coloring of glow textures
-	float glowmod[3];
 	// view location in model space
 	vec3_t localvieworigin;
 	// polygon offset data for submodels
@@ -454,8 +442,8 @@ typedef struct rsurfacestate_s
 	float userwavefunc_param[Q3WAVEFUNC_USER_COUNT];
 
 	// pointer to an entity_render_t used only by R_GetCurrentTexture and
-	// RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity as a unique id within
-	// each frame (see r_frame also)
+	// RSurf_ActiveModelEntity as a unique id within each frame (see r_frame
+	// also)
 	entity_render_t *entity;
 }
 rsurfacestate_t;
@@ -464,7 +452,6 @@ extern rsurfacestate_t rsurface;
 
 void R_HDR_UpdateIrisAdaptation(const vec3_t point);
 
-void RSurf_ActiveWorldEntity(void);
 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass);
 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);
 void RSurf_SetupDepthAndCulling(void);
@@ -511,7 +498,7 @@ rsurfacepass_t;
 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha);
 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy);
 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal);
-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 *waterplane, qboolean notrippy);
+void R_SetupShader_Surface(const float ambientcolor[3], const float diffusecolor[3], const float specularcolor[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *waterplane, qboolean notrippy);
 void R_SetupShader_DeferredLight(const rtlight_t *rtlight);
 
 typedef struct r_waterstate_waterplane_s
diff --git a/shader_glsl.h b/shader_glsl.h
index a69dbbc5..36542c53 100644
--- a/shader_glsl.h
+++ b/shader_glsl.h
@@ -1421,12 +1421,6 @@
 "uniform sampler2D Texture_ReflectMask;\n",
 "uniform samplerCube Texture_ReflectCube;\n",
 "#endif\n",
-"#ifdef MODE_LIGHTDIRECTION\n",
-"uniform myhalf3 LightColor;\n",
-"#endif\n",
-"#ifdef MODE_LIGHTSOURCE\n",
-"uniform myhalf3 LightColor;\n",
-"#endif\n",
 "#ifdef USEBOUNCEGRID\n",
 "uniform sampler3D Texture_BounceGrid;\n",
 "uniform float BounceGridIntensity;\n",
@@ -1528,7 +1522,6 @@
 "#else\n",
 "	color.rgb = diffusetex * Color_Ambient;\n",
 "#endif\n",
-"	color.rgb *= LightColor;\n",
 "	color.rgb *= cast_myhalf(dp_texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n",
 "#if defined(USESHADOWMAP2D)\n",
 "	color.rgb *= ShadowMapCompare(CubeVector);\n",
@@ -1546,7 +1539,7 @@
 "	#ifdef USEDIFFUSE\n",
 "		myhalf3 lightnormal = cast_myhalf3(normalize(LightVector));\n",
 "	#endif\n",
-"	#define lightcolor LightColor\n",
+"	#define lightcolor 1\n",
 "#endif // MODE_LIGHTDIRECTION\n",
 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n",
 "   #define SHADING\n",
@@ -1589,7 +1582,7 @@
 "#ifdef MODE_FAKELIGHT\n",
 "	#define SHADING\n",
 "	myhalf3 lightnormal = cast_myhalf3(normalize(EyeVectorFogDepth.xyz));\n",
-"	myhalf3 lightcolor = cast_myhalf3(1.0);\n",
+"	#define lightcolor 1\n",
 "#endif // MODE_FAKELIGHT\n",
 "\n",
 "\n",
diff --git a/shader_hlsl.h b/shader_hlsl.h
index 9b3f04c3..57df52d0 100644
--- a/shader_hlsl.h
+++ b/shader_hlsl.h
@@ -1329,12 +1329,6 @@
 "uniform sampler Texture_ReflectMask : register(s5),\n",
 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n",
 "#endif\n",
-"#ifdef MODE_LIGHTDIRECTION\n",
-"uniform half3 LightColor : register(c21),\n",
-"#endif\n",
-"#ifdef MODE_LIGHTSOURCE\n",
-"uniform half3 LightColor : register(c21),\n",
-"#endif\n",
 "\n",
 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n",
 "uniform sampler Texture_Attenuation : register(s9),\n",
@@ -1451,7 +1445,6 @@
 "#else\n",
 "	color.rgb = diffusetex * Color_Ambient;\n",
 "#endif\n",
-"	color.rgb *= LightColor;\n",
 "	color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n",
 "#if defined(USESHADOWMAP2D)\n",
 "	color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n",
@@ -1497,7 +1490,7 @@
 "	#ifdef USEDIFFUSE\n",
 "		half3 lightnormal = half3(normalize(LightVector));\n",
 "	#endif\n",
-"	#define lightcolor LightColor\n",
+"	#define lightcolor 1\n",
 "#endif // MODE_LIGHTDIRECTION\n",
 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n",
 "	#define SHADING\n",
@@ -1536,7 +1529,7 @@
 "#ifdef MODE_FAKELIGHT\n",
 "	#define SHADING\n",
 "	half3 lightnormal = half3(normalize(EyeVector));\n",
-"	half3 lightcolor = half3(1.0,1.0,1.0);\n",
+"	#define lightcolor 1\n",
 "#endif // MODE_FAKELIGHT\n",
 "\n",
 "\n",