float4x4 World	: WORLD;
float4x4 View	: VIEW;
float4x4 Proj	: PROJECTION;


float4x4		ViewProj;
float4x4		WVP;
float4x4		InvWVP;
float4x4		InvWorld;

float			fTime;
float4			eyeVec;
float4			lightVec;
texture			BaseTexture;
texture			SphereMapTexture;


// light direction (view space)
float4 lightDir = {0.0f, 0.0f, 1.0f, 1.0f};


// light intensity
float4 I_a = { 0.1f, 0.1f, 0.1f, 1.0f };    // ambient
float4 I_d = { 0.75f, 0.8f, 0.95f, 1.0f };    // diffuse
float4 I_s = { 1.0f, 1.0f, 1.0f, 1.0f };    // specular


// material reflectivity
float4 k_a : MATERIALAMBIENT = { 0.1f, 0.1f, 0.1f, 1.0f };	// ambient
float4 k_d : MATERIALDIFFUSE = { 1.0f, 1.0f, 1.0f, 1.0f };	// diffuse
float4 k_s : MATERIALSPECULAR= { 1.0f, 1.0f, 1.0f, 1.0f };	// specular
float  n   : MATERIALPOWER = 32.0f;				// power




sampler SamplerBase = sampler_state
{
    Texture	= (BaseTexture);
    MipFilter	= LINEAR;
    MinFilter	= LINEAR;
    MagFilter	= LINEAR;
    AddressU	= WRAP;
    AddressV	= WRAP;
};

sampler SamplerSphereMap = sampler_state
{
    Texture	= (SphereMapTexture);
    MipFilter	= LINEAR;
    MinFilter	= LINEAR;
    MagFilter	= LINEAR;
    AddressU	= WRAP;
    AddressV	= WRAP;
};

// Vertex Definitions
struct APP_OUTPUT
{
	float3 position	: POSITION;
	float3 normal	: NORMAL;
	float2 texture0 : TEXCOORD0;
};

struct VS_OUTPUT
{
	float4 hposition : POSITION;
	float4 diffuse	 : COLOR0;
	float4 specular	 : COLOR1;
	float2 texture0  : TEXCOORD0;
	float2 texture1  : TEXCOORD1;
};

struct PS_OUTPUT
{
	float4 color : COLOR;
};

VS_OUTPUT PhongIllumVS( APP_OUTPUT IN )
{
	VS_OUTPUT OUT = (VS_OUTPUT) 0;


	// view space matrix
	float4x4 wv = mul( World, View );

	// temp position holder
	float4 tempPos = float4( IN.position, 1 );

	float3 P = mul(float4(IN.position, 1), (float4x3)wv);

	float3 N = normalize( mul(IN.normal, (float3x3)wv) );

	float3 E = mul( eyeVec, (float4x3)wv );

	float3 V = -normalize( P );

	float3 L = -lightDir;//normalize( lightVec.xyz );

	float diff = saturate(dot(N, L));

	float3 R = normalize(2 * dot(N, L) * N - L);
	float3 H = normalize( L + V );


	OUT.hposition = mul( float4(IN.position, 1), WVP );


	OUT.diffuse  = I_a * k_a + I_d * k_d * max(0, dot(N, L)); 	// diffuse + ambient
	OUT.specular = I_s * k_s * pow(max(0, dot(R, V)), n);		// specular
 

	OUT.texture0 = IN.texture0 * 2;
	OUT.texture1.x = ((R.x * 0.5f) * 0.5f);
	OUT.texture1.y = ((R.y * 0.5f) * 0.5f);


	return OUT;
}

PS_OUTPUT PhongIllumPS( VS_OUTPUT IN )
{
	PS_OUTPUT OUT = (PS_OUTPUT) 0;

	// (texture0 * texture1) * diffuse + specular
	float4 diff = tex2D( SamplerBase, IN.texture0 );
	OUT.color = (diff * IN.diffuse) + IN.specular;

	return OUT;
}



//-----------------------------------------------------------------------------
// Environment mapping VS
VS_OUTPUT EnvMapVS( APP_OUTPUT IN )
{
    VS_OUTPUT OUT = (VS_OUTPUT) 0;

	// temp holders
	float4 tempPos = float4(IN.position, 1);

	float3 P = mul( tempPos, (float4x3)World );
	float3 N = mul( IN.normal, (float3x3)World );

	float3 E = eyeVec.xyz;

	float3 L = normalize( lightVec.xyz );
	float diff = saturate(dot( N, L ));

	float3 V = normalize( E - P );

	float3 R = reflect( V, N );

	float4 specular = pow((dot(R, V)), n);

	// Transform vertex 
	OUT.hposition = mul( tempPos, WVP );

	OUT.diffuse  = k_a + diff;
	OUT.specular = specular;//(k_s * specular );

	OUT.texture0.x = (R.x + 1.0f) * 0.5f;
	OUT.texture0.y = (R.y + 1.0f) * 0.5f;

	OUT.texture1 = IN.texture0;

	return OUT;
}

//-----------------------------------------------------------------------------
// EnvMap Pixel Shader
PS_OUTPUT EnvMapPS( VS_OUTPUT IN )
{
	PS_OUTPUT OUT = (PS_OUTPUT) 0;

	float4 refl = tex2D( SamplerSphereMap, IN.texture0 );

	OUT.color = (IN.diffuse * refl) + IN.specular;


	return OUT;
}



technique TechniquePhongModel
{
    pass Pass0
    {
		ZEnable			= TRUE;
		ZWriteEnable	= TRUE;
		Lighting		= TRUE;
		FogEnable		= FALSE;
		CullMode		= NONE;

		// enable alpha blending
		AlphaBlendEnable	= TRUE;
		SrcBlend		= SRCALPHA;
		DestBlend		= INVSRCALPHA;

		// set up texture stage states to use the diffuse color
		ColorOp[0]		= MODULATE;//SelectArg1;
		ColorArg1[0]		= TEXTURE;
		ColorArg2[0]		= DIFFUSE;
		AlphaOp[0]		= DISABLE;//MODULATE;//SelectArg1;
//		AlphaArg1[0]		= TEXTURE;
//		AlphaArg2[0]		= DIFFUSE;


		Sampler[0]		= (SamplerBase);	// Needed by pixel shader
		Sampler[1]		= (SamplerSphereMap);	// Needed by pixel shader


		VertexShader = compile vs_1_1 PhongIllumVS();
		PixelShader  = compile ps_1_3 PhongIllumPS();
    }
}


technique TechniqueEnvMap
{
    pass Pass0
    {
		ZEnable			= TRUE;
		ZWriteEnable		= TRUE;
		Lighting		= FALSE;
		FogEnable		= FALSE;
		CullMode		= NONE;

		// enable alpha blending
		AlphaBlendEnable	= FALSE;
		SrcBlend		= SRCALPHA;
		DestBlend		= INVSRCALPHA;

		// set up texture stage states to use the diffuse color
		ColorOp[0]		= SelectArg1;
		ColorArg1[0]		= TEXTURE;
		ColorArg2[0]		= DIFFUSE;
		AlphaOp[0]		= DISABLE;//SelectArg1;


		Sampler[0]		= (SamplerSphereMap);	// Needed by pixel shader
		Sampler[1]		= (SamplerBase);	// Needed by pixel shader


		VertexShader		= compile vs_1_1 EnvMapVS();
		PixelShader		= compile ps_1_3 EnvMapPS();
    }
}