 	float viewDepth = - projectionMatrix.w / (depth2 + projectionMatrix.z);
 	// Compute the x and y components in view space.
 	return vec3(- ndcPos * viewDepth / projectionMatrix.xy , viewDepth);
+}
+
+// Compute the shadow multiplicator based on shadow map.
+
+float shadow(vec3 lightToPosDir){
+	float probabilityMax = 1.0;
+	// Read first and second moment from shadow map.
+	vec2 moments = texture(shadowMap, lightToPosDir).rg;
+	if(moments.x >= 1.0){
+		// No information in the depthmap: no occluder.
+		return 1.0;
+	}
+	// We have to scale by the frustum size.
+	moments *= vec2(lightFarPlane, lightFarPlane*lightFarPlane);
+	// Initial probability of light.
+	float dist = length(lightToPosDir);
+	float probability = float(dist <= moments.x);
+	// Compute variance.
+	float variance = moments.y - (moments.x * moments.x);
+	variance = max(variance, 0.00001);
+	// Delta of depth.
+	float d = dist - moments.x;
+	// Use Chebyshev to estimate bound on probability.
+	probabilityMax = variance / (variance + d*d);
+	probabilityMax = max(probability, probabilityMax);
+	// Limit light bleeding by rescaling and clamping the probability factor.
+	probabilityMax = clamp( (probabilityMax - 0.1) / (1.0 - 0.1), 0.0, 1.0);
+	return probabilityMax;
 }
 
 

	// Orientation: basic diffuse shadowing.
	float orientation = max(0.0, dot(l,n));
	// Attenuation with increasing distance to the light.
	
	float localRadius2 = dot(deltaPosition, deltaPosition);
	float radiusRatio2 = localRadius2/(lightRadius*lightRadius);
	float attenNum = clamp(1.0 - radiusRatio2, 0.0, 1.0);
	float attenuation = attenNum*attenNum;
	
	// BRDF contributions.
	// Compute F0 (fresnel coeff).

uniform sampler2D normalTexture;
uniform sampler2D depthTexture;
uniform sampler2D effectsTexture;
uniform samplerCube shadowMap;

uniform vec2 inverseScreenSize;
uniform vec4 projectionMatrix;
