#if !defined INCLUDE_SHADOWDISTORTION
#define INCLUDE_SHADOWDISTORTION

#define SHADOW_INFINITE_RENDER_DISTANCE // required until voxel & shadow maps don't need to share a texture, or shadow map gets limited to only render into its corner
#define SHADOW_DISTORTION_AMOUNT_INVERSE 0.1

float CalculateDistortionFactor(vec2 position) {
	#if defined SHADOW_INFINITE_RENDER_DISTANCE
		return 1.0 / (SHADOW_DISTORTION_AMOUNT_INVERSE + length(position));
	#else
		const float a = exp(SHADOW_DISTORTION_AMOUNT_INVERSE);
		const float b = exp(1.0) - a;
		return 1.0 / log(length(position) * b + a);
	#endif
}

#if !defined PROGRAM_SHADOW
float CalculateDistortionDerivative(vec2 position) {
	float x = length(position);
	#if defined SHADOW_INFINITE_RENDER_DISTANCE
		return SHADOW_DISTORTION_AMOUNT_INVERSE / Pow2(x + SHADOW_DISTORTION_AMOUNT_INVERSE);
	#else
		float a = exp(SHADOW_DISTORTION_AMOUNT_INVERSE);
		float b = exp(1.0) - a;

		float num   =      log(x * b + a)  * (x * b + a) - x * b;
		float denom = Pow2(log(x * b + a)) * (x * b + a);
		return num / denom;
	#endif
}
#endif

vec2 DistortShadowSpace(vec2 position) {
	return position * CalculateDistortionFactor(position);
}
vec3 DistortShadowSpace(vec3 position) {
	position.xy = DistortShadowSpace(position.xy);
	return position;
}
vec4 DistortShadowSpace(vec4 position) {
	position.xy = DistortShadowSpace(position.xy);
	return position;
}

#endif
