float4		gSLParamsArray[gLightCount];
float3		gLightDirObjArray[gLightCount];
float4		gDiffuseArray[gLightCount];
float4 		gSpecularArray[gLightCount];
float4		gLightAttenArray[gLightCount];
float4		gLightDistObjArray[gLightCount];
float4		gAmbient;
float		gSpecShine;

float4x4 	gWorldViewProj;
float4 		gCameraPosObj;
float4 		gLightPosObjArray[gLightCount];


struct vertexIn
{
	float4 position : POSITION;
	float3 normal	: NORMAL0;
};
 
struct vertexOut
{
	float4 position  		: POSITION;
	float3 normal			: TEXCOORD0;
	float3 viewDir   		: TEXCOORD1;
	float3 pixelToLight[gLightCount]	: TEXCOORD2;
};
 
//lighting sub program, read multiTypeLightPS first(this one is called from it)
//--------------------------------------------------------------------------------
void light(	float3 normal, 
		float3 viewDir, 
		float3 pixelToLight,
		float3 spotLightDir,
		float4 spotLightParams,
		float4 diffColor,
		float4 specColor,
		float4 lightAtten,
		float  lightDist,
		float  gSpecShine,
	inout	float4 diff,
	inout	float4 spec
	)
{
	float 	dotNL	 	= dot(pixelToLight, normal);
	float 	luminosity 	= 1 / ( lightAtten.y + lightAtten.z*lightDist + lightAtten.w*pow(lightDist,2));
	float3 	halfAng 	= normalize(viewDir + pixelToLight);
	float 	dotNH		= dot(normal, halfAng);
 
	// if spotlight params are (1, 0, 0, 1) we have a point, directional or empty light; we handle them the same.
	if(spotLightParams.x == 1 && spotLightParams.y == 0 && spotLightParams.z == 0 && spotLightParams.w == 1)
	{
		spec	+= pow(saturate(dotNH),gSpecShine) * specColor * luminosity;
		diff 	+= (saturate(dotNL)) * diffColor * luminosity;		
	}
	else
	if(dotNL > 0)
	{	
		//if it was not either of the above, we have a spotlight
		float 	dotPLd		= dot(-pixelToLight, spotLightDir);
		//diffuse
		//------------------------------
		if	( dotPLd > spotLightParams.y )
			diff += dotNL * (1-(spotLightParams.x - dotPLd)/(spotLightParams.x - spotLightParams.y)) * diffColor * luminosity;
		else
		if	( dotPLd > spotLightParams.x )
			diff += dotNL * diffColor * luminosity;	
		//------------------------------
 
		// specular
		//------------------------------
		if (dotPLd > 0) 
			spec 	+= pow(saturate(dotNH),gSpecShine) * specColor * luminosity;
		//------------------------------
	}
}
//--------------------------------------------------------------------------------
 
// main vertex program
//--------------------------------------------------------------------------------
vertexOut multiTypeLightVS(vertexIn input)
{
	vertexOut output= (vertexOut)0;
 
	output.position = mul(gWorldViewProj, input.position);
	output.normal 	= input.normal;
	output.viewDir	= gCameraPosObj - input.position;
	int j = 2;
 
	for(int i = 0; i < gLightCount; i++)
	{	
		if(gLightPosObjArray[i].w == 0)
			output.pixelToLight[i] = gLightPosObjArray[i].xyz;
		else
			output.pixelToLight[i] = gLightPosObjArray[i] - input.position;
	}
	return output;
}
//--------------------------------------------------------------------------------
 
//main pixel program
//--------------------------------------------------------------------------------
float4 multiTypeLightPS(vertexOut input) : COLOR
{
	float4 diff 	= float4(0, 0, 0, 0);
	float4 spec 	= float4(0, 0, 0, 0);
 
	input.viewDir	= normalize( input.viewDir );
	input.normal 	= normalize( input.normal );
 
	for(int i = 0; i<gLightCount ; i++)
	{
		input.pixelToLight[i]	= normalize( input.pixelToLight[i] );
 
		light(	input.normal, 
			input.viewDir, 
			input.pixelToLight[i],
			normalize(gLightDirObjArray[i]),
			gSLParamsArray[i],
			gDiffuseArray[i],
			gSpecularArray[i],
			gLightAttenArray[i],
			gLightDistObjArray[i],
			gSpecShine,
			diff,
			spec);
	}
	return gAmbient + diff + spec ;
}
//--------------------------------------------------------------------------------