Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/deferred.cg
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/deferred.cg	(revision 2943)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/deferred.cg	(revision 2944)
@@ -13,4 +13,16 @@
 };
 
+#define NUM_SAMPLES 16
+
+
+float2 myreflect(float2 pt, float2 n)
+{
+	// distance to plane
+	float d = dot(n, pt);
+	// reflect around plane
+	float2 rpt = pt - d * 2.0f * n;
+
+	return rpt;
+}
 
 
@@ -73,4 +85,48 @@
 }
 
+
+float CalcShadowTerm(fragment IN,
+					 uniform sampler2D shadowMap,
+					 uniform float w,
+					 uniform float2 lightSpacePos,
+					 float depth,
+					 uniform float2 samples[NUM_SAMPLES],
+					 uniform sampler2D noiseTexture
+					 )
+{
+	float s;
+
+	float total_d = 0.0;
+	//float total_d = tex2D(shadowMap, lightSpacePos).x;
+
+	for (int i = 0; i < NUM_SAMPLES; ++ i) 
+	{
+		const float2 offset = samples[i];
+
+#if 1
+		////////////////////
+		//-- add random noise: reflect around random normal vector (warning: slow!)
+
+		float2 mynoise = tex2D(noiseTexture, IN.texCoord.xy).xy;
+		const float2 offsetTransformed = myreflect(offset, mynoise);
+#else
+		const float2 offsetTransformed = offset;
+#endif
+		// weight with projected coordinate to reach similar kernel size for near and far
+		float2 texcoord = lightSpacePos + offsetTransformed * w;
+
+		float shadowDepth = tex2D(shadowMap, texcoord).x;
+
+		total_d += step(shadowDepth, depth);
+		//total_d += length(offsetTransformed);
+	}
+
+	total_d /= (float)NUM_SAMPLES;
+
+	return total_d;
+}
+
+
+#if 0
 /** The mrt shader for standard rendering
 */
@@ -114,12 +170,12 @@
 	
 	shadowDepth[1] = tex2D(shadowMap, lightSpacePos.xy + float2( w,  w)).x;
-	shadowDepth[2] = tex2D(shadowMap, lightSpacePos.xy - float2( w, -w)).x;
-	shadowDepth[3] = tex2D(shadowMap, lightSpacePos.xy - float2(-w, -w)).x;
-	shadowDepth[4] = tex2D(shadowMap, lightSpacePos.xy - float2(-w,  w)).x;
-
-	shadowDepth[5] = tex2D(shadowMap, lightSpacePos.xy - float2( w,  0)).x;
-	shadowDepth[6] = tex2D(shadowMap, lightSpacePos.xy - float2( 0,  w)).x;
-	shadowDepth[7] = tex2D(shadowMap, lightSpacePos.xy - float2(-w,  0)).x;
-	shadowDepth[8] = tex2D(shadowMap, lightSpacePos.xy - float2( 0, -w)).x;
+	shadowDepth[2] = tex2D(shadowMap, lightSpacePos.xy + float2( w, -w)).x;
+	shadowDepth[3] = tex2D(shadowMap, lightSpacePos.xy + float2(-w, -w)).x;
+	shadowDepth[4] = tex2D(shadowMap, lightSpacePos.xy + float2(-w,  w)).x;
+
+	shadowDepth[5] = tex2D(shadowMap, lightSpacePos.xy + float2( w,  0)).x;
+	shadowDepth[6] = tex2D(shadowMap, lightSpacePos.xy + float2( 0,  w)).x;
+	shadowDepth[7] = tex2D(shadowMap, lightSpacePos.xy + float2(-w,  0)).x;
+	shadowDepth[8] = tex2D(shadowMap, lightSpacePos.xy + float2( 0, -w)).x;
 
 	
@@ -156,22 +212,53 @@
 	return OUT;
 }
-
-
-/** The mrt shader for standard rendering
-*/
-pixel main_shadow_debug(fragment IN, 
-						uniform sampler2D shadowMap,
-						uniform sampler2D colorTex,
-						uniform float4x4 shadowMatrix)
+#else
+
+pixel main_shadow(fragment IN, 
+				  uniform sampler2D colors,
+				  uniform sampler2D positions,
+				  uniform sampler2D normals,		   
+				  uniform sampler2D shadowMap,
+				  uniform float4x4 shadowMatrix,
+				  uniform float maxDepth,
+				  uniform float sampleWidth,
+				  uniform sampler2D noiseTexture,
+				  uniform float2 samples[NUM_SAMPLES]
+				  )
 {
 	pixel OUT;
-#if 0
-	// visualize depth
-	OUT.color = tex2Dlod(colorTex, float4(IN.texCoord.xy, 0, 0));
-#else
-	float4 col;
-	col = tex2Dlod(shadowMap, float4(IN.texCoord.xy, 0, 0));
-	OUT.color = float4(col.z / col.w, 0, 0, 1);
+
+	float4 norm = tex2D(normals, IN.texCoord.xy);
+	float4 color = tex2Dlod(colors, float4(IN.texCoord.xy, 0, 0));
+	float4 position = tex2D(positions, IN.texCoord.xy);
+
+
+	// an ambient color term
+	float amb = norm.w;
+
+	float3 normal = normalize(norm.xyz);
+	float4 col = shade(IN, color, position, normal, amb);
+	
+	position *= maxDepth;
+	position.w = 1.0f;
+	
+	float4 lightSpacePos = mul(shadowMatrix, position);
+	lightSpacePos /= lightSpacePos.w;
+
+	OUT.color = col;
+
+	float shadowTerm = CalcShadowTerm(IN, shadowMap, sampleWidth, lightSpacePos.xy, lightSpacePos.z, samples, noiseTexture);
+
+	if (amb < 0.9f) // hack: prevent shadowing the sky	
+	{
+		// base lighting
+		const float baseLighting = 0.3f;
+		OUT.color *= baseLighting + (1.0f - baseLighting) * (1.0f - shadowTerm);
+	}
+	
+	// also write out depth component
+	OUT.color.w = color.w;
+
+	return OUT;
+}
+
 #endif
-	return OUT;
-}
