// All content © 2010-2011 DigiPen (USA) Corporation, all rights reserved.

//shader to render shadows using PCF with a 2x2 kernel.

#version 150

//pcf
#define SAMPLE_COUNT_X		2 //must be >1
#define SAMPLE_COUNT_Y		2 //must be >1

// ---------------------------------------------------------------------------
//uniforms

uniform sampler2D		uDepthMap; //depth map for this light

uniform mat4			uVtL; //view to light space matrix
uniform mat4			uLsp; //bias matrix * light projection matrix

uniform float			uLightFarPlane; //light far plane - light near plane
uniform float			uTexelSize; //1.0/shadowmapsize

// ---------------------------------------------------------------------------
// const

const float TOTAL_SAMPLES		= SAMPLE_COUNT_X * SAMPLE_COUNT_Y;

// ---------------------------------------------------------------------------
// function declarations

float calcShadow( in vec3 viewSpacePos );

//internal functions
float pcf( in vec2 tc, float lsDepth );

float calcShadow( in vec3 viewSpacePos )
{	
	//get light space position
	vec4 lsPos = uVtL * vec4( viewSpacePos, 1.0 );

	//transform from screenspace to texture coordinates
	vec4 tc = uLsp * lsPos;
	tc /= tc.w;
	return pcf( tc.xy, -lsPos.z );
	
	//float shadowMapDepth = textureProj( uDepthMap, uLsp * lsPos ).r * uLightFarPlane;
	//return -lsPos.z > shadowMapDepth - 0.0001? 0.0 : 1.0;	
}

//calculates shadow attenuation at the input shadow depth map texcoord using pcf
float pcf( in vec2 tc, float lsDepth )
{	
	float depth = 0.0;
	
	vec2 filter = vec2( SAMPLE_COUNT_X, SAMPLE_COUNT_Y ) * vec2( uTexelSize, uTexelSize ); //size of filter in UV coordinates
	float dX = filter.x/(SAMPLE_COUNT_X-1);
	float dY = filter.y/(SAMPLE_COUNT_Y-1);
	
	vec2 lowerLeft = tc - 0.5 * filter; //lower left texcoord
	for ( int x = 0; x < SAMPLE_COUNT_X; ++x )
	{
		float currX = x * dX;
		
		for ( int y = 0; y < SAMPLE_COUNT_Y; ++y )
		{
			float shadowMapDepth = texture( uDepthMap, lowerLeft + vec2( currX, y * dY ) ).r;
			shadowMapDepth = shadowMapDepth * uLightFarPlane; //map depth from [0, 1] to [0, light_far_clip]

			depth += lsDepth > shadowMapDepth - 0.001? 0.0 : 1.0;	
		}
	}	
	
	return depth/TOTAL_SAMPLES;
}
