Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/FrameBufferObject.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/FrameBufferObject.cpp	(revision 3193)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/FrameBufferObject.cpp	(revision 3204)
@@ -176,4 +176,6 @@
 	case WRAP_CLAMP_TO_EDGE:
 		wrapParam = GL_CLAMP_TO_EDGE; break;
+	case WRAP_CLAMP_TO_BORDER:
+		wrapParam = GL_MIRROR_CLAMP_TO_EDGE_EXT; break;
 	}
 
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaderenv.h
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaderenv.h	(revision 3203)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaderenv.h	(revision 3204)
@@ -8,5 +8,6 @@
 //#define NUM_SAMPLES 8
 //#define NUM_SAMPLES 16
-#define NUM_SAMPLES 96
+#define NUM_SAMPLES 24
+//#define NUM_SAMPLES 96
 
 #define SAMPLE_INTENSITY 0.3f
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/deferred.cg
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/deferred.cg	(revision 3199)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/deferred.cg	(revision 3204)
@@ -256,28 +256,50 @@
 	const float squaredLen = SqrLen(difVec);
 	
-	// test if this pixel was not valid in the old frame
-	float validPixel;
+	// test if this pixel was valid in the old frame
+	float pixelValid;
 
 	const bool oldDynamic = (squaredLen > DYNAMIC_OBJECTS_THRESHOLD);
 	const bool newDynamic = (oldPixel.z > DYNAMIC_OBJECTS_THRESHOLD);
 
-	if (!(oldDynamic && !newDynamic) && !(!oldDynamic && newDynamic) 
-		&& !(oldDynamic && newDynamic && (depthDif <= MIN_DEPTH_DIFF))
-		&& (oldTexCoords.x >= 0.0f) && (oldTexCoords.x < 1.0f)
-		&& (oldTexCoords.y >= 0.0f) && (oldTexCoords.y < 1.0f)
+	const float xOffs = 1.0f / 1024.0f;
+	const float yOffs = 1.0f / 768.0f;
+
+	// actually 0 means pixel is valid
+	const float pixelIsValid = 0.0f;
+	const float pixelCouldBeValid = 2.0f;
+	const float pixelNotValid = 10.0f;
+
+	const float eps = 1e-6f;
+
+	if (0
+		//&& !(oldDynamic && newDynamic && (depthDif <= MIN_DEPTH_DIFF))
+		//&& (oldTexCoords.x + eps >= xOffs) && (oldTexCoords.x <= (1.0f - xOffs) + eps )
+		//&& (oldTexCoords.y + eps >= yOffs) && (oldTexCoords.y <= (1.0f - yOffs) + eps )
+		|| (oldTexCoords.x < .0f) || (oldTexCoords.x >= 1.0f)
+		|| (oldTexCoords.y < .0f) || (oldTexCoords.y >= 1.0f)
 		)
 	{
-		validPixel = 0.0f;
-	}
-	else
+		pixelValid = pixelNotValid;
+	}
+	// check if changed from dynamic to not dynamic object
+	// or there is a depth discontinuity
+	else 
+	if ((oldDynamic && !newDynamic) || (!oldDynamic && newDynamic) ||
+		(oldDynamic && newDynamic && (depthDif <= MIN_DEPTH_DIFF)))
 	{	
-		validPixel = 10.5f;
-	}
-
-	//return depthDif;
-	return validPixel;
-}
-
-
+		pixelValid = pixelCouldBeValid; 
+	}
+	else 
+	{
+		pixelValid = pixelIsValid;
+	}
+
+	return pixelValid;
+}
+
+
+/** This function is called during downsampling of the buffers
+	for ssao.
+*/
 pixel PrepareSsao(fragment IN,
 				   uniform sampler2D colorsTex,
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/combineSsao.cg
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/combineSsao.cg	(revision 3203)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/combineSsao.cg	(revision 3204)
@@ -125,8 +125,7 @@
 
 		aoSample = tex2Dlod(ssaoTex, sampleTexCoord);
-		sampleNorm = tex2Dlod(normalsTex, sampleTexCoord).xyz;
+		//sampleNorm = tex2Dlod(normalsTex, sampleTexCoord).xyz;
 
 		// check spatial discontinuity
-
 		// note: using the depth from the color texture is not 100% correct as depth was
 		// not scaled with the interpolated view vector depth yet ...
@@ -137,5 +136,5 @@
 		spatialFactor = 1.0f / max(len, 1e-3f);
 
-		//normalFactor = max(step(.0f, dot(sampleNorm, centerNormal)), 1e-2f);
+		//normalFactor = max(step(.2f, dot(sampleNorm, centerNormal)), 1e-2f);
 		convergenceFactor = aoSample.y + 1.0f;
 		
@@ -172,5 +171,5 @@
 
 	float4 col = tex2Dlod(colorsTex, float4(IN.texCoord, 0, 0));
-	float4 ao = tex2Dlod(ssaoTex, float4(IN.texCoord, 0, 0));
+	float4 ao =  tex2Dlod(ssaoTex, float4(IN.texCoord, 0, 0));
 
 	// get the minimum convergence by exactly sampling the 4 surrounding
@@ -178,16 +177,18 @@
 	// will be interpolated when upsampling and filter size does not match!
 	float4 texelCenterConv;
-	const float w = 512.0f; const float h = 384.0f;
+	//const float w = 512.0f; const float h = 384.0f;
+	//const float w = 128.0f; const float h = 96.0f;
+	const float w = 16.0f; const float h = 12.0f;
 	const float xoffs = .5f / w; const float yoffs = .5f / h;
 
 	// get position exactly between old texel centers
 	float2 center;
-	center.x = float(floor(IN.texCoord.x * w - .5f) + 1.0f) / w;
-	center.y = float(floor(IN.texCoord.y * h - .5f) + 1.0f) / h;
-
-	texelCenterConv.x = tex2Dlod(ssaoTex, float4(center + float2(xoffs, yoffs), 0, 0)).y;
-	texelCenterConv.y = tex2Dlod(ssaoTex, float4(center + float2(xoffs, -yoffs), 0, 0)).y;
-	texelCenterConv.z = tex2Dlod(ssaoTex, float4(center + float2(-xoffs, yoffs), 0, 0)).y;
-	texelCenterConv.w = tex2Dlod(ssaoTex, float4(center + float2(-xoffs, -yoffs), 0, 0)).y;
+	center.x = (floor(IN.texCoord.x * w - .5f) + 1.0f) / w;
+	center.y = (floor(IN.texCoord.y * h - .5f) + 1.0f) / h;
+//center=IN.texCoord;
+	texelCenterConv.x = tex2Dlod(ssaoTex, float4(center + float2( xoffs,  yoffs), 0, 0)).y;
+	texelCenterConv.y = tex2Dlod(ssaoTex, float4(center + float2( xoffs, -yoffs), 0, 0)).y;
+	texelCenterConv.z = tex2Dlod(ssaoTex, float4(center + float2(-xoffs, -yoffs), 0, 0)).y;
+	texelCenterConv.w = tex2Dlod(ssaoTex, float4(center + float2(-xoffs,  yoffs), 0, 0)).y;
 
 	const float m1 = min(texelCenterConv.x, texelCenterConv.y);
@@ -196,8 +197,10 @@
 	const float minConvergence = min(m1, m2);
 
-	const float convergence = step(200.0f, minConvergence) * minConvergence;
+	const float convergence = minConvergence;
+	//const float convergence = 0;
 	//const float convergence = ao.y;
 
-	// filter reaches size 1 after thres samples
+	// filter reaches size 1 pixel after thres samples: 
+	// afterwards we do not use the filter anymore
 	const float thres = 500.0f; 
 
@@ -222,5 +225,7 @@
 
 	//OUT.illum_col.xyz = float3(ao.x, ao.x, step(thres, convergence));
-	//OUT.illum_col.xyz = float3(ao.x, ao.x, ao.x);
+	OUT.illum_col.xyz = float3(0, convergence, 0);
+	//OUT.illum_col.xyz = float3(abs(center.x - IN.texCoord.x) * 16.0f, abs(center.y - IN.texCoord.y) * 12.0f, 0);
+	
 	//OUT.illum_col.xyz = float3(0, clamp(1.0f - ao.y * 1e-3f, 0, 1), 1);
 	//OUT.illum_col.xyz = float3(0, 1.0f - step(0.5f + NUM_SAMPLES, convergence), 1);
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;
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/DeferredRenderer.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/DeferredRenderer.cpp	(revision 3199)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/DeferredRenderer.cpp	(revision 3204)
@@ -292,5 +292,4 @@
 
 
-
 DeferredRenderer::DeferredRenderer(int w, int h, PerspectiveCamera *cam):
 mWidth(w), mHeight(h), 
@@ -306,5 +305,7 @@
 	//-- the flip-flop fbos
 
-	const int dsw = w / 2; const int dsh = h / 2;
+	//const int dsw = w / 2; const int dsh = h / 2;
+	//const int dsw = 128; const int dsh = 96;
+	const int dsw = 16; const int dsh = 12;
 	//const int dsw = w; const int dsh = h;
 
@@ -325,7 +326,8 @@
 
 	mDownSampleFbo = new FrameBufferObject(dsw, dsh, FrameBufferObject::DEPTH_NONE);
+	// the downsampled color + depth buffer
 	mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
-// downsample buffer for the normal texture
-mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
+	// downsample buffer for the normal texture
+	mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
 
 	for (int i = 0; i < 2; ++ i)
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/FrameBufferObject.h
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/FrameBufferObject.h	(revision 3147)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/FrameBufferObject.h	(revision 3204)
@@ -16,5 +16,5 @@
 
 	enum FORMAT {RGB_UBYTE, RGBA_UBYTE, RGB_FLOAT_16, RGBA_FLOAT_16, RGB_FLOAT_32, RGBA_FLOAT_32};
-	enum WRAP_TYPE {WRAP_REPEAT, WRAP_CLAMP_TO_EDGE};
+	enum WRAP_TYPE {WRAP_REPEAT, WRAP_CLAMP_TO_EDGE, WRAP_CLAMP_TO_BORDER};
 	enum FILTER_TYPE {FILTER_NEAREST, FILTER_LINEAR};
 
