#version 120

uniform float sun_ymin, sun_ymax;
uniform sampler2D sun_shadowmap;

uniform float animateSlider;

varying vec3 posVS, posWS, normalVS, normalWS;
varying vec4 sunUV;

#define NUMSAMPLES 1
#define ONE_BY_NUMSAMPLES (1.0/float(NUMSAMPLES))

float unpack(vec4 encodedValue) { return dot(encodedValue,vec4( 1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0 )); }

vec2 poissonDisk[16] = vec2[16](
   vec2( -0.94201624, -0.39906216 ), 
   vec2( 0.94558609, -0.76890725 ), 
   vec2( -0.094184101, -0.92938870 ), 
   vec2( 0.34495938, 0.29387760 ), 
   vec2( -0.91588581, 0.45771432 ), 
   vec2( -0.81544232, -0.87912464 ), 
   vec2( -0.38277543, 0.27676845 ), 
   vec2( 0.97484398, 0.75648379 ), 
   vec2( 0.44323325, -0.97511554 ), 
   vec2( 0.53742981, -0.47373420 ), 
   vec2( -0.26496911, -0.41893023 ), 
   vec2( 0.79197514, 0.19090188 ), 
   vec2( -0.24188840, 0.99706507 ), 
   vec2( -0.81409955, 0.91437590 ), 
   vec2( 0.19984126, 0.78641367 ), 
   vec2( 0.14383161, -0.14100790 )
);

float calculateSunShadow(vec3 nn) {
	float myLightZ = (posWS.y-sun_ymin)/(sun_ymax-sun_ymin);
	
	vec2 center = sunUV.xy / sunUV.w;
	
	float dott = max(0.0, nn.y);
	
	if (min(center.x, center.y)<0.0 || max(center.x, center.y)>1.0) {
		return dott;
	}
	
	const float dd=0.008;
	
	float shadowSum = 0.0;
	
	for (int i=0; i<NUMSAMPLES; i++) {
		vec2 uv = center;

		#if NUMSAMPLES>1
			uv += poissonDisk[i]*dd;
		#endif

		float sampleZ = unpack(texture2D(sun_shadowmap, uv));
		shadowSum += step(sampleZ, myLightZ);
	}
	
	return shadowSum * dott * (ONE_BY_NUMSAMPLES * ONE_BY_NUMSAMPLES);
}

void main(void)
{
	
	vec3 sunColor = vec3(0.8,0.8,0.65);
	
	vec3 n = normalWS;
	n.x+=sin(animateSlider*0.3)*cos(posWS.x*4.0)*0.005;
	n.y+=sin(animateSlider*0.4)*cos(posWS.y*3.0)*0.005;
	n.z+=sin(animateSlider*0.5)*cos(posWS.z*3.5)*0.005;
	
	float sunShadow = calculateSunShadow(normalize(n));
	
	gl_FragData[0] = gl_Color*(vec4(sunShadow * sunColor, 1.0));
	gl_FragData[1] = vec4(gl_Color.xyz,posVS.z);
}
