// Options:
//  optBumpMap : true uses the normal map. False uses a constant normal.
//	optSpecular : true renders light specular. False do not render it
//  optSpecMap : true uses the specular map. False ignores it.

// matrixes
float4x4 matWorld;
float4x4 matViewProj;
float4x4 matWorldInverse;

// globals
float3 viewPosition;
float3 lightPosition;
float radius;



/****************************/
/*		VERTEX SHADER		*/
/****************************/


/*
 *	structs
 */
struct VS_INPUT{
	float4 position: POSITION;
	float3 normal: NORMAL;
	float4 tangent: TANGENT;
	float2 tex: TEXCOORD0;
};

struct VS_OUTPUT{
	float4 position: POSITION;
	float2 tex: TEXCOORD0;
	float3 lightDir: TEXCOORD1;
	float3 attenuation: TEXCOORD2;
	float3 halfVector: TEXCOORD3;
	float4 color: COLOR;
};


/*
 *	vs_main
 */
VS_OUTPUT vs_main(VS_INPUT input){
	VS_OUTPUT Out = (VS_OUTPUT)0;

	//transformar vertice, calcular binormal e copiar texCoord
	float4 objectPosition = input.position;
	float4 worldPosition = mul(objectPosition, matWorld);
	Out.position = mul(worldPosition, matViewProj);
	float3 binormal = normalize(cross(input.normal, input.tangent))*input.tangent.w;
	Out.tex = input.tex;

	float3 worldLightPosition = lightPosition;
	float3 objectLightPosition = mul(float4(lightPosition,1), matWorldInverse);
	float3 objectLightDir = objectLightPosition - objectPosition;
	Out.lightDir.y = dot(objectLightDir, input.tangent.xyz);
	Out.lightDir.x = dot(objectLightDir, binormal);
	Out.lightDir.z = dot(objectLightDir, input.normal);
	Out.attenuation = (worldPosition - worldLightPosition) / radius;

	if(optSpecular){
		float3 worldViewPosition = viewPosition;
		float3 objectViewPosition = mul(float4(worldViewPosition,1), matWorldInverse);
		float3 objectViewDir = objectViewPosition - objectPosition;
		float3 tanViewDir;
		tanViewDir.y = dot(objectViewDir, input.tangent);
		tanViewDir.x = dot(objectViewDir, binormal);
		tanViewDir.z = dot(objectViewDir, input.normal);
		Out.halfVector = normalize(Out.lightDir) + normalize(tanViewDir);
	}

	Out.color = float4(binormal,1);

	return Out;
}



/****************************/
/*		VERTEX SHADER		*/
/****************************/

// globals
float4 lightColor;
float shininess;
float4 diffuseColor;

// textures
sampler diffuseMap;
sampler normalMap;
sampler specularMap;
sampler attenuationMap;


/*
 *	Estruturas
 */
struct PS_INPUT{
	float2 tex: TEXCOORD0;
	float3 lightDir: TEXCOORD1;
	float3 attenuation: TEXCOORD2;
	float3 halfAngle: TEXCOORD3;
	float4 color: COLOR;
};



/*
 *	ps_main
 */
float4 ps_main(PS_INPUT input): COLOR0{
	half3 diffuseRes = 0;
	half3 specularRes = 0;

	// normalize entru data
	input.lightDir = normalize(input.lightDir);
	input.halfAngle = normalize(input.halfAngle);

	// get attenaution
	half attenuation = tex3D(attenuationMap, input.attenuation).x;

	// calculate diffuse light
	half4 decal = tex2D(diffuseMap, input.tex);
	half light;
	half3 normal;
	if(optBumpMap){
		normal = tex2D(normalMap, input.tex)*2-1;
		normal = normalize(normal);
	}
	else
		normal = half3(0,0,1);
	light = max(0, dot(normal, input.lightDir));
	diffuseRes = decal * light;

	// calculate specular
	if(optSpecular){
		half specular;
		specular = pow(max(0, dot(normal, input.halfAngle)), shininess*2);
		half4 specMap = 1;
		if(optSpecMap)
			specMap = tex2D(specularMap, input.tex);
		specularRes = specular * specMap;
	}

	// self shadow
	float self = saturate(light*4);

	half3 surfaceColor = lightColor*diffuseColor;
	half3 fakeRadiosity = decal*surfaceColor*dot(normal, half3(0,0,1))*attenuation;
	half3 pixelIlumination = (diffuseRes + specularRes*2)*self*surfaceColor*attenuation;
	
	half3 result = fakeRadiosity*0.15 + pixelIlumination;
	
	return float4(result, 1);
	return lerp(float4(result, 1), lightColor*0.2, 0.8);
}

