//--------------------------------------------------------------------------------------
// Constant Buffer Variables
//--------------------------------------------------------------------------------------
TextureCube lightColorTex :		register( t0 );
TextureCube lightNormal :		register( t1 );
TextureCube lightPos :			register( t2 );
TextureCube lightMaterial :		register( t3 );
TextureCube lightDepth :		register( t4 );
TextureCube lightVSM :			register( t5 );
Texture2D eyeColor :		register( t6 );
Texture2D eyeNormal :		register( t7 );
Texture2D eyePos :			register( t8 );
Texture2D eyeMaterial :		register( t9 );
Texture2D eyeDepth :		register( t10 );

SamplerState samLinear :register( s0 );
SamplerState samPoint :	register( s1 );
SamplerState samVSM :	register( s2 );

cbuffer cbChangeOnRenderTarget: register( b0 )
{
	float4 lightWorldPos;
	float4 lightColor;
	float4 eyeWorldPos;
};

//--------------------------------------------------------------------------------------
struct VS_INPUT
{
    float2 Pos : POSITION;
    float2 Tex : TEXCOORD0;
};

struct PS_INPUT
{
    float4 Pos : SV_POSITION;
    float2 Tex : TEXCOORD0;
};

float calcVSMIntensity(float2 moments, float depth) {  
    float E_x2 = moments.y;
    float Ex_2 = moments.x * moments.x;
    float variance = E_x2 - Ex_2;    
    float mD = (moments.x - depth );
    float mD_2 = mD * mD;
    float p = variance / (variance + mD_2 );
    return max( p, depth <= moments.x );
}


//--------------------------------------------------------------------------------------
// Vertex Shader
//-----------------------------------------------------------------09---------------------
PS_INPUT VS( VS_INPUT input )
{
    PS_INPUT output = (PS_INPUT)0;
    output.Pos.xy = input.Pos;
	output.Pos.zw = float2(0.0f,1.0f);
    output.Tex = input.Tex;
    
    return output;
}


//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS( PS_INPUT input) : SV_TARGET
{
	float4 pos = eyePos.Sample( samPoint, input.Tex ); pos.w=1.0f;
	float4 norm = eyeNormal.Sample( samPoint, input.Tex );
	float4 color = eyeColor.Sample( samPoint, input.Tex );
	float4 material = eyeMaterial.Sample( samPoint, input.Tex );

	float3 lv = pos.xyz - lightWorldPos.xyz;
	float smdepth = length(lv);
	float3 smtex = normalize(lv);
	float2 d = lightVSM.Sample( samVSM, smtex );
	float intensity = calcVSMIntensity(d,abs(smdepth));
	if(intensity>0.0f) {
		
		float4 lightvec = lightWorldPos - pos;
		lightvec = normalize(lightvec);
		float4 viewvec = eyeWorldPos - pos;
		viewvec = normalize(viewvec);

		float intensityDiffuse = saturate(dot(lightvec,norm)) * intensity;
		float4 h = viewvec + (lightvec-viewvec)*0.5f;
		h = normalize(h);
		//        reflected color  *   ( Diffuse                         +        Specular        )     
		float4 r = lightColor * color * (intensityDiffuse * material.y + intensityDiffuse * material.z * pow(saturate(dot(norm,h)),material.w) ) ;
		r.w = 0.0f;
		return r;
	}

	return float4(0.0f,0.0f,0.0f,1.0f);
}
