#define SHADOW_MAP_BIAS 0.85
const int shadowMapResolution = 2048;		//shadowmap resolution

const float shadowDistance = 180.0;		//draw distance of shadows

float shadowAmbient = 3.0;		//shadow darkness levels, lower values mean darker shadows, see .vsh for colors
const bool shadowHardwareFiltering = true;

//--//--//--//--//--//--//

uniform mat4 shadowProjection;
uniform mat4 shadowModelView;
uniform sampler2DShadow shadow;
uniform sampler2DShadow shadowtex1;
uniform sampler2DShadow shadowcolor1;
vec4 ShadowProjection(vec4 fragpos){
	vec4 wp = Worldposition(fragpos);
			wp = (shadowModelView * wp);
			wp = (shadowProjection * wp);
return wp;
}

vec4 ShadowBias(vec4 worldpos){
	float distb = sqrt(worldpos.x*worldpos.x + worldpos.y*worldpos.y);
	float distortFactor = 1 - SHADOW_MAP_BIAS+ distb * SHADOW_MAP_BIAS;

	worldpos.xy /= ((distortFactor / distortFactor) * (distortFactor));

	worldpos.xyz = (0.5 * worldpos.xyz);
	worldpos.xyz += 0.5;
	return worldpos;
}

mat2 getRotaionMatrix(in vec2 coord){
  float rotationAmout = texture2D(
    noisetex,
    coord * vec2(
      viewWidth / noiseTextureResolution,
      viewHeight / noiseTextureResolution
      )
    ).r;

  return mat2(
    cos(rotationAmout), -sin(rotationAmout),
    sin(rotationAmout), cos(rotationAmout)
    );
}

vec3 calculateLitSurface(vec2 pos, vec3 color, float pixeldepth, vec3 norm){

  vec4 positionCameraSpace =  FragPosition(pos,pixeldepth);
  vec4 positionShadowSpace = ShadowProjection(positionCameraSpace);
  vec4 shadowMapBias = ShadowBias(positionShadowSpace);

  vec3 shadowCoord = shadowMapBias.xyz;
	mat2 Rotation = getRotaionMatrix(pos + cameraPosition.st);

  float dist = length(FragPosition(pos,pixeldepth).xyz);

  float distof = clamp(1.0-dist/(shadowDistance *0.75),0.0,1.0);

  float shadow_fade = clamp(distof*12.0,0.0,1.0);


    float NdotL = dot(normal, lightVector);
	NdotL = mix(NdotL,1.0,getReflectiveObjects);
    float diffthresh = (pow( 1 - SHADOW_MAP_BIAS+ sqrt(positionShadowSpace.x*positionShadowSpace.x + positionShadowSpace.y*positionShadowSpace.y) * SHADOW_MAP_BIAS*1.2,2.0)*(0.2/148.0)*(tan(acos(abs(NdotL)))) + (0.02/148.0));
    diffthresh = diffthresh*(12.0+0.1*clamp(tan(acos(abs(NdotL))),0.0,2.));


  vec3 shadows;
	float visibility = 0.0;
	vec3 visibility2 = vec3(visibility);
	float visibility3 = 0.0;
for (int i = -2; i < 2; i++){
    for (int j = -2; j < 2; j++){
				vec2 offset        			 = (vec2(j,i) * Rotation) / shadowMapResolution;

				visibility               = shadow2D(shadow, vec3(shadowCoord.st+offset,shadowCoord.z-diffthresh)).x  * (1 - rainStrength) ;
				visibility3         	   = shadow2D(shadowtex1, vec3(shadowCoord.st+offset,shadowCoord.z-diffthresh)).x  * (1 - rainStrength);
				visibility2         		+= mix(vec3(1.0),shadow2D(shadowcolor1, vec3(shadowCoord.st+offset,shadowCoord.z-diffthresh)).rgb * 2.0* (1 - rainStrength)  , vec3(1.0-visibility))* 10.0;
				visibility2             *=  1.0 - clamp((shadowCoord.z - visibility3) * 1200,0.0,1.0);
				visibility2 = mix(vec3(1.0), visibility2, 1.0);
				shadows           			= visibility2  * (1.2 - DayTimeCycle(timefract).a);
      }
}
  vec3 sunLightAmount = shadows * 0.111;
  float ambientLighting = float(shadowAmbient);

  sunLightAmount *= clamp(NdotL,0.0,1.0);
	ambientLighting = mix(ambientLighting,1.0,getReflectiveObjects);
   return (sunLightAmount + ambientLighting) ;

}
