// Description: Test shareds for learning purposes
// Author: Isaac Lascasas
float4x4	matWorldViewProj;
float4x4	matWorld;
float4x4	matInvTransposeWorld;
float4		vecLightDir;
texture		txScene;
float4		vecDiffuseColor;
// specular only
float4		vecEye;
float4		vecSpecularColor;
// NPR only
float4x4	matView;
float4x4	matViewProj;

struct VS_OUTPUT
	{
	float4 Pos: POSITION;
	};
	
struct VS_OUTPUT2
	{
    float4 Pos		: POSITION;
    float3 Light	: TEXCOORD0;
    float3 Norm		: TEXCOORD1;
	};

////////////////////////
// GLOBAL ILUMINATION //
////////////////////////

VS_OUTPUT VS_GlobalIlumination( float4 Pos: POSITION )
	{
	VS_OUTPUT Out = (VS_OUTPUT) 0;
	Out.Pos = mul(Pos, matWorldViewProj); // transform Position
	return Out;
	}

float4 PS_GlobalIlumination() : COLOR
	{
	return float4(0.5, 0.075, 0.075, 1.0);
	}

//////////////////////////
// AMBIENT WITH TEXTURE //
//////////////////////////

sampler  g_samScene =
sampler_state
{
    Texture = <txScene>;
    MinFilter = Linear;
    MagFilter = Linear;
    MipFilter = Point;
};

struct VS_OUTPUT4
	{
    float4 Pos		: POSITION;
	float2 Tex		: TEXCOORD0;
	};

VS_OUTPUT4 VS_AmbientWithTexture(float4 Pos : POSITION, float2 Tex : TEXCOORD0)
	{
	VS_OUTPUT4 Out = (VS_OUTPUT4)0;
    Out.Tex = Tex;
	Out.Pos = mul(Pos, matWorldViewProj);           // transform Position
	return Out;
	}

float4 PS_AmbientWithTexture(float2 Tex : TEXCOORD0) : COLOR
	{
	float4 ambient = {1.0, 1.0, 1.0, 0.0};
	return ambient * tex2D( g_samScene, Tex );
	}

//////////////////////////////
// SIMPLE DIFFUSE LIGHTNING //
//////////////////////////////

VS_OUTPUT2 VS_DiffuseLightning(float4 Pos : POSITION, float3 Normal : NORMAL)
	{
	VS_OUTPUT2 Out = (VS_OUTPUT2)0;
	Out.Pos = mul(Pos, matWorldViewProj);           // transform Position
	Out.Light = vecLightDir;                        // output light vector
	Out.Norm = normalize(mul(matWorldViewProj, Normal));    // transform Normal and normalize it
	return Out;
	}

float4 PS_DiffuseLightning(float3 Light: TEXCOORD0, float3 Norm : TEXCOORD1) : COLOR
	{
	float4 diffuse = { 1.0f, 0.0f, 0.0f, 1.0f};
	float4 ambient = {0.1, 0.0, 0.0, 1.0};
	return ambient + diffuse * saturate(dot(Light, Norm));
	}

//////////////////////////
// DIFFUSE WITH TEXTURE //
//////////////////////////

struct VS_OUTPUT3
	{
    float4 Pos		: POSITION;
    float3 Light	: TEXCOORD2;
    float3 Norm		: TEXCOORD1;
	float2 Tex		: TEXCOORD0;
	};

VS_OUTPUT3 VS_DiffuseWithTexture(float4 Pos : POSITION, float3 Normal : NORMAL,float2 Tex : TEXCOORD0)
	{
	VS_OUTPUT3 Out = (VS_OUTPUT3)0;
    Out.Tex = Tex;	
	Out.Pos = mul(Pos, matWorldViewProj);           // transform Position
	Out.Light = -vecLightDir;                        // output light vector
	Out.Norm = normalize(mul(Normal, matWorldViewProj));    // transform Normal and normalize it
	return Out;
	}

float4 PS_DiffuseWithTexture(float3 Light: TEXCOORD0, float3 Norm : TEXCOORD1, float2 Tex : TEXCOORD0) : COLOR
	{
	Tex.y = -Tex.y;
	float4 diffuse = { 1.0f, 1.0f, 1.0f, 1.0f};
	float4 ambient = {0.2, 0.2, 0.2, 0.0};
	return (ambient + saturate(dot(Light, Norm))) * tex2D( g_samScene, Tex );
	}

//////////////
// SPECULAR //
//////////////

struct VS_OUTPUT_SPECULAR
	{
	float4 Pos:		POSITION;
	float3 Light:	TEXCOORD0;
	float3 Norm:	TEXCOORD1;
	float3 View:	TEXCOORD2;
	float2 Tex:		TEXCOORD3;
	};
	
VS_OUTPUT_SPECULAR VS_Specular(float4 Pos:POSITION, float3 Normal:NORMAL,float2 Tex : TEXCOORD0)
	{
	VS_OUTPUT_SPECULAR Out = (VS_OUTPUT_SPECULAR)0;
	
	// transform position
	Out.Pos = mul(Pos, matWorldViewProj);
	
	// transform normal
	Out.Norm = mul(Normal, matWorld);
	
	float4 PosWorld = mul(Pos, matWorld);
	
	// fill output
	Out.Light = vecLightDir;
	Out.View = vecEye - PosWorld;
	Out.Tex = Tex;
	return Out;
	}
	
float4 PS_Specular(float3 Light:TEXCOORD0, float3 Norm:TEXCOORD1, float3 View:TEXCOORD2,float2 Tex : TEXCOORD3):COLOR
	{
	float4 Ambient = {0.1f, 0.1f, 0.1f, 0.1f};
	
	float3 Normal = normalize(Norm);
	float3 LightDir = normalize(Light);
	float3 ViewDir = normalize(View);
	
	// diffuse
	float Diffuse = saturate(dot(Normal, LightDir));
	float Diffuse2 = saturate(dot(Normal, -LightDir));	
	
	// R = 2 * (NdotL) * N - L
	float3 Reflection = normalize(2 * Diffuse * Normal - LightDir);
	
	// RdotV^n
	float Specular = pow(saturate(dot(Reflection, ViewDir)), 1.0);
	
	// I = A + DiffuseColor * DiffuseIntensity * NdotL + SpecularColor * SpecularIntensity * (RdotV)^n
	float4 r = Ambient + tex2D( g_samScene, Tex ) * (Diffuse+Diffuse2) + float4(1.0, 1.0, 1.0, 1.0) * Specular;
	
	/*int i[4];
	i[0] = r.r*3.0;
	i[1] = r.g*3.0;
	i[2] = r.b*3.0;
	r.r = (float)i[0]/3;
	r.g = (float)i[1]/3;
	r.b = (float)i[2]/3;*/
	
	return r;
	}

////////////////
// TECHNIQUES //
////////////////

technique Global
	{
    pass P0
		{          
        VertexShader = compile vs_1_1 VS_GlobalIlumination();
        PixelShader = compile ps_1_1 PS_GlobalIlumination();
		}
	}

technique AmbientWithTexture
	{
    pass P0
		{          
        VertexShader = compile vs_1_1 VS_GlobalIlumination();
        PixelShader = compile ps_1_1 PS_GlobalIlumination();
		}
	}

technique Diffuse
	{
    pass P0
		{          
        VertexShader = compile vs_1_1 VS_DiffuseLightning();
        PixelShader = compile ps_1_4 PS_DiffuseLightning();
		}	
	}
	
technique DiffuseWithTexture
	{
    pass P0
		{          
        VertexShader = compile vs_1_1 VS_DiffuseWithTexture();
        PixelShader = compile ps_1_4 PS_DiffuseWithTexture();
		}	
	}	
	
technique Specular
	{
    pass P0
		{          
        VertexShader = compile vs_2_0 VS_Specular();
        PixelShader = compile ps_2_0 PS_Specular();
		}	
	}