Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/ssao.cg
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/ssao.cg	(revision 3203)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/ssao.cg	(revision 3204)
@@ -105,4 +105,7 @@
 	const float4 oldPixel = tex2Dlod(oldTex, float4(oldTexCoords, .0f, .0f));
 
+	// the ssao value in the old frame
+	const float ssao = oldPixel.x;
+
 #if USE_EYESPACE_DEPTH
 
@@ -129,21 +132,29 @@
 #endif
 
-	float newWeight;
+	const float xOffs = 1.0f / 1024.0f;
+	const float yOffs = 1.0f / 768.0f;
+	const float eps = 1e-6f;
+
+	// the weight of the old value
+	float w;
+
+	//////////////
+	//-- reuse old value only if it was still valid in the old frame
 
 	if (1
-		&& (oldTexCoords.x >= 0.0f) && (oldTexCoords.x < 1.0f)
-		&& (oldTexCoords.y >= 0.0f) && (oldTexCoords.y < 1.0f)
+		&& (oldTexCoords.x + eps >= xOffs) && (oldTexCoords.x <= 1.0f - xOffs + eps)
+		&& (oldTexCoords.y + eps >= yOffs) && (oldTexCoords.y <= 1.0f - yOffs + eps)
 		&& (depthDif <= MIN_DEPTH_DIFF) 
 		)
 	{
-		// increase the weight for convergence
-		newWeight =  oldPixel.y;
+		// pixel valid => retrieve the convergence weight
+		w = 10.0f;//oldPixel.y;
 	}
 	else
 	{	
-		newWeight = 0.0f;
-	}
-
-	return float2(oldPixel.x, newWeight);
+		w = 0.0f;
+	}
+
+	return float2(ssao, w);
 }
 
@@ -168,8 +179,4 @@
 			 )
 {
-	// Check in a circular area around the current position.
-	// Shoot vectors to the positions there, and check the angle to these positions.
-	// Summing up these angles gives an estimation of the occlusion at the current position.
-
 	float total_ao = .0f;
 	float numSamples = .0f;
@@ -198,5 +205,4 @@
 		const float3 samplePos = ReconstructSamplePos(sampleColor.w, texcoord, bl, br, tl, tr);
 		// the normal of the current sample
-		//const float3 sampleNormal = normalize(tex2Dlod(normalTex, float4(texcoord, 0, 0)).xyz);
 		const float3 sampleNormal = tex2Dlod(normalTex, float4(texcoord, 0, 0)).xyz;
 
@@ -218,7 +224,4 @@
 		cosAngle *= step(0.0f, dot(dirSample, normal));
 	
-		// the distance_scale offset is used to avoid singularity that occurs at global illumination when 
-		// the distance to a sample approaches zero
-		//const float aoContrib = SAMPLE_INTENSITY / (DISTANCE_SCALE + lengthToSample * lengthToSample);
 		const float aoContrib = SAMPLE_INTENSITY / sqrLen;
 		//const float aoContrib = (1.0f > lengthToSample) ? occlusionPower(9e-2f, DISTANCE_SCALE + lengthToSample): .0f;
@@ -248,4 +251,9 @@
 	This version of the ssao shader uses the dotproduct between 
 	pixel-to-sample direction and sample normal as weight.
+
+    The algorithm works like the following:
+	1) Check in a circular area around the current position.
+	2) Shoot vectors to the positions there, and check the angle to these positions.
+	3) Summing up these angles gives an estimation of the occlusion at the current position.
 */
 float3 ssao(fragment IN,
@@ -264,8 +272,4 @@
 			)
 {
-	// Check in a circular area around the current position.
-	// Shoot vectors to the positions there, and check the angle to these positions.
-	// Summing up these angles gives an estimation of the occlusion at the current position.
-
 	float total_ao = .0f;
 	float validSamples = .0f;
@@ -278,5 +282,6 @@
 #if 1
 		////////////////////
-		//-- add random noise: reflect around random normal vector (rather slow!)
+		//-- add random noise: reflect around random normal vector 
+		//-- (slows down the computation for some reason!)
 
 		float2 mynoise = tex2Dlod(noiseTex, float4(IN.texCoord * 4.0f, 0, 0)).xy;
@@ -286,5 +291,4 @@
 #endif
 		// weight with projected coordinate to reach similar kernel size for near and far
-		//const float2 texcoord = IN.texCoord.xy + offsetTransformed * scaleFactor + jitter;
 		const float2 texcoord = IN.texCoord.xy + offsetTransformed * scaleFactor;
 
@@ -321,5 +325,6 @@
 		// hack: the distance measure can fail in some cases => choose something different
 		const float tooFarAway = step(1.0f, lengthToSample);
-		validSamples += (1.0f - tooFarAway) * sampleColor.x;
+		validSamples = max(validSamples, (1.0f - tooFarAway) * sampleColor.x);
+
 		//validSamples += sampleColor.x;
 
@@ -327,5 +332,5 @@
 
 		//if ((validSamples < 1.0f) && (newWeight > 200) && (numSamples >= 8)) break;
-		if ((validSamples < 1.0f) && (numSamples >= 8)) break;
+		//if ((validSamples < 1.0f) && (numSamples >= 8)) break;
 	}
 
@@ -400,5 +405,4 @@
 
 	// cull background note: this should be done with the stencil buffer
-	//if (SqrLen(diffVec < 1e6f) && (eyeSpaceDepth < 1e10f))
 	if (eyeSpaceDepth < 1e10f)
 	{
@@ -412,15 +416,15 @@
 
 	const float squaredLen = SqrLen(diffVec);
-	
-	if ((ao.y > 1.0f) && (squaredLen < DYNAMIC_OBJECTS_THRESHOLD))
-	{		
+/*	
+	if (ao.y > 4.0f) oldWeight = 0;
+	else if ((ao.y > 1.0f) && (squaredLen < DYNAMIC_OBJECTS_THRESHOLD))
 		oldWeight = min(oldWeight, 4.0f * NUM_SAMPLES);
-	}
-
+*/	
 	const float newWeight = ao.z;
 
 	// blend between old and new samples (and avoid division by zero)
 	OUT.illum_col.x = (ao.x * newWeight + oldSsao * oldWeight) / max(1e-6f, (newWeight + oldWeight));
-	OUT.illum_col.y = clamp(newWeight + oldWeight, .0f, temporalCoherence);
+	OUT.illum_col.y = oldWeight;//clamp(newWeight + oldWeight, .0f, temporalCoherence);
+
 	OUT.illum_col.z = SqrLen(diffVec);
 	OUT.illum_col.w = eyeSpaceDepth;
