_DrawLight_OMNI.vsh
{
	include generic_vertex.vsh
}

_DrawLight_OMNI.fsh
{
	#extension GL_ARB_texture_rectangle: enable
	uniform sampler2DRect	u_NormalBuffer;
	uniform sampler2DRect	u_SpecularBuffer;
	uniform sampler2DRect	u_DepthBuffer;
#if defined(Stages1)
	uniform sampler2DRect	u_AttenuationMap0;
	uniform vec2		u_AttenuationSizes;
	uniform vec4		u_AttenuationColor;
#endif
#if defined(Stages2)
	uniform sampler2DRect	u_AttenuationMap0;
	uniform sampler2DRect	u_AttenuationMap1;
	uniform ivec2		u_Blend;
	uniform vec2		u_AttenuationSizes[2];
	uniform vec4		u_AttenuationColor[2];
#endif
#if defined(Stages3)
	uniform sampler2DRect	u_AttenuationMap0;
	uniform sampler2DRect	u_AttenuationMap1;
	uniform sampler2DRect	u_AttenuationMap2;
	uniform ivec2		u_Blend[2];
	uniform vec2		u_AttenuationSizes[3];
	uniform vec4		u_AttenuationColor[3];
#endif
#if defined(Stages4)
	uniform sampler2DRect	u_AttenuationMap0;
	uniform sampler2DRect	u_AttenuationMap1;
	uniform sampler2DRect	u_AttenuationMap2;
	uniform sampler2DRect	u_AttenuationMap3;
	uniform ivec2		u_Blend[3];
	uniform vec2		u_AttenuationSizes[4];
	uniform vec4		u_AttenuationColor[4];
#endif
#if defined(Stages5)
	uniform sampler2DRect	u_AttenuationMap0;
	uniform sampler2DRect	u_AttenuationMap1;
	uniform sampler2DRect	u_AttenuationMap2;
	uniform sampler2DRect	u_AttenuationMap3;
	uniform sampler2DRect	u_AttenuationMap4;
	uniform ivec2		u_Blend[4];
	uniform vec2		u_AttenuationSizes[5];
	uniform vec4		u_AttenuationColor[5];
#endif
	uniform vec3		u_LightOrigin;
	uniform vec3		u_ViewOrigin;
	uniform vec3		u_LightColor;
	uniform mat4		u_LightAttenuationMatrix;
	uniform mat4		u_UnprojectMatrix;
	uniform float		u_sphereRadius;
	uniform float		u_noSpecular;
	include UnPackNormal.inc
#ifndef Stages1
	include Blend.inc
#endif
	out	vec3	fragData[2];
	void main(void)
	{
		if (texture2DRect(u_SpecularBuffer, gl_FragCoord.xy).a == 1.0)
		{
			discard;	// no portal surfaces draw
			return;
		}

		// reconstruct vertex position in world space
		float depth = texture2DRect(u_DepthBuffer, gl_FragCoord.xy).r;
		vec4 P = u_UnprojectMatrix * vec4(gl_FragCoord.xy, depth, 1.0);
		P.xyz /= P.w;

		// fast culling
		float dist = distance(u_LightOrigin, P.xyz);
		if (dist > u_sphereRadius)
		{
			discard;
			return;
		}

		// compute color attenuation
		vec3 texAtten = (u_LightAttenuationMatrix * vec4(P.xyz, 1.0)).xyz;
		texAtten.z = abs(texAtten.z - 0.5);
		if (texAtten.z >= 0.5)
		{
			discard;
			return;
		}

		vec3 col = 2.0 * (0.5 - texAtten.z) * u_LightColor;

#if defined(Stages1)
		col *= (texture2DRect(u_AttenuationMap0, texAtten.xy * u_AttenuationSizes) * u_AttenuationColor).rgb;
#endif
#if defined(Stages2)
		vec4 d = texture2DRect(u_AttenuationMap0, texAtten.xy * u_AttenuationSizes[0]) * u_AttenuationColor[0];
		vec4 s = texture2DRect(u_AttenuationMap1, texAtten.xy * u_AttenuationSizes[1]) * u_AttenuationColor[1];
		col *= (Blend(s,d,u_Blend)).rgb;
#endif
#if defined(Stages3)
		vec4 d = texture2DRect(u_AttenuationMap0, texAtten.xy * u_AttenuationSizes[0]) * u_AttenuationColor[0];
		vec4 s = texture2DRect(u_AttenuationMap1, texAtten.xy * u_AttenuationSizes[1]) * u_AttenuationColor[1];
		d = Blend(s,d,u_Blend[0]);
		s = texture2DRect(u_AttenuationMap2, texAtten.xy * u_AttenuationSizes[2]) * u_AttenuationColor[2];
		col *= (Blend(s,d,u_Blend[1])).rgb;
#endif
#if defined(Stages4)
		vec4 d = texture2DRect(u_AttenuationMap0, texAtten.xy * u_AttenuationSizes[0]) * u_AttenuationColor[0];
		vec4 s = texture2DRect(u_AttenuationMap1, texAtten.xy * u_AttenuationSizes[1]) * u_AttenuationColor[1];
		d = Blend(s,d,u_Blend[0]);
		s = texture2DRect(u_AttenuationMap2, texAtten.xy * u_AttenuationSizes[2]) * u_AttenuationColor[2];
		d = Blend(s,d,u_Blend[1]);
		s = texture2DRect(u_AttenuationMap3, texAtten.xy * u_AttenuationSizes[3]) * u_AttenuationColor[3];
		col *= (Blend(s,d,u_Blend[2])).rgb;
#endif
#if defined(Stages5)
		vec4 d = texture2DRect(u_AttenuationMap0, texAtten.xy * u_AttenuationSizes[0]) * u_AttenuationColor[0];
		vec4 s = texture2DRect(u_AttenuationMap1, texAtten.xy * u_AttenuationSizes[1]) * u_AttenuationColor[1];
		d = Blend(s,d,u_Blend[0]);
		s = texture2DRect(u_AttenuationMap2, texAtten.xy * u_AttenuationSizes[2]) * u_AttenuationColor[2];
		d = Blend(s,d,u_Blend[1]);
		s = texture2DRect(u_AttenuationMap3, texAtten.xy * u_AttenuationSizes[3]) * u_AttenuationColor[3];
		d = Blend(s,d,u_Blend[2]);
		s = texture2DRect(u_AttenuationMap4, texAtten.xy * u_AttenuationSizes[4]) * u_AttenuationColor[4];
		col *= (Blend(s,d,u_Blend[3])).rgb;
#endif
		if (dot(col,col) < 0.00001526)	// instead: if (length(col) < 1.0/256.0)
		{
			discard;	// attenuated color is too dark
			return;
		}

		vec3 N = UnPackNormal(texture2DRect(u_NormalBuffer, gl_FragCoord.xy).xy);

		// compute light direction in world space
		vec3 L = (u_LightOrigin - P.xyz) / dist;

		float sh = dot(N, L);
		if (sh <= 0.0)		// back face
		{
			discard;
			return;
		}

		col *= sh;
		fragData[0] = col;

		if (u_noSpecular == 0.0)
		{
			// compute view direction in world space
			vec3 V = normalize(u_ViewOrigin - P.xyz);

			// compute half angle in world space
			vec3 H = normalize(L + V);

			fragData[1] = col * pow(dot(N, H), 32.0);
		}
	}
}


_DrawLight_PROJ.vsh
{
	include generic_vertex.vsh
}

_DrawLight_PROJ.fsh
{
	#extension GL_ARB_texture_rectangle: enable
	uniform sampler2DRect	u_NormalBuffer;
	uniform sampler2DRect	u_SpecularBuffer;
	uniform sampler2DRect	u_DepthBuffer;
#if defined(Stages1)
	uniform sampler2DRect	u_AttenuationMap0;
	uniform vec2		u_AttenuationSizes;
	uniform vec4		u_AttenuationColor;
#endif
#if defined(Stages2)
	uniform sampler2DRect	u_AttenuationMap0;
	uniform sampler2DRect	u_AttenuationMap1;
	uniform ivec2		u_Blend;
	uniform vec2		u_AttenuationSizes[2];
	uniform vec4		u_AttenuationColor[2];
#endif
#if defined(Stages3)
	uniform sampler2DRect	u_AttenuationMap0;
	uniform sampler2DRect	u_AttenuationMap1;
	uniform sampler2DRect	u_AttenuationMap2;
	uniform ivec2		u_Blend[2];
	uniform vec2		u_AttenuationSizes[3];
	uniform vec4		u_AttenuationColor[3];
#endif
#if defined(Stages4)
	uniform sampler2DRect	u_AttenuationMap0;
	uniform sampler2DRect	u_AttenuationMap1;
	uniform sampler2DRect	u_AttenuationMap2;
	uniform sampler2DRect	u_AttenuationMap3;
	uniform ivec2		u_Blend[3];
	uniform vec2		u_AttenuationSizes[4];
	uniform vec4		u_AttenuationColor[4];
#endif
#if defined(Stages5)
	uniform sampler2DRect	u_AttenuationMap0;
	uniform sampler2DRect	u_AttenuationMap1;
	uniform sampler2DRect	u_AttenuationMap2;
	uniform sampler2DRect	u_AttenuationMap3;
	uniform sampler2DRect	u_AttenuationMap4;
	uniform ivec2		u_Blend[4];
	uniform vec2		u_AttenuationSizes[5];
	uniform vec4		u_AttenuationColor[5];
#endif
	uniform vec3		u_LightOrigin;
	uniform vec3		u_ViewOrigin;
	uniform vec3		u_LightColor;
	uniform mat4		u_LightAttenuationMatrix;
	uniform mat4		u_UnprojectMatrix;
	uniform float		u_sphereRadius;
	uniform float		u_noSpecular;
	include UnPackNormal.inc
#ifndef Stages1
	include Blend.inc
#endif
	out	vec3	fragData[2];
	void main(void)
	{
		if (texture2DRect(u_SpecularBuffer, gl_FragCoord.xy).a == 1.0)
		{
			discard;	// no portal surfaces draw
			return;
		}

		// reconstruct vertex position in world space
		float depth = texture2DRect(u_DepthBuffer, gl_FragCoord.xy).r;
		vec4 P = u_UnprojectMatrix * vec4(gl_FragCoord.xy, depth, 1.0);
		P.xyz /= P.w;

		// fast culling
		float dist = distance(u_LightOrigin, P.xyz);
		if (dist > u_sphereRadius)
		{
			discard;
			return;
		}

		// compute color attenuation
		vec4 texAtten = u_LightAttenuationMatrix * vec4(P.xyz, 1.0);
		if(texAtten.w <= 0.0)
		{
			discard;	// fragment is behind the near clip plane
			return;
		}

		vec3 col = (1.0 - texAtten.z) * u_LightColor;
		texAtten.xy /= texAtten.w;

#if defined(Stages1)
		col *= (texture2DRect(u_AttenuationMap0, texAtten.xy * u_AttenuationSizes) * u_AttenuationColor).rgb;
#endif
#if defined(Stages2)
		vec4 d = texture2DRect(u_AttenuationMap0, texAtten.xy * u_AttenuationSizes[0]) * u_AttenuationColor[0];
		vec4 s = texture2DRect(u_AttenuationMap1, texAtten.xy * u_AttenuationSizes[1]) * u_AttenuationColor[1];
		col *= (Blend(s,d,u_Blend)).rgb;
#endif
#if defined(Stages3)
		vec4 d = texture2DRect(u_AttenuationMap0, texAtten.xy * u_AttenuationSizes[0]) * u_AttenuationColor[0];
		vec4 s = texture2DRect(u_AttenuationMap1, texAtten.xy * u_AttenuationSizes[1]) * u_AttenuationColor[1];
		d = Blend(s,d,u_Blend[0]);
		s = texture2DRect(u_AttenuationMap2, texAtten.xy * u_AttenuationSizes[2]) * u_AttenuationColor[2];
		col *= (Blend(s,d,u_Blend[1])).rgb;
#endif
#if defined(Stages4)
		vec4 d = texture2DRect(u_AttenuationMap0, texAtten.xy * u_AttenuationSizes[0]) * u_AttenuationColor[0];
		vec4 s = texture2DRect(u_AttenuationMap1, texAtten.xy * u_AttenuationSizes[1]) * u_AttenuationColor[1];
		d = Blend(s,d,u_Blend[0]);
		s = texture2DRect(u_AttenuationMap2, texAtten.xy * u_AttenuationSizes[2]) * u_AttenuationColor[2];
		d = Blend(s,d,u_Blend[1]);
		s = texture2DRect(u_AttenuationMap3, texAtten.xy * u_AttenuationSizes[3]) * u_AttenuationColor[3];
		col *= (Blend(s,d,u_Blend[2])).rgb;
#endif
#if defined(Stages5)
		vec4 d = texture2DRect(u_AttenuationMap0, texAtten.xy * u_AttenuationSizes[0]) * u_AttenuationColor[0];
		vec4 s = texture2DRect(u_AttenuationMap1, texAtten.xy * u_AttenuationSizes[1]) * u_AttenuationColor[1];
		d = Blend(s,d,u_Blend[0]);
		s = texture2DRect(u_AttenuationMap2, texAtten.xy * u_AttenuationSizes[2]) * u_AttenuationColor[2];
		d = Blend(s,d,u_Blend[1]);
		s = texture2DRect(u_AttenuationMap3, texAtten.xy * u_AttenuationSizes[3]) * u_AttenuationColor[3];
		d = Blend(s,d,u_Blend[2]);
		s = texture2DRect(u_AttenuationMap4, texAtten.xy * u_AttenuationSizes[4]) * u_AttenuationColor[4];
		col *= (Blend(s,d,u_Blend[3])).rgb;
#endif

		if (dot(col,col) < 0.00001526)	// instead: if (length(col) < 1.0/256.0)
		{
			discard;	// attenuated color is too dark
			return;
		}

		vec3 N = UnPackNormal(texture2DRect(u_NormalBuffer, gl_FragCoord.xy).xy);

		// compute light direction in world space
		vec3 L = (u_LightOrigin - P.xyz) / dist;

		float sh = dot(N, L);
		if (sh <= 0.0)		// back face
		{
			discard;
			return;
		}

		col *= sh;
		fragData[0] = col;

		if (u_noSpecular == 0.0)
		{
			// compute view direction in world space
			vec3 V = normalize(u_ViewOrigin - P.xyz);

			// compute half angle in world space
			vec3 H = normalize(L + V);

			fragData[1] = col * pow(dot(N, H), 32.0);
		}
	}
}


_sunLight.vsh
{
	include generic_vertex.vsh
}

_sunLight.fsh
{
	#extension GL_ARB_texture_rectangle: enable
	uniform sampler2DRect	u_NormalBuffer;
	uniform sampler2DRect	u_SpecularBuffer;
	uniform sampler2DRect	u_DepthBuffer;
	uniform vec3		u_sunDirection;
	uniform vec3		u_ViewOrigin;
	uniform vec3		u_sunColor;
	uniform mat4		u_UnprojectMatrix;
	include UnPackNormal.inc
	out	vec3	fragData[2];
	void main(void)
	{
		if (texture2DRect(u_SpecularBuffer, gl_FragCoord.xy).a == 1.0)
		{	// no portal surfaces draw
			fragData[0] = vec3(0.0);
			fragData[1] = vec3(0.0);
			return;
		}

		// reconstruct vertex position in world space
		float depth = texture2DRect(u_DepthBuffer, gl_FragCoord.xy).r;
		vec4 P = u_UnprojectMatrix * vec4(gl_FragCoord.xy, depth, 1.0);
		P.xyz /= P.w;
		vec3 N = UnPackNormal(texture2DRect(u_NormalBuffer, gl_FragCoord.xy).xy);
		float sh = dot(N, u_sunDirection);
		if (sh <= 0.0)
		{	// back face
			fragData[0] = vec3(0.0);
			fragData[1] = vec3(0.0);
			return;
		}

		// compute view direction in world space
		vec3 V = normalize(u_ViewOrigin - P.xyz);

		// compute half angle in world space
		vec3 H = normalize(u_sunDirection + V);

		vec3 col = u_sunColor * sh;
		fragData[0] = col;
		fragData[1] = col * pow(dot(N, H), 32.0);
	}
}


_FakePPL.vsh
{
	include generic_vertex.vsh
}

_FakePPL.fsh
{
	#extension GL_ARB_texture_rectangle: enable
	uniform sampler2DRect	u_NormalBuffer;
	uniform sampler2DRect	u_SpecularBuffer;
	uniform sampler2DRect	u_DepthBuffer;
	uniform sampler2DRect	u_TB_Buffer;
	uniform vec3		u_ViewOrigin;
	uniform mat4		u_UnprojectMatrix;
	uniform float		u_lightMapBrightness;
	include UnPackNormal.inc
	out	vec3	fragData[2];
	void main(void)
	{
		vec4 specular = texture2DRect(u_SpecularBuffer, gl_FragCoord.xy);
		if (specular.a == 1.0)
		{	// no portal surfaces draw
			fragData[0] = vec3(0.0);
			fragData[1] = vec3(0.0);
			return;
		}

		// reconstruct vertex position in world space
		float depth = texture2DRect(u_DepthBuffer, gl_FragCoord.xy).r;
		vec4 P = u_UnprojectMatrix * vec4(gl_FragCoord.xy, depth, 1.0);
		P.xyz /= P.w;

		// normal from NormalMap
		vec3 N = UnPackNormal(texture2DRect(u_NormalBuffer, gl_FragCoord.xy).xy);

		// reconstruct surface normal
		vec4 tblm = texture2DRect(u_TB_Buffer, gl_FragCoord.xy);
		vec3 L = vec3(tblm.xy * 2.0 - 1.0, N.z);

		// reconstruct lightmap
		vec3 lmc = vec3(specular.a, tblm.ba) * u_lightMapBrightness;

		float sh = abs(dot(N, L));
		lmc *= sh;

		// compute view direction in world space
		vec3 V = normalize(u_ViewOrigin - P.xyz);

		// compute half angle in world space
		vec3 H = normalize(L + V);

		fragData[0] = lmc;
		fragData[1] = lmc * pow(dot(N, H), 32.0);
	}
}
