sampler2D ShadowMap;

static float OffsetSize = 1500;
static float InvOffsetSize = 1.0f / 1500;

float ComputeShadow(float4 InputShadowPos, float InputDepth){
	float2 ShadowCoords = InputShadowPos.xy / InputShadowPos.z;
	
    float floor_x = floor(ShadowCoords.x * OffsetSize) / OffsetSize;
    float floor_y = floor(ShadowCoords.y * OffsetSize) / OffsetSize;

	float2 ShadowPos[4];
	ShadowPos[0] = float2(floor_x, floor_y);
	ShadowPos[1] = float2(floor_x + InvOffsetSize, floor_y);
	ShadowPos[2] = float2(floor_x, floor_y + InvOffsetSize);
	ShadowPos[3] = float2(floor_x + InvOffsetSize, floor_y + InvOffsetSize);

	float Depth[4];
	Depth[0] = tex2D(ShadowMap, ShadowPos[0]);
	Depth[1] = tex2D(ShadowMap, ShadowPos[1]);
	Depth[2] = tex2D(ShadowMap, ShadowPos[2]);
	Depth[3] = tex2D(ShadowMap, ShadowPos[3]);
	
	float ShadowPass[4];
	for (dword i = 0; i < 4; i++){
		if (InputDepth - Depth[i] > 0.002f){
			ShadowPass[i] = 0.5f;
		}
		else ShadowPass[i] = 1;
	}
	
	float fraction_x = clamp((ShadowCoords.x - floor_x) * OffsetSize, 0, 1);
	float fraction_y = clamp((ShadowCoords.y - floor_y) * OffsetSize, 0, 1);
	
    float one_minus_x = 1.0 - fraction_x;
    float one_minus_y = 1.0 - fraction_y;
	
	float b1 = one_minus_x * ShadowPass[0] + fraction_x * ShadowPass[1];
	float b2 = one_minus_x * ShadowPass[2] + fraction_x * ShadowPass[3];
	
	float ShadowColor = one_minus_y * b1 + fraction_y * b2;
	
	return ShadowColor;
}

float ComputeShadowFast(float4 InputShadowPos, float InputDepth){
	float Depth = tex2Dproj(ShadowMap, InputShadowPos);

	float ShadowColor;
	if (InputDepth - Depth > 0.001f){
		ShadowColor = 0.5f;
	}
	else ShadowColor = 1;
	
	return ShadowColor;
}