Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/FrameBufferObject.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/FrameBufferObject.cpp	(revision 2857)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/FrameBufferObject.cpp	(revision 2859)
@@ -132,9 +132,9 @@
 
 
-ColorBufferObject *FrameBufferObject::AddColorBuffer(ColorBufferObject::FORMAT col, 
-													 ColorBufferObject::WRAP_TYPE wrapType, 
-													 ColorBufferObject::FILTER_TYPE filterType, 
-													 bool useMipMap, 
-													 bool useMultiSampling)
+int FrameBufferObject::AddColorBuffer(ColorBufferObject::FORMAT col, 
+									  ColorBufferObject::WRAP_TYPE wrapType, 
+									  ColorBufferObject::FILTER_TYPE filterType, 
+									  bool useMipMap, 
+									  bool useMultiSampling)
 {
 	ColorBufferObject *colorBuf = 
@@ -142,6 +142,7 @@
 	mColorBuffers.push_back(colorBuf);
 
-	return colorBuf;
+	return (int)mColorBuffers.size() - 1;
 }
 
+
 } // namespace
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SsaoShader.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SsaoShader.cpp	(revision 2858)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SsaoShader.cpp	(revision 2859)
@@ -1,9 +1,257 @@
-#include "DeferredShader.h"
+#include "SsaoShader.h"
+#include "FrameBufferObject.h"
+#include "RenderState.h"
+#include "SampleGenerator.h"
+
 
 using namespace std;
 
+GLenum mrt[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT};
 
 namespace CHCDemoEngine
 {
 
+static CGprogram sCgSsaoProgram = NULL;
+
+static CGparameter sColorsTexParam;
+static CGparameter sPositionsTexParam;
+static CGparameter sNormalsTexParam;
+static CGparameter sOldModelViewProjMatrixParam;
+static CGparameter sMaxDepthParam;
+static CGparameter sSamplesParam; 
+static CGparameter sOldTexParam;
+static CGparameter sNoiseTexParam;
+static CGparameter sNoiseMultiplierParam;
+static CGparameter sExpFactorParam;
+
+
+#define NUM_SAMPLES 16
+
+// ssao random spherical samples
+static Sample2 samples[NUM_SAMPLES];
+
+
+static void PrintGLerror(char *msg)
+{
+	GLenum errCode;
+	const GLubyte *errStr;
+	
+	if ((errCode = glGetError()) != GL_NO_ERROR) 
+	{
+		errStr = gluErrorString(errCode);
+		fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg);
+	}
+}
+
+
+/** Generate poisson disc distributed sample points on the unit disc
+*/
+static void GenerateSamples()
+{
+	static PoissonDiscSampleGenerator poisson(NUM_SAMPLES, 1.0f);
+	poisson.Generate((Sample2 *)samples);
+}
+
+
+SsaoShader::SsaoShader(int w, int h, float expFactor, float scaleFactor):
+mWidth(w), mHeight(h), mExpFactor(expFactor), mScaleFactor(scaleFactor)
+{}
+
+
+void SsaoShader::Init(CGcontext context)
+{
+	
+	///////////////
+
+	sCgSsaoProgram = 
+		cgCreateProgramFromFile(context, 
+								CG_SOURCE,
+								"src/shaders/deferred.cg", 
+								RenderState::sCgFragmentProfile,
+								"main_ssao",
+								NULL);
+
+	if (sCgSsaoProgram != NULL)
+	{
+		cgGLLoadProgram(sCgSsaoProgram);
+
+		// we need size of texture for scaling
+		sPositionsTexParam = cgGetNamedParameter(sCgSsaoProgram, "positions");  
+		sColorsTexParam = cgGetNamedParameter(sCgSsaoProgram, "colors");  
+		sNormalsTexParam = cgGetNamedParameter(sCgSsaoProgram, "normals");  
+		sNoiseTexParam = cgGetNamedParameter(sCgSsaoProgram, "noiseTexture");
+		sNoiseMultiplierParam = cgGetNamedParameter(sCgSsaoProgram, "noiseMultiplier");
+		sOldModelViewProjMatrixParam = cgGetNamedParameter(sCgSsaoProgram, "oldModelViewProj");
+		sMaxDepthParam = cgGetNamedParameter(sCgSsaoProgram, "maxDepth");
+		sExpFactorParam = cgGetNamedParameter(sCgSsaoProgram, "expFactor");
+
+		sSamplesParam = cgGetNamedParameter(sCgSsaoProgram, "samples");
+		sOldTexParam = cgGetNamedParameter(sCgSsaoProgram, "oldTex");  
+
+		// generate samples for ssao kernel
+		GenerateSamples(); 
+		cgGLSetParameterArray2f(sSamplesParam, 0, NUM_SAMPLES, (const float *)samples);
+	}
+	else
+		cerr << "ssao program failed to load" << endl;
+
+	PrintGLerror("init");
+}
+
+
+void SsaoShader::Render(FrameBufferObject *fbo, FrameBufferObject *fbo2)
+{
+	FirstPass(fbo, fbo2);
+	SecondPass(fbo, fbo2);
+}
+
+
+void SsaoShader::FirstPass(FrameBufferObject *fbo, FrameBufferObject *fbo2)
+{
+	GLuint positionsTex = fbo->GetColorBuffer(0)->GetTexture();
+	GLuint colorsTex = fbo->GetColorBuffer(0)->GetTexture();
+	GLuint normalsTex = fbo->GetColorBuffer(0)->GetTexture();
+
+	glPushAttrib(GL_VIEWPORT_BIT);
+	glViewport(0, 0, mWidth, mHeight);
+
+	glDrawBuffers(1, mrt);
+
+	glDisable(GL_ALPHA_TEST);
+	glDisable(GL_TEXTURE_2D);
+	glDisable(GL_LIGHTING);
+
+	glMatrixMode(GL_PROJECTION);
+	glPushMatrix();
+	glLoadIdentity();
+
+	glMatrixMode(GL_MODELVIEW);
+	glPushMatrix();
+	glLoadIdentity();
+
+	const float offs = 0.5f;
+
+	glOrtho(-offs, offs, -offs, offs, 0, 1);
+
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	cgGLEnableProfile(RenderState::sCgFragmentProfile);
+
+	cgGLBindProgram(sCgSsaoProgram);
+
+	cgGLSetTextureParameter(sPositionsTexParam, positionsTex);
+	cgGLEnableTextureParameter(sPositionsTexParam);
+
+	cgGLSetTextureParameter(sColorsTexParam, colorsTex);
+	cgGLEnableTextureParameter(sColorsTexParam);
+
+	cgGLSetTextureParameter(sNormalsTexParam, normalsTex);
+	cgGLEnableTextureParameter(sNormalsTexParam);
+
+	cgGLSetTextureParameter(sNoiseTexParam, noiseTex);
+	cgGLEnableTextureParameter(sNoiseTexParam);
+
+	cgGLSetTextureParameter(sOldTexParam, oldTex);
+	cgGLEnableTextureParameter(sOldTexParam);
+
+	cgGLSetParameter1f(sNoiseMultiplierParam, RandomValue(3.0f, 17.0f));
+	
+	cgGLSetParameter1f(sMaxDepthParam, mScaleFactor);
+	cgGLSetParameter1f(sExpFactorParam, mExpFactor);
+
+
+	GenerateSamples(); 
+	cgGLSetParameterArray2f(sSamplesParam, 0, NUM_SAMPLES, (const float *)samples);
+
+	Vector3 tl, tr, bl, br;
+	ComputeViewVectors(tl, tr, bl, br);
+
+	glColor3f(1.0f, 1.0f, 1.0f);
+
+	glBegin(GL_QUADS);
+
+	// note: slightly larger texture hides ambient occlusion error on border but costs resolution
+	//float offs2 = 0.55f;
+	float offs2 = 0.5f;
+
+	glColor3f(bl.x, bl.y, bl.z); glTexCoord2f(0, 0); glVertex3f(-offs2, -offs2, -0.5f);
+	glColor3f(br.x, br.y, br.z); glTexCoord2f(1, 0); glVertex3f( offs2, -offs2, -0.5f);
+	glColor3f(tr.x, tr.y, tr.z); glTexCoord2f(1, 1); glVertex3f( offs2,  offs2, -0.5f);
+	glColor3f(tl.x, tl.y, tl.z); glTexCoord2f(0, 1); glVertex3f(-offs2,  offs2, -0.5f);
+
+	glEnd();
+
+	cgGLDisableTextureParameter(sColorsTexParamSsao);
+	cgGLDisableTextureParameter(sPositionsTexParamSsao);
+	cgGLDisableTextureParameter(sNormalsTexParamSsao);
+	cgGLDisableTextureParameter(sNoiseTexParamSsao);
+	cgGLDisableTextureParameter(sOldTexParamSsao);
+
+	cgGLDisableProfile(RenderState::sCgFragmentProfile);
+
+	glEnable(GL_LIGHTING);
+	glDisable(GL_TEXTURE_2D);
+
+	glMatrixMode(GL_PROJECTION);
+	glPopMatrix();
+
+	glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
+
+	glPopAttrib();
+
+	PrintGLerror("displaytexture");
+
+	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+
+	PrintGLerror("ssao first pass");
+}
+
+
+void SsaoShader::SecondPass(FrameBufferObject *fbo, FrameBufferObject *fbo2)
+{
+	glEnable(GL_TEXTURE_2D);
+
+	glBindTexture(GL_TEXTURE_2D, fbo2->GetColorBuffer(0)->GetTexture());
+
+	glDisable(GL_LIGHTING);
+	
+	glMatrixMode(GL_PROJECTION);
+	glPushMatrix();
+	glLoadIdentity();
+
+	glMatrixMode(GL_MODELVIEW);
+	glPushMatrix();
+	glLoadIdentity();
+
+	const float offs = 0.5f;
+	glOrtho(-offs, offs, -offs, offs, 0, 1);
+	
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+	glBegin(GL_QUADS);
+
+	glTexCoord2f(0, 0); glVertex3f(-offs, -offs, -0.5f);
+	glTexCoord2f(1, 0); glVertex3f( offs, -offs, -0.5f);
+	glTexCoord2f(1, 1); glVertex3f( offs,  offs, -0.5f);
+	glTexCoord2f(0, 1); glVertex3f(-offs,  offs, -0.5f);
+
+	glEnd();
+
+	glEnable(GL_LIGHTING);
+	glDisable(GL_TEXTURE_2D);
+	
+	glMatrixMode(GL_PROJECTION);
+	glPopMatrix();
+
+	glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
+
+	PrintGLerror("ssao second pass");
+}
+
+
+
 } // namespace
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/DeferredShader.h
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/DeferredShader.h	(revision 2858)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/DeferredShader.h	(revision 2859)
@@ -3,4 +3,8 @@
 
 #include "common.h"
+#include "glInterface.h"
+#include <Cg/cg.h>
+#include <Cg/cgGL.h>
+
 
 namespace CHCDemoEngine 
@@ -9,12 +13,14 @@
 class FrameBufferObject;
 
-/** This class implements a deferred shading algorithm.
+
+/** This class implements a deferred shading algorithm that takes
+	a frame buffer object as input and outputs an image in the given size
 */
 class DeferredShader
 {
 public:
-	/** constructor requesting an opengl occlusion query.
+	/** constructor for a deferred shader taking the requested output image size
 	*/
-	DeferredShader();
+	DeferredShader(int w, int h);
 
 	/** The algorithm renders the scene given an fbo.
@@ -22,4 +28,15 @@
 	*/
 	void Render(FrameBufferObject *fbo);
+
+	/** Initialises the deferred shader and loads the required shaders:
+		This function has to be called only once.
+	*/
+	static void Init(CGcontext context);
+
+
+protected:
+
+	int mWidth;
+	int mHeight;
 };
 
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SsaoShader.h
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SsaoShader.h	(revision 2858)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SsaoShader.h	(revision 2859)
@@ -1,6 +1,10 @@
-#ifndef _DeferredShader_H__
-#define _DeferredShader_H__
+#ifndef _SsaoShader_H__
+#define _SsaoShader_H__
 
 #include "common.h"
+#include "glInterface.h"
+#include <Cg/cg.h>
+#include <Cg/cgGL.h>
+
 
 namespace CHCDemoEngine 
@@ -9,19 +13,48 @@
 class FrameBufferObject;
 
-/** This class implements a deferred shading algorithm.
+
+/** This class implements a deferred shading algorithm that takes
+	a frame buffer object as input and outputs an image in the given size
 */
-class DeferredShader
+class SsaoShader
 {
 public:
-	/** constructor requesting an opengl occlusion query.
+	/** constructor for a deferred shader taking the requested output image size,
+		the exponential smoothing factor for temporal reprojection.
+		
+		The last parameter is a just a scale factor
+		for the scene depth in order to get better floating point precision in the shader
+		This must be reciprocal value of the scale factor used in the mrt shader.
 	*/
-	DeferredShader();
-
+	SsaoShader(int w, int h, float expFactor, float scaleFactor);
 	/** The algorithm renders the scene given an fbo.
 		The fbo must have color buffer, position buffer, normal buffer.
 	*/
-	void Render(FrameBufferObject *fbo);
+	void Render(FrameBufferObject *fbo, FrameBufferObject *fbo2);
+
+	/** Initialises the deferred shader and loads the required shaders:
+		This function has to be called only once.
+	*/
+	static void Init(CGcontext context);
+
+
+protected:
+
+	void FirstPass(FrameBufferObject *fbo, FrameBufferObject *fbo2);
+
+	void SecondPass(FrameBufferObject *fbo, FrameBufferObject *fbo2);
+
+
+	////////////
+
+	int mWidth;
+	int mHeight;
+
+	/// the temporal smoothing factor
+	float mExpFactor;
+	/// this is just a scale factor for the scene depth in order to get better float precision in the shader
+	float mScaleFactor;
 };
 
 } // namespace 
-#endif // _DeferredShader_H__
+#endif // _SsaoShader_H__
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp	(revision 2857)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp	(revision 2859)
@@ -671,22 +671,21 @@
 
 
-	ColorBufferObject *diffuseBuffer = 
-		myfbo->AddColorBuffer(ColorBufferObject::BUFFER_FLOAT_32, 
-		                      ColorBufferObject::WRAP_CLAMP_TO_EDGE, 
-							  ColorBufferObject::FILTER_LINEAR, 
-							  false, false);
-
-	ColorBufferObject *mypositionBuffer = 
-		myfbo->AddColorBuffer(ColorBufferObject::BUFFER_FLOAT_32, 
-		                      ColorBufferObject::WRAP_CLAMP_TO_EDGE, 
-							  ColorBufferObject::FILTER_NEAREST, 
-							  false, false);
-
-
-	ColorBufferObject *mynormalsBuffer = 
-		myfbo->AddColorBuffer(ColorBufferObject::BUFFER_UBYTE, 
-		                      ColorBufferObject::WRAP_CLAMP_TO_EDGE, 
-							  ColorBufferObject::FILTER_NEAREST, 
-							  false, false);
+	// the diffuse color buffer
+	myfbo->AddColorBuffer(ColorBufferObject::BUFFER_FLOAT_32, 
+						  ColorBufferObject::WRAP_CLAMP_TO_EDGE, 
+						  ColorBufferObject::FILTER_LINEAR, 
+						  false, false);
+
+	// the positions buffer
+	myfbo->AddColorBuffer(ColorBufferObject::BUFFER_FLOAT_32, 
+	                      ColorBufferObject::WRAP_CLAMP_TO_EDGE, 
+						  ColorBufferObject::FILTER_NEAREST, 
+						  false, false);
+
+	// the normals buffer
+	myfbo->AddColorBuffer(ColorBufferObject::BUFFER_UBYTE, 
+	                      ColorBufferObject::WRAP_CLAMP_TO_EDGE, 
+						  ColorBufferObject::FILTER_NEAREST, 
+						  false, false);
 
 	
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/DeferredShader.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/DeferredShader.cpp	(revision 2858)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/DeferredShader.cpp	(revision 2859)
@@ -1,4 +1,5 @@
 #include "DeferredShader.h"
-#include "glInterface.h"
+#include "FrameBufferObject.h"
+#include "RenderState.h"
 
 
@@ -9,8 +10,65 @@
 {
 
+
+static void PrintGLerror(char *msg)
+{
+	GLenum errCode;
+	const GLubyte *errStr;
+	
+	if ((errCode = glGetError()) != GL_NO_ERROR) 
+	{
+		errStr = gluErrorString(errCode);
+		fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg);
+	}
+}
+
+
+static CGprogram sCgDeferredProgram;
+static CGparameter sColorsTexParam;
+static CGparameter sPositionsTexParam;
+static CGparameter sNormalsTexParam;
+
+
+DeferredShader::DeferredShader(int w, int h):
+mWidth(w), mHeight(h)
+{}
+
+
+void DeferredShader::Init(CGcontext context)
+{
+	
+	sCgDeferredProgram = 
+		cgCreateProgramFromFile(context, 
+								CG_SOURCE,
+								"src/shaders/deferred.cg", 
+								RenderState::sCgFragmentProfile,
+								"main",
+								NULL);
+
+	if (sCgDeferredProgram != NULL)
+	{
+		cgGLLoadProgram(sCgDeferredProgram);
+
+		// we need size of texture for scaling
+		sPositionsTexParam = cgGetNamedParameter(sCgDeferredProgram, "positions");  
+		sColorsTexParam = cgGetNamedParameter(sCgDeferredProgram, "colors");  
+		sNormalsTexParam = cgGetNamedParameter(sCgDeferredProgram, "normals"); 
+	}
+	else
+		cerr << "deferred program failed to load" << endl;
+
+
+	PrintGLerror("init");
+}
+
+
 void DeferredShader::Render(FrameBufferObject *fbo)
 {
+	GLuint positionsTex = fbo->GetColorBuffer(0)->GetTexture();
+	GLuint colorsTex = fbo->GetColorBuffer(0)->GetTexture();
+	GLuint normalsTex = fbo->GetColorBuffer(0)->GetTexture();
+
 	glPushAttrib(GL_VIEWPORT_BIT);
-	glViewport(0, 0, fbo->GetWidth(), fbo->GetHeight());
+	glViewport(0, 0, mWidth, mHeight);
 
 	glDisable(GL_ALPHA_TEST);
@@ -35,9 +93,9 @@
 	cgGLBindProgram(sCgDeferredProgram);
 
+	cgGLSetTextureParameter(sColorsTexParam, colorsTex);
+	cgGLEnableTextureParameter(sColorsTexParam);
+
 	cgGLSetTextureParameter(sPositionsTexParam, positionsTex);
 	cgGLEnableTextureParameter(sPositionsTexParam);
-
-	cgGLSetTextureParameter(sColorsTexParam, colorsTex);
-	cgGLEnableTextureParameter(sColorsTexParam);
 
 	cgGLSetTextureParameter(sNormalsTexParam, normalsTex);
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/FrameBufferObject.h
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/FrameBufferObject.h	(revision 2857)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/FrameBufferObject.h	(revision 2859)
@@ -27,4 +27,6 @@
 					  bool useMultiSampling);
 
+	unsigned int GetTexture() const {return mTexId;}
+
 protected:
 
@@ -41,15 +43,21 @@
 
 	enum DEPTH_FORMAT { DEPTH_16, DEPTH_24, DEPTH_32 };
+
 	/** constructor requesting an opengl occlusion query.
 	*/
 	FrameBufferObject(int w, int h, bool useDepth, DEPTH_FORMAT d);
 	/** Creates and adds a color buffer to the current frame buffer object.
-		Returns a pointer to the buffer object
+		Returns the index that allows to retrieve the color buffer object.
 	*/
-	ColorBufferObject *AddColorBuffer(ColorBufferObject::FORMAT col, 
-		                              ColorBufferObject::WRAP_TYPE wrapType, 
-									  ColorBufferObject::FILTER_TYPE filterType, 
-									  bool useMipMap, 
-									  bool useMultiSampling);
+	int AddColorBuffer(ColorBufferObject::FORMAT col, 
+		               ColorBufferObject::WRAP_TYPE wrapType, 
+					   ColorBufferObject::FILTER_TYPE filterType, 
+					   bool useMipMap, 
+					   bool useMultiSampling);
+
+	/** Returns the color buffer object on position i.
+	*/
+	ColorBufferObject *GetColorBuffer(int i) const { return mColorBuffers[i]; }
+
 
 protected:
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/FriendlyCulling.vcproj
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/FriendlyCulling.vcproj	(revision 2857)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/FriendlyCulling.vcproj	(revision 2859)
@@ -316,4 +316,12 @@
 			</File>
 			<File
+				RelativePath=".\src\SsaoShader.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\SsaoShader.h"
+				>
+			</File>
+			<File
 				RelativePath=".\src\Triangle3.cpp"
 				>
