diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c
index d7b724cda..cdfe1320f 100644
--- a/engine/gl/gl_vidcommon.c
+++ b/engine/gl/gl_vidcommon.c
@@ -290,27 +290,27 @@ void (APIENTRY myGLDEBUGPROCAMD)(GLenum source,
 	switch(type)
 	{
 	case GL_DEBUG_TYPE_ERROR_ARB:
-		OutputDebugString("Error: ");
+		OutputDebugStringA("Error: ");
 		break;
 	case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
-		OutputDebugString("Depricated: ");
+		OutputDebugStringA("Depricated: ");
 		break;
 	case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
-		OutputDebugString("Undefined: ");
+		OutputDebugStringA("Undefined: ");
 		break;
 	case GL_DEBUG_TYPE_PORTABILITY_ARB:
-		OutputDebugString("Portability: ");
+		OutputDebugStringA("Portability: ");
 		break;
 	case GL_DEBUG_TYPE_PERFORMANCE_ARB:
-		OutputDebugString("Performance: ");
+		OutputDebugStringA("Performance: ");
 		break;
 	default:
 	case GL_DEBUG_TYPE_OTHER_ARB:
-		OutputDebugString("Other: ");
+		OutputDebugStringA("Other: ");
 		break;
 	}
-	OutputDebugString(message);
-	OutputDebugString("\n");
+	OutputDebugStringA(message);
+	OutputDebugStringA("\n");
 }
 #endif
 
@@ -1154,8 +1154,7 @@ static const char *glsl_hdrs[] =
 			"#ifdef SPOT\n"
 				//bias it. don't bother figuring out which side or anything, its not needed
 				//l_projmatrix contains the light's projection matrix so no other magic needed
-				"vtexprojcoord.z -= 0.015;\n"
-				"return (vtexprojcoord.xyz/vtexprojcoord.w + vec3(1.0, 1.0, 1.0)) * vec3(0.5, 0.5, 0.5);\n"
+				"return ((vtexprojcoord.xyz-vec3(0.0,0.0,0.015))/vtexprojcoord.w + vec3(1.0, 1.0, 1.0)) * vec3(0.5, 0.5, 0.5);\n"
 			//"#elif defined(CUBESHADOW)\n"
 			//	vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w;
 			//	#define dosamp(x,y) shadowCube(s_t4, shadowcoord + vec2(x,y)*texscale.xy).r
diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h
index dd1c4a450..fbe57853b 100644
--- a/engine/gl/r_bishaders.h
+++ b/engine/gl/r_bishaders.h
@@ -382,6 +382,39 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
 "}\n"
 "#endif\n"
 
+},
+#endif
+#ifdef D3D11QUAKE
+{QR_DIRECT3D11, 11, "depthonly",
+//used for generating shadowmaps and stuff that draws nothing.
+
+"struct a2v\n"
+"{\n"
+"float4 pos: POSITION;\n"
+"float3 normal: NORMAL;\n"
+"};\n"
+"struct v2f\n"
+"{\n"
+"float4 pos: SV_POSITION;\n"
+"};\n"
+
+"#include <ftedefs.h>\n"
+
+"#ifdef VERTEX_SHADER\n"
+"v2f main (a2v inp)\n"
+"{\n"
+"v2f outp;\n"
+"outp.pos = mul(m_model, inp.pos);\n"
+"outp.pos = mul(m_view, outp.pos);\n"
+"outp.pos = mul(m_projection, outp.pos);\n"
+"return outp;\n"
+"}\n"
+"#endif\n"
+"#ifdef FRAGMENT_SHADER\n"
+"void main (v2f inp) : SV_TARGET\n"
+"{\n"
+"}\n"
+"#endif\n"
 },
 #endif
 #ifdef GLQUAKE
@@ -1866,8 +1899,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
 /*filter the light by the shadowmap. logically a boolean, but we allow fractions for softer shadows*/
 //diff.rgb = (vtexprojcoord.xyz/vtexprojcoord.w) * 0.5 + 0.5;
 "colorscale *= ShadowmapFilter();\n"
-//	gl_FragColor.rgb = vec3(ShadowmapFilter());
-
+//	diff = ShadowmapCoord();
 "#endif\n"
 
 "#if defined(PROJECTION)\n"
@@ -1946,6 +1978,240 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
 "#endif\n"
 },
 #endif
+#ifdef D3D11QUAKE
+{QR_DIRECT3D11, 11, "rtlight",
+"!!permu BUMP\n"
+"!!permu FRAMEBLEND\n"
+"!!permu SKELETAL\n"
+"!!permu UPPERLOWER\n"
+"!!permu FOG\n"
+"!!cvarf r_glsl_offsetmapping_scale\n"
+"!!cvardf r_glsl_pcf\n"
+
+
+//this is the main shader responsible for realtime dlights.
+
+//texture units:
+//s0=diffuse, s1=normal, s2=specular, s3=shadowmap
+//custom modifiers:
+//PCF(shadowmap)
+//CUBEPROJ(projected cubemap)
+//SPOT(projected circle
+//CUBESHADOW
+
+"#undef CUBE //engine cannot load cubemaps properly with d3d yet.\n"
+
+"#ifndef r_glsl_pcf\n"
+"#error r_glsl_pcf wasn't defined\n"
+"#endif\n"
+"#if r_glsl_pcf < 1\n"
+"#undef r_glsl_pcf\n"
+"#define r_glsl_pcf 9\n"
+"#endif\n"
+
+"#ifdef UPPERLOWER\n"
+"#define UPPER\n"
+"#define LOWER\n"
+"#endif\n"
+
+
+"struct a2v\n"
+"{\n"
+"float4 pos: POSITION;\n"
+"float4 tc: TEXCOORD0;\n"
+"float3 n: NORMAL;\n"
+"float3 s: TANGENT;\n"
+"float3 t: BINORMAL;\n"
+"};\n"
+"struct v2f\n"
+"{\n"
+"float4 pos: SV_POSITION;\n"
+"float2 tc: TEXCOORD0;\n"
+"float3 lightvector: TEXCOORD1;\n"
+"float3 eyevector: TEXCOORD2;\n"
+"float3 vtexprojcoord: TEXCOORD3;\n"
+"};\n"
+
+"#include <ftedefs.h>\n"
+
+"#ifdef VERTEX_SHADER\n"
+"v2f main (a2v inp)\n"
+"{\n"
+"v2f outp;\n"
+"float4 wpos;\n"
+"wpos = mul(m_model, inp.pos);\n"
+"outp.pos = mul(m_view, wpos);\n"
+"outp.pos = mul(m_projection, outp.pos);\n"
+"outp.tc = inp.tc.xy;\n"
+"float3 lightminusvertex = l_lightposition - wpos.xyz;\n"
+"outp.lightvector.x = -dot(lightminusvertex, inp.s.xyz);\n"
+"outp.lightvector.y = dot(lightminusvertex, inp.t.xyz);\n"
+"outp.lightvector.z = dot(lightminusvertex, inp.n.xyz);\n"
+"float3 eyeminusvertex = e_eyepos - wpos.xyz;\n"
+"outp.eyevector.x = -dot(eyeminusvertex, inp.s.xyz);\n"
+"outp.eyevector.y = dot(eyeminusvertex, inp.t.xyz);\n"
+"outp.eyevector.z = dot(eyeminusvertex, inp.n.xyz);\n"
+"outp.vtexprojcoord = mul(l_cubematrix, wpos).xyz;\n"
+"return outp;\n"
+"}\n"
+"#endif\n"
+
+
+"#ifdef FRAGMENT_SHADER\n"
+
+"Texture2D tx_base : register(t0);\n"
+"Texture2D tx_bump : register(t1);\n"
+"Texture2D tx_spec : register(t2);\n"
+"TextureCube tx_cube : register(t3);\n"
+"Texture2D tx_smap : register(t4);\n"
+"Texture2D tx_lower : register(t5);\n"
+"Texture2D tx_upper : register(t6);\n"
+
+"SamplerState ss_base : register(s0);\n"
+"SamplerState ss_bump : register(s1);\n"
+"SamplerState ss_spec : register(s2);\n"
+"SamplerState ss_cube : register(s3);\n"
+"SamplerComparisonState ss_smap : register(s4);\n"
+"SamplerState ss_lower : register(s5);\n"
+"SamplerState ss_upper : register(s6);\n"
+
+"#ifdef PCF\n"
+"float3 ShadowmapCoord(float3 vtexprojcoord)\n"
+"{\n"
+"#ifdef SPOT\n"
+//bias it. don't bother figuring out which side or anything, its not needed
+//l_projmatrix contains the light's projection matrix so no other magic needed
+"vtexprojcoord.z -= 0.015;\n"
+"return (vtexprojcoord.xyz + float3(1.0, 1.0, 1.0)) * float3(0.5, 0.5, 0.5);\n"
+//#elif defined(CUBESHADOW)
+//	vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w;
+//	#define dosamp(x,y) shadowCube(s_t4, shadowcoord + vec2(x,y)*texscale.xy).r
+"#else\n"
+//figure out which axis to use
+//texture is arranged thusly:
+//forward left  up
+//back    right down
+"float3 dir = abs(vtexprojcoord.xyz);\n"
+//assume z is the major axis (ie: forward from the light)
+"float3 t = vtexprojcoord.xyz;\n"
+"float ma = dir.z;\n"
+"float3 axis = float3(0.5/3.0, 0.5/2.0, 0.5);\n"
+"if (dir.x > ma)\n"
+"{\n"
+"ma = dir.x;\n"
+"t = vtexprojcoord.zyx;\n"
+"axis.x = 0.5;\n"
+"}\n"
+"if (dir.y > ma)\n"
+"{\n"
+"ma = dir.y;\n"
+"t = vtexprojcoord.xzy;\n"
+"axis.x = 2.5/3.0;\n"
+"}\n"
+//if the axis is negative, flip it.
+"if (t.z > 0.0)\n"
+"{\n"
+"axis.y = 1.5/2.0;\n"
+"t.z = -t.z;\n"
+"}\n"
+
+//we also need to pass the result through the light's projection matrix too
+//the 'matrix' we need only contains 5 actual values. and one of them is a -1. So we might as well just use a vec4.
+//note: the projection matrix also includes scalers to pinch the image inwards to avoid sampling over borders, as well as to cope with non-square source image
+//the resulting z is prescaled to result in a value between -0.5 and 0.5.
+//also make sure we're in the right quadrant type thing
+"return axis + ((l_shadowmapproj.xyz*t.xyz + float3(0.0, 0.0, l_shadowmapproj.w)) / -t.z);\n"
+"#endif\n"
+"}\n"
+
+"float ShadowmapFilter(float3 vtexprojcoord)\n"
+"{\n"
+"float3 shadowcoord = ShadowmapCoord(vtexprojcoord);\n"
+
+//	#define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r
+
+//	#define dosamp(x,y) (tx_smap.Sample(ss_smap, shadowcoord.xy + (float2(x,y)*l_shadowmapscale.xy)).r < shadowcoord.z)
+"#define dosamp(x,y) (tx_smap.SampleCmpLevelZero(ss_smap, shadowcoord.xy+(float2(x,y)*l_shadowmapscale.xy), shadowcoord.z))\n"
+
+
+"float s = 0.0;\n"
+"#if r_glsl_pcf >= 1 && r_glsl_pcf < 5\n"
+"s += dosamp(0.0, 0.0);\n"
+"return s;\n"
+"#elif r_glsl_pcf >= 5 && r_glsl_pcf < 9\n"
+"s += dosamp(-1.0, 0.0);\n"
+"s += dosamp(0.0, -1.0);\n"
+"s += dosamp(0.0, 0.0);\n"
+"s += dosamp(0.0, 1.0);\n"
+"s += dosamp(1.0, 0.0);\n"
+"return s/5.0;\n"
+"#else\n"
+"s += dosamp(-1.0, -1.0);\n"
+"s += dosamp(-1.0, 0.0);\n"
+"s += dosamp(-1.0, 1.0);\n"
+"s += dosamp(0.0, -1.0);\n"
+"s += dosamp(0.0, 0.0);\n"
+"s += dosamp(0.0, 1.0);\n"
+"s += dosamp(1.0, -1.0);\n"
+"s += dosamp(1.0, 0.0);\n"
+"s += dosamp(1.0, 1.0);\n"
+"return s/9.0;\n"
+"#endif\n"
+"}\n"
+"#endif\n"
+
+
+"float4 main (v2f inp) : SV_TARGET\n"
+"{\n"
+"float2 tc = inp.tc; //TODO: offsetmapping.\n"
+
+"float4 base = tx_base.Sample(ss_base, tc);\n"
+"#ifdef BUMP\n"
+"float4 bump = tx_bump.Sample(ss_bump, tc);\n"
+"bump.rgb = normalize(bump.rgb - 0.5);\n"
+"#else\n"
+"float4 bump = float4(0, 0, 1, 0);\n"
+"#endif\n"
+"float4 spec = tx_spec.Sample(ss_spec, tc);\n"
+"#ifdef CUBE\n"
+"float4 cubemap = tx_cube.Sample(ss_cube, inp.vtexprojcoord);\n"
+"#endif\n"
+"#ifdef LOWER\n"
+"float4 lower = tx_lower.Sample(ss_lower, tc);\n"
+"base += lower;\n"
+"#endif\n"
+"#ifdef UPPER\n"
+"float4 upper = tx_upper.Sample(ss_upper, tc);\n"
+"base += upper;\n"
+"#endif\n"
+
+"float lightscale = max(1.0 - (dot(inp.lightvector,inp.lightvector)/(l_lightradius*l_lightradius)), 0.0);\n"
+"float3 nl = normalize(inp.lightvector);\n"
+"float bumpscale = max(dot(bump.xyz, nl), 0.0);\n"
+"float3 halfdir = normalize(normalize(inp.eyevector) + nl);\n"
+"float specscale = pow(max(dot(halfdir, bump.rgb), 0.0), 32.0 * spec.a);\n"
+
+"float4 result;\n"
+"result.a    = base.a;\n"
+"result.rgb  = base.rgb * (l_lightcolourscale.x + l_lightcolourscale.y * bumpscale); //amient light + diffuse\n"
+"result.rgb += spec.rgb * l_lightcolourscale.z * specscale; //specular\n"
+
+"result.rgb *= lightscale * l_colour; //fade light by distance and light colour.\n"
+
+"#ifdef CUBE\n"
+"result.rgb *= cubemap.rgb; //fade by cubemap\n"
+"#endif\n"
+
+"#ifdef PCF\n"
+"result.rgb *= ShadowmapFilter(inp.vtexprojcoord);\n"
+"#endif\n"
+
+//TODO: fog
+"return result;\n"
+"}\n"
+"#endif\n"
+},
+#endif
 #ifdef GLQUAKE
 {QR_OPENGL, 110, "underwaterwarp",
 "!!cvarf r_waterwarp\n"
@@ -2109,9 +2375,12 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
 "uniform sampler2D s_t4;\n"
 
 "#ifdef PCF\n"
-"sampler2DShadow s_t5;\n"
+"uniform sampler2DShadow s_t5;\n"
 "#include \"sys/pcf.h\"\n"
 "#endif\n"
+"#ifdef CUBE\n"
+"uniform samplerCube s_t6;\n"
+"#endif\n"
 
 //light levels
 "uniform vec4 e_lmscale;\n"
@@ -2164,6 +2433,10 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
 
 "r.rgb *= colorscale * l_lightcolour;\n"
 
+"#ifdef CUBE\n"
+"r.rgb *= textureCube(s_t6, vtexprojcoord.xyz).rgb;\n"
+"#endif\n"
+
 "gl_FragColor = fog4additive(r);\n"
 "#else\n"
 //lightmap is greyscale in m.a. probably we should just scale the texture mix, but precision errors when editing make me paranoid.
@@ -2188,6 +2461,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
 "float2 tc: TEXCOORD0;\n"
 "float2 lmtc: TEXCOORD1;\n"
 "float4 vcol: COLOR0;\n"
+"float3 vtexprojcoord: TEXCOORD2;\n"
+"float3 vtexprojcoord: TEXCOORD2;\n"
 "};\n"
 
 "#include <ftedefs.h>\n"
@@ -2207,22 +2482,50 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
 "#endif\n"
 
 "#ifdef FRAGMENT_SHADER\n"
-"Texture2D shaderTexture[5];\n"
-"SamplerState SampleType;\n"
+"Texture2D shaderTexture[7];\n"
+"SamplerState SampleType[7];\n"
 
 "float4 main (v2f inp) : SV_TARGET\n"
 "{\n"
-"return float4(1,1,1,1);\n"
+"float4 result;\n"
 
-//		float4 m = shaderTexture[4].Sample(SampleType, inp.tc) ;
+"float4 base = shaderTexture[0].Sample(SampleType[0], inp.tc);\n"
+"#ifdef BUMP\n"
+"float4 bump = shaderTexture[1].Sample(SampleType[1], inp.tc);\n"
+"#else\n"
+"float4 bump = float4(0, 0, 1, 0);\n"
+"#endif\n"
+"float4 spec = shaderTexture[2].Sample(SampleType[2], inp.tc);\n"
+"#ifdef CUBE\n"
+"float4 cubemap = shaderTexture[3].Sample(SampleType[3], inp.vtexprojcoord);\n"
+"#endif\n"
+//shadowmap 2d
+"#ifdef LOWER\n"
+"float4 lower = shaderTexture[5].Sample(SampleType[5], inp.tc);\n"
+"base += lower;\n"
+"#endif\n"
+"#ifdef UPPER\n"
+"float4 upper = shaderTexture[6].Sample(SampleType[6], inp.tc);\n"
+"base += upper;\n"
+"#endif\n"
 
-//		return inp.vcol*float4(m.aaa,1.0)*(
-//			  shaderTexture[0].Sample(SampleType, inp.tc)*m.r
-//			+ shaderTexture[1].Sample(SampleType, inp.tc)*m.g
-//			+ shaderTexture[2].Sample(SampleType, inp.tc)*m.b
-//			+ shaderTexture[3].Sample(SampleType, inp.tc)*1.0 - (m.r + m.g + m.b))
-//			;
+"float lightscale = max(1.0 - (dot(inp.lightvector,inp.lightvector)/(l_lightradius*l_lightradius)), 0.0);\n"
+"float3 nl = normalize(inp.lightvector);\n"
+"float bumpscale = max(dot(bump.xyz, nl), 0.0);\n"
+"float3 halfdir = normalize(normalize(eyevector) + nl);\n"
+"float specscale = pow(max(dot(halfdir, bumps), 0.0), 32.0 * spec.a);\n"
 
+"result.a = base.a;\n"
+"result.rgb = base.rgb * (l_lightcolourscale.x + l_lightcolourscale.y * bumpscale); //amient light + diffuse\n"
+"result.rgb += spec.rgb * l_lightcolourscale.z * specscale; //specular\n"
+
+"result.rgb *= lightscale; //fade light by distance\n"
+
+"#ifdef CUBE\n"
+"result.rgb *= cubemap.rgb; //fade by cubemap\n"
+"#endif\n"
+
+"return result;\n"
 "}\n"
 "#endif\n"
 },
diff --git a/engine/shaders/glsl/rtlight.glsl b/engine/shaders/glsl/rtlight.glsl
index a3cd96cdf..165c76914 100644
--- a/engine/shaders/glsl/rtlight.glsl
+++ b/engine/shaders/glsl/rtlight.glsl
@@ -274,8 +274,7 @@ void main ()
 	/*filter the light by the shadowmap. logically a boolean, but we allow fractions for softer shadows*/
 //diff.rgb = (vtexprojcoord.xyz/vtexprojcoord.w) * 0.5 + 0.5;
 	colorscale *= ShadowmapFilter();
-//	gl_FragColor.rgb = vec3(ShadowmapFilter());
-
+//	diff = ShadowmapCoord();
 #endif
 
 #if defined(PROJECTION)
diff --git a/engine/shaders/glsl/terrain.glsl b/engine/shaders/glsl/terrain.glsl
index 407f5adaa..296524a76 100644
--- a/engine/shaders/glsl/terrain.glsl
+++ b/engine/shaders/glsl/terrain.glsl
@@ -82,9 +82,12 @@ uniform sampler2D s_t3;
 uniform sampler2D s_t4;
 
 #ifdef PCF
-	sampler2DShadow s_t5;
+	uniform sampler2DShadow s_t5;
 	#include "sys/pcf.h"
 #endif
+#ifdef CUBE
+	uniform samplerCube s_t6;
+#endif
 
 //light levels
 uniform vec4 e_lmscale;
@@ -137,6 +140,10 @@ void main (void)
 
 	r.rgb *= colorscale * l_lightcolour;
 
+	#ifdef CUBE
+		r.rgb *= textureCube(s_t6, vtexprojcoord.xyz).rgb;
+	#endif
+
 	gl_FragColor = fog4additive(r);
 #else
 	//lightmap is greyscale in m.a. probably we should just scale the texture mix, but precision errors when editing make me paranoid.
diff --git a/engine/shaders/hlsl11/terrain.hlsl b/engine/shaders/hlsl11/terrain.hlsl
index 487dead4d..dfe0b0f40 100644
--- a/engine/shaders/hlsl11/terrain.hlsl
+++ b/engine/shaders/hlsl11/terrain.hlsl
@@ -10,6 +10,8 @@ struct v2f
 	float2 tc: TEXCOORD0;
 	float2 lmtc: TEXCOORD1;
 	float4 vcol: COLOR0;
+	float3 vtexprojcoord: TEXCOORD2;
+	float3 vtexprojcoord: TEXCOORD2;
 };
 
 #include <ftedefs.h>
@@ -29,21 +31,49 @@ struct v2f
 #endif
 
 #ifdef FRAGMENT_SHADER
-	Texture2D shaderTexture[5];
-	SamplerState SampleType;
+	Texture2D shaderTexture[7];
+	SamplerState SampleType[7];
 
 	float4 main (v2f inp) : SV_TARGET
 	{
-return float4(1,1,1,1);
+		float4 result;
 
-//		float4 m = shaderTexture[4].Sample(SampleType, inp.tc) ;
+		float4 base = shaderTexture[0].Sample(SampleType[0], inp.tc);
+#ifdef BUMP
+		float4 bump = shaderTexture[1].Sample(SampleType[1], inp.tc);
+#else
+		float4 bump = float4(0, 0, 1, 0);
+#endif
+		float4 spec = shaderTexture[2].Sample(SampleType[2], inp.tc);
+#ifdef CUBE
+		float4 cubemap = shaderTexture[3].Sample(SampleType[3], inp.vtexprojcoord);
+#endif
+		//shadowmap 2d
+#ifdef LOWER
+		float4 lower = shaderTexture[5].Sample(SampleType[5], inp.tc);
+		base += lower;
+#endif
+#ifdef UPPER
+		float4 upper = shaderTexture[6].Sample(SampleType[6], inp.tc);
+		base += upper;
+#endif
 
-//		return inp.vcol*float4(m.aaa,1.0)*(
-//			  shaderTexture[0].Sample(SampleType, inp.tc)*m.r
-//			+ shaderTexture[1].Sample(SampleType, inp.tc)*m.g
-//			+ shaderTexture[2].Sample(SampleType, inp.tc)*m.b
-//			+ shaderTexture[3].Sample(SampleType, inp.tc)*1.0 - (m.r + m.g + m.b))
-//			;
+		float lightscale = max(1.0 - (dot(inp.lightvector,inp.lightvector)/(l_lightradius*l_lightradius)), 0.0);
+		float3 nl = normalize(inp.lightvector);
+		float bumpscale = max(dot(bump.xyz, nl), 0.0);
+		float3 halfdir = normalize(normalize(eyevector) + nl);
+		float specscale = pow(max(dot(halfdir, bumps), 0.0), 32.0 * spec.a);
 
+		result.a = base.a;
+		result.rgb = base.rgb * (l_lightcolourscale.x + l_lightcolourscale.y * bumpscale);	//amient light + diffuse
+		result.rgb += spec.rgb * l_lightcolourscale.z * specscale;	//specular
+
+		result.rgb *= lightscale;	//fade light by distance
+
+#ifdef CUBE
+		result.rgb *= cubemap.rgb;	//fade by cubemap
+#endif
+
+		return result;
 	}
 #endif
\ No newline at end of file