Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polyhedron.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polyhedron.h	(revision 2929)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polyhedron.h	(revision 3020)
@@ -37,4 +37,5 @@
 	~Polyhedron();
 	/** Computes the intersection of the polyhedron with the given plane
+		and returns it as another polyhedron
 		@returns NULL if the geometry is not split by this plane
 	*/
@@ -42,5 +43,8 @@
 	/** Adds a polygon to the polyhedron.
 	*/
+	//void Add(const Polygon3 &poly);
+	
 	void Add(Polygon3 *poly);
+
 	/** Computes bounding box of the geometry.
 	*/
@@ -70,10 +74,10 @@
 	*/
 	void CollectVertices(VertexArray &vertices) const;
-	
-	inline friend std::ostream &operator<<(std::ostream &s, const Polyhedron &a);
-
 	/** Computes polyhedron from a couple of intersecting planes and a bounding box.
 	*/
 	static Polyhedron *CreatePolyhedron(const std::vector<Plane3> &planes, const AxisAlignedBox3 &box);
+
+	inline friend std::ostream &operator<<(std::ostream &s, const Polyhedron &a);
+
 
 protected:
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SkyPreetham.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SkyPreetham.cpp	(revision 3017)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SkyPreetham.cpp	(revision 3020)
@@ -344,6 +344,6 @@
 
 	// diffuse component should be more saturated (and less blueish) for high sun positions
-	diffuse.x *= 1.2f;
-	diffuse.z *= 0.8f;
+	diffuse.x *= 1.3f;
+	diffuse.z *= 0.7f;
 
 	// scale diffuse component in order to make sky look less bright in relation to
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ResourceManager.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ResourceManager.h	(revision 3019)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ResourceManager.h	(revision 3020)
@@ -10,5 +10,4 @@
 
 
-#define _CRTDBG_MAP_ALLOC
 
 class igzstream;
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/irradiance.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/irradiance.cpp	(revision 3020)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/irradiance.cpp	(revision 3020)
@@ -0,0 +1,2184 @@
+// chcdemo.cpp : Defines the entry point for the console application.
+//
+#include "glInterface.h"
+#include <math.h>
+#include <time.h>
+#include "common.h"
+#include "RenderTraverser.h"
+#include "SceneEntity.h"
+#include "Vector3.h"
+#include "Matrix4x4.h"
+#include "ResourceManager.h"
+#include "Bvh.h"
+#include "Camera.h"
+#include "Geometry.h"
+#include "BvhLoader.h"
+#include "FrustumCullingTraverser.h"
+#include "StopAndWaitTraverser.h"
+#include "CHCTraverser.h"
+#include "CHCPlusPlusTraverser.h"
+#include "Visualization.h"
+#include "RenderState.h"
+#include "Timer/PerfTimer.h"
+#include "SceneQuery.h"
+#include "RenderQueue.h"
+#include "Material.h"
+#include <Cg/cg.h>
+#include <Cg/cgGL.h>
+#include "glfont2.h"
+#include "PerformanceGraph.h"
+#include "Environment.h"
+#include "Halton.h"
+#include "Transform3.h"
+#include "SampleGenerator.h"
+#include "FrameBufferObject.h"
+#include "DeferredRenderer.h"
+#include "ShadowMapping.h"
+#include "Light.h"
+#include "SceneEntityConverter.h"
+#include "ObjConverter.h"
+#include "SkyPreetham.h"
+#include "Texture.h"
+#include "EntityMerger.h"
+
+
+
+using namespace std;
+using namespace CHCDemoEngine;
+
+
+static Environment env;
+
+#define MAX_DEPTH_CONST 10.0f
+
+// fbo
+FrameBufferObject *fbo = NULL;
+
+GLuint fontTex;
+
+/// the renderable scene geometry
+SceneEntityContainer sceneEntities;
+SceneEntityContainer sceneEntities2;
+SceneEntity *buddha = NULL;
+// traverses and renders the hierarchy
+RenderTraverser *traverser = NULL;
+/// the hierarchy
+Bvh *bvh = NULL;
+/// handles scene loading
+ResourceManager *loader = NULL;
+/// the scene camera
+Camera *camera = NULL;
+/// the scene camera
+Camera *visCamera = NULL;
+/// the visualization
+Visualization *visualization = NULL;
+/// the current render state
+RenderState state;
+/// the rendering algorithm
+int renderMode = RenderTraverser::CHCPLUSPLUS;
+// eye near plane distance
+float nearDist = 0.2f;
+float farDist = 1e6f;
+/// the field of view
+float fov = 50.0f;
+/// the pixel threshold where a node is still considered invisible
+int threshold;
+
+int assumedVisibleFrames = 10;
+int maxBatchSize = 50;
+
+int trianglesPerVirtualLeaf = INITIAL_TRIANGLES_PER_VIRTUAL_LEAVES;
+
+SceneQuery *sceneQuery = NULL;
+RenderQueue *renderQueue = NULL;
+
+// traverses and renders the hierarchy
+RenderTraverser *shadowTraverser = NULL;
+
+SkyPreetham *preetham = NULL;
+
+
+/// the used render type for this render pass
+enum RenderMethod
+{
+	RENDER_FIXED,
+	RENDER_DEPTH_PASS,
+	RENDER_DEFERRED,
+	RENDER_DEPTH_PASS_DEFERRED,
+	RENDER_NUM_RENDER_TYPES
+};
+
+/// one of four possible render methods
+int renderMethod = RENDER_FIXED;
+
+
+/// these values get scaled with the frame rate
+static float keyForwardMotion = 30.0f;
+static float keyRotation = 1.5f;
+
+/// elapsed time in milliseconds
+double elapsedTime = 1000.0f;
+double algTime = 1000.0f;
+
+static int winWidth = 1024;
+static int winHeight = 768;
+
+int shadowSize = 2048;
+
+static float winAspectRatio = 1.0f;
+
+double accumulatedTime = 1000;
+float fps = 1e3f;
+
+glfont::GLFont myfont;
+
+// rendertexture
+static int texWidth = 1024;
+static int texHeight = 768;
+
+int renderedObjects = 0;
+int renderedNodes = 0;
+int renderedTriangles = 0;
+
+int issuedQueries = 0;
+int traversedNodes = 0;
+int frustumCulledNodes = 0;
+int queryCulledNodes = 0;
+int stateChanges = 0;
+int numBatches = 0;
+
+
+// mouse navigation state
+int xEyeBegin = 0;
+int yEyeBegin = 0;
+int yMotionBegin = 0;
+int verticalMotionBegin = 0;
+int horizontalMotionBegin = 0;
+
+
+bool leftKeyPressed = false;
+bool rightKeyPressed = false;
+bool upKeyPressed = false;
+bool downKeyPressed = false;
+bool descendKeyPressed = false;
+bool ascendKeyPressed = false;
+
+bool showHelp = false;
+bool showStatistics = false;
+bool showOptions = true;
+bool showBoundingVolumes = false;
+bool visMode = false;
+
+bool useOptimization = false;
+bool useTightBounds = true;
+bool useRenderQueue = true;
+bool useMultiQueries = true;
+bool flyMode = true;
+
+bool useGlobIllum = false;
+bool useTemporalCoherence = true;
+bool showAlgorithmTime = false;
+
+bool useFullScreen = false;
+bool useLODs = true;
+bool moveLight = false;
+
+bool useAdvancedShading = false;
+bool showShadowMap = false;
+bool renderLightView = false;
+
+bool altKeyPressed = false;
+
+bool useHDR = true;
+
+static float ssaoTempCohFactor = 255.0;
+
+
+PerfTimer frameTimer, algTimer;
+
+static int sCurrentMrtSet = 0;
+
+PerformanceGraph *perfGraph = NULL;
+
+
+//DeferredRenderer::SAMPLING_METHOD samplingMethod = DeferredRenderer::SAMPLING_POISSON;
+DeferredRenderer::SAMPLING_METHOD samplingMethod = DeferredRenderer::SAMPLING_QUADRATIC;
+
+ShadowMap *shadowMap = NULL;
+DirectionalLight *light = NULL;
+DeferredRenderer *ssaoShader = NULL;
+
+SceneEntity *cube = NULL;
+SceneEntity *aeroplane = NULL;
+SceneEntity *skyDome = NULL;
+
+
+
+// function forward declarations
+void InitExtensions();
+void DisplayVisualization();
+void InitGLstate();
+void InitRenderTexture();
+void InitCg();
+void CleanUp();
+void SetupEyeView();
+void UpdateEyeMtx();
+void SetupLighting();
+void DisplayStats();
+void Output(int x, int y, const char *string);
+void DrawHelpMessage();
+void RenderSky();
+void RenderVisibleObjects();
+
+void Begin2D();
+void End2D();
+void KeyBoard(unsigned char c, int x, int y);
+void DrawStatistics();
+void Display();
+void Special(int c, int x, int y);
+void KeyUp(unsigned char c, int x, int y);
+void SpecialKeyUp(int c, int x, int y);
+void Reshape(int w, int h);
+void Mouse(int button, int state, int x, int y);
+void LeftMotion(int x, int y);
+void RightMotion(int x, int y);
+void MiddleMotion(int x, int y);
+void CalcDecimalPoint(string &str, int d);
+
+RenderTraverser *CreateTraverser(Camera *cam);
+
+void KeyHorizontalMotion(float shift);
+void KeyVerticalMotion(float shift);
+
+void PlaceViewer(const Vector3 &oldPos);
+
+inline float KeyRotationAngle() { return keyRotation * elapsedTime * 1e-3f; }
+inline float KeyShift() { return keyForwardMotion * elapsedTime * 1e-3f; }
+
+void InitFBO();
+
+void RightMotionLight(int x, int y);
+
+void RenderShadowMap(float newfar);
+
+
+
+/////////
+//-- cg stuff
+
+static CGcontext sCgContext = NULL;
+static CGprogram sCgMrtVertexProgram = NULL;
+
+static CGparameter sMaxDepthParam;
+static CGparameter sMaxDepthParamTex;
+static CGparameter sEyePosParamTex;
+static CGparameter sEyePosParam;
+
+static CGparameter sTLParam;
+static CGparameter sTRParam;
+static CGparameter sBRParam;
+static CGparameter sBLParam;
+
+static CGparameter sTLParamTex;
+static CGparameter sTRParamTex;
+static CGparameter sBRParamTex;
+static CGparameter sBLParamTex;
+
+static Matrix4x4 viewProjMat = IdentityMatrix();
+static Matrix4x4 oldViewProjMat = IdentityMatrix();
+
+
+
+static void cgErrorCallback()
+{
+	CGerror lastError = cgGetError();
+
+	if(lastError)
+	{
+		printf("%s\n\n", cgGetErrorString(lastError));
+		printf("%s\n", cgGetLastListing(sCgContext));
+		
+		printf("Cg error, exiting...\n");
+
+		exit(0);
+	}
+}
+
+
+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);
+	}
+}
+
+
+int main(int argc, char* argv[])
+{
+	int returnCode = 0;
+
+	Vector3 camPos(.0f, .0f, .0f);
+	Vector3 camDir(.0f, 1.0f, .0f);
+	Vector3 lightDir(-0.8f, 1.0f, -0.7f);
+
+	cout << "=== reading environment file ===" << endl << endl;
+
+	string envFileName = "default.env";
+	if (!env.Read(envFileName))
+	{
+		cerr << "loading environment " << envFileName << " failed!" << endl;
+	}
+	else
+	{
+		env.GetIntParam(string("assumedVisibleFrames"), assumedVisibleFrames);
+		env.GetIntParam(string("maxBatchSize"), maxBatchSize);
+		env.GetIntParam(string("trianglesPerVirtualLeaf"), trianglesPerVirtualLeaf);
+
+		env.GetFloatParam(string("keyForwardMotion"), keyForwardMotion);
+		env.GetFloatParam(string("keyRotation"), keyRotation);
+
+		env.GetIntParam(string("winWidth"), winWidth);
+		env.GetIntParam(string("winHeight"), winHeight);
+
+		env.GetBoolParam(string("useFullScreen"), useFullScreen);
+		env.GetFloatParam(string("tempCohFactor"), ssaoTempCohFactor);
+		env.GetVectorParam(string("camPosition"), camPos);
+		env.GetVectorParam(string("camDirection"), camDir);
+		env.GetVectorParam(string("lightDirection"), lightDir);
+
+		env.GetBoolParam(string("useLODs"), useLODs);
+		env.GetIntParam(string("shadowSize"), shadowSize);
+
+		env.GetBoolParam(string("useHDR"), useHDR);
+
+		//env.GetStringParam(string("modelPath"), model_path);
+		//env.GetIntParam(string("numSssaoSamples"), numSsaoSamples);
+
+
+		cout << "assumedVisibleFrames: " << assumedVisibleFrames << endl; 
+		cout << "maxBatchSize: " << maxBatchSize << endl;
+		cout << "trianglesPerVirtualLeaf: " << trianglesPerVirtualLeaf << endl;
+
+		cout << "keyForwardMotion: " << keyForwardMotion << endl;
+		cout << "keyRotation: " << keyRotation << endl;
+		cout << "winWidth: " << winWidth << endl;
+		cout << "winHeight: " << winHeight << endl;
+		cout << "useFullScreen: " << useFullScreen << endl;
+		cout << "useLODs: " << useLODs << endl;
+		cout << "camPosition: " << camPos << endl;
+		cout << "temporal coherence: " << ssaoTempCohFactor << endl;
+		cout << "shadow size: " << shadowSize << endl;
+
+		//cout << "model path: " << model_path << endl;
+
+		cout << "**** end parameters ****" << endl << endl;
+	}
+
+	///////////////////////////
+
+	camera = new Camera(winWidth, winHeight, fov);
+	camera->SetNear(nearDist);
+	camera->SetFar(1000);
+
+	camera->SetDirection(camDir);
+	camera->SetPosition(camPos);
+
+	visCamera = new Camera(winWidth, winHeight, fov);
+	visCamera->SetNear(0.0f);
+	visCamera->Yaw(.5 * M_PI);
+
+	// create a new light
+	light = new DirectionalLight(lightDir, RgbaColor(1, 1, 1, 1), RgbaColor(1, 1, 1, 1));
+
+
+	renderQueue = new RenderQueue(&state, camera);
+
+	glutInitWindowSize(winWidth, winHeight);
+	glutInit(&argc, argv);
+	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE);
+	//glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
+	//glutInitDisplayString("samples=2");
+
+	SceneEntity::SetUseLODs(useLODs);
+
+
+	if (!useFullScreen)
+	{
+		glutCreateWindow("FriendlyCulling");
+	}
+	else
+	{
+		glutGameModeString( "1024x768:32@75" ); 
+		glutEnterGameMode(); 
+	}
+
+	glutDisplayFunc(Display);
+	glutKeyboardFunc(KeyBoard);
+	glutSpecialFunc(Special);
+	glutReshapeFunc(Reshape);
+	glutMouseFunc(Mouse);
+	glutIdleFunc(Display);
+	glutKeyboardUpFunc(KeyUp);
+	glutSpecialUpFunc(SpecialKeyUp);
+	glutIgnoreKeyRepeat(true);
+
+	// initialise gl graphics
+	InitExtensions();
+	InitGLstate();
+
+
+	glEnable(GL_MULTISAMPLE_ARB);
+	glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
+
+	LeftMotion(0, 0);
+	MiddleMotion(0, 0);
+
+	perfGraph = new PerformanceGraph(1000);
+
+	loader = new ResourceManager();
+
+	const string filename = string(model_path + "city.dem");
+
+	if (loader->Load(filename, sceneEntities))
+		cout << "model " << filename << " loaded" << endl;
+	else
+	{
+		cerr << "loading model " << filename << " failed" << endl;
+		CleanUp();
+		exit(0);
+	}
+
+	const string bvh_filename = string(model_path + "city.bvh");
+	BvhLoader bvhLoader;
+	bvh = bvhLoader.Load(bvh_filename, sceneEntities);
+
+	if (!bvh)
+	{
+		cerr << "loading bvh " << bvh_filename << " failed" << endl;
+		CleanUp();
+		exit(0);
+	}
+	
+	
+	const string buddhafilename = string(model_path + "hbuddha.dem");
+
+	if (loader->Load(buddhafilename, sceneEntities2))
+		cout << "model " << buddhafilename << " loaded" << endl;
+	else
+	{
+		cerr << "loading model " << buddhafilename << " failed" << endl;
+		CleanUp();
+		exit(0);
+	}
+
+	buddha = sceneEntities2[0];
+
+	Matrix4x4 translation = TranslationMatrix(camera->GetPosition());
+
+	buddha->GetTransform()->SetMatrix(translation);
+
+
+#if 0
+
+	int merged = 0;
+
+	SceneEntity *oldEnt = NULL;
+
+	cout << "merging entities .. " << endl;
+	SceneEntityContainer::const_iterator sit, sit_end = sceneEntities.end();
+
+	for (sit = sceneEntities.begin(); sit < sit_end; ++ sit)
+	{
+		SceneEntity *newEnt = (*sit);
+
+		if (!newEnt->GetTransform()->IsIdentity())
+		{
+			sceneEntities2.push_back(newEnt);
+			continue;
+		}
+
+		if (oldEnt)
+		{
+			EntityMerger merger(newEnt, oldEnt);
+			SceneEntity *ent = merger.Merge();
+
+			sceneEntities2.push_back(ent);
+
+			oldEnt = NULL;
+
+			++ merged;
+		}
+		else
+		{
+			oldEnt = newEnt;
+		}
+	}
+
+	if (oldEnt && oldEnt->GetTransform()->IsIdentity())
+		sceneEntities2.push_back(oldEnt);
+
+	cout << "merged " << merged << " of " << (int)sceneEntities.size() << " entities " << endl;
+#endif
+
+	// set far plane based on scene extent
+	farDist = 10.0f * Magnitude(bvh->GetBox().Diagonal());
+	bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
+
+	camera->SetFar(Magnitude(bvh->GetBox().Diagonal()));
+	
+	InitCg();
+
+	DeferredRenderer::Init(sCgContext);
+	SkyPreetham::Init(sCgContext);
+
+	Vector3 cubeCenter(470.398f, 240.364f, 182.5f);
+	
+	Matrix4x4 transl = TranslationMatrix(cubeCenter);
+	
+
+	SceneEntityContainer dummy;
+	
+	string skyDomeStr(model_path + "sky.dem");
+
+	if (loader->Load(skyDomeStr, dummy))
+		cout << "successfully loaded " << dummy.size() << " scene entities" << endl;
+	else
+	{
+		cerr << "loading file " << skyDomeStr << " failed" << endl;
+
+		CleanUp();
+		exit(0);
+	}
+
+	skyDome = dummy[0];
+
+
+	const float turbitiy = 5.0f;
+	preetham = new SkyPreetham(turbitiy, skyDome);
+
+	// initialize the render traverser
+	traverser = CreateTraverser(camera);
+
+	visualization = new Visualization(bvh, camera, NULL, &state);
+	
+	state.SetRenderPassType(RenderState::FIXED);
+	sceneQuery = new SceneQuery(bvh->GetBox(), traverser);
+
+	// frame time is restarted every frame
+	frameTimer.Start();
+
+	// the rendering loop
+	glutMainLoop();
+
+	// clean up
+	CleanUp();
+
+	return 0;
+}
+
+
+void InitCg(void) 
+{
+	// Setup Cg
+	cgSetErrorCallback(cgErrorCallback);
+
+	// Create cgContext.
+	sCgContext = cgCreateContext();
+
+	// get the best profile for this hardware
+	RenderState::sCgFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
+	cgGLSetOptimalOptions(RenderState::sCgFragmentProfile);
+
+	RenderState::sCgVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
+	cgGLSetOptimalOptions(RenderState::sCgVertexProfile);
+
+	sCgMrtVertexProgram = 
+		cgCreateProgramFromFile(sCgContext, 
+								CG_SOURCE,
+								"src/shaders/mrt.cg", 
+								RenderState::sCgVertexProfile,
+								"vtx",
+								NULL);
+
+	if (sCgMrtVertexProgram != NULL)
+	{
+		cgGLLoadProgram(sCgMrtVertexProgram);
+
+		//sInvViewProjParam = cgGetNamedParameter(sCgMrtVertexProgram, "InvViewProj");
+		Transform3::sModelMatrixParam = cgGetNamedParameter(sCgMrtVertexProgram, "ModelView");
+	}
+
+	RenderState::sCgMrtFragmentTexProgram = 
+		cgCreateProgramFromFile(sCgContext, 
+								CG_SOURCE,
+								"src/shaders/mrt.cg", 
+								RenderState::sCgFragmentProfile,
+								"fragtex",
+								NULL);
+
+	if (RenderState::sCgMrtFragmentTexProgram != NULL)
+	{
+		cgGLLoadProgram(RenderState::sCgMrtFragmentTexProgram);
+
+		sMaxDepthParamTex = cgGetNamedParameter(RenderState::sCgMrtFragmentTexProgram, "maxDepth");
+		sEyePosParamTex = cgGetNamedParameter(RenderState::sCgMrtFragmentTexProgram, "eyePos");
+		RenderState::sTexParam = cgGetNamedParameter(RenderState::sCgMrtFragmentTexProgram, "tex");
+	
+		cgGLSetParameter1f(sMaxDepthParamTex, MAX_DEPTH_CONST / farDist);
+
+		sTLParamTex = cgGetNamedParameter(RenderState::sCgMrtFragmentTexProgram, "tl"); 
+		sTRParamTex = cgGetNamedParameter(RenderState::sCgMrtFragmentTexProgram, "tr"); 
+		sBRParamTex = cgGetNamedParameter(RenderState::sCgMrtFragmentTexProgram, "br"); 
+		sBLParamTex = cgGetNamedParameter(RenderState::sCgMrtFragmentTexProgram, "bl"); 
+	}
+	else
+		cerr << "fragment tex program failed to load" << endl;
+
+	RenderState::sCgMrtFragmentProgram = 
+		cgCreateProgramFromFile(sCgContext, 
+								CG_SOURCE,
+								"src/shaders/mrt.cg", 
+								RenderState::sCgFragmentProfile,
+								"frag",
+								NULL);
+
+	if (RenderState::sCgMrtFragmentProgram != NULL)
+	{
+		cgGLLoadProgram(RenderState::sCgMrtFragmentProgram);
+
+		sMaxDepthParam = cgGetNamedParameter(RenderState::sCgMrtFragmentProgram, "maxDepth");
+		sEyePosParam = cgGetNamedParameter(RenderState::sCgMrtFragmentTexProgram, "eyePos");
+		
+		cgGLSetParameter1f(sMaxDepthParam, MAX_DEPTH_CONST / farDist);
+
+		sTLParam = cgGetNamedParameter(RenderState::sCgMrtFragmentProgram, "tl"); 
+		sTRParam = cgGetNamedParameter(RenderState::sCgMrtFragmentProgram, "tr"); 
+		sBRParam = cgGetNamedParameter(RenderState::sCgMrtFragmentProgram, "br"); 
+		sBLParam = cgGetNamedParameter(RenderState::sCgMrtFragmentProgram, "bl"); 
+	}
+	else
+		cerr << "fragment program failed to load" << endl;
+	
+
+	PrintGLerror("init");
+
+	cout << "cg initialization successful" << endl;
+}
+
+
+void InitFBO()
+{
+	PrintGLerror("fbo start");
+
+	// this fbo basicly stores the scene information we get from standard rendering of a frame
+	// we store colors, normals, positions (for the ssao)
+	fbo = new FrameBufferObject(texWidth, texHeight, FrameBufferObject::DEPTH_32);
+	//fbo = new FrameBufferObject(texWidth, texHeight, FrameBufferObject::DEPTH_24);
+
+	// the diffuse color buffer
+	fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST, ColorBufferObject::FILTER_NEAREST);
+	// the normals buffer
+	fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
+	// the positions buffer
+	//fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
+	fbo->AddColorBuffer(ColorBufferObject::RGB_UBYTE, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
+	// another color buffer
+	fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST, ColorBufferObject::FILTER_NEAREST);
+
+	PrintGLerror("fbo");
+}
+
+
+bool InitFont(void)
+{
+	glEnable(GL_TEXTURE_2D);
+
+	glGenTextures(1, &fontTex);
+	glBindTexture(GL_TEXTURE_2D, fontTex);
+	if (!myfont.Create("data/fonts/verdana.glf", fontTex))
+		return false;
+
+	glDisable(GL_TEXTURE_2D);
+	
+	return true;
+}
+
+
+void InitGLstate() 
+{
+	glClearColor(0.4f, 0.4f, 0.4f, 1.0f);
+	
+	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+	glPixelStorei(GL_PACK_ALIGNMENT,1); 
+	
+	glDepthFunc(GL_LESS);
+	glEnable(GL_DEPTH_TEST);
+
+	glColor3f(1.0f, 1.0f, 1.0f);
+	glShadeModel(GL_SMOOTH);
+	
+	glMaterialf(GL_FRONT, GL_SHININESS, 64);
+	glEnable(GL_NORMALIZE);
+		
+	glDisable(GL_ALPHA_TEST);
+	glAlphaFunc(GL_GEQUAL, 0.5f);
+
+	glFrontFace(GL_CCW);
+	glCullFace(GL_BACK);
+	glEnable(GL_CULL_FACE);
+
+	glDisable(GL_TEXTURE_2D);
+
+	GLfloat ambientColor[] = {0.2, 0.2, 0.2, 1.0};
+	GLfloat diffuseColor[] = {1.0, 0.0, 0.0, 1.0};
+	GLfloat specularColor[] = {0.0, 0.0, 0.0, 1.0};
+
+	glMaterialfv(GL_FRONT, GL_AMBIENT, ambientColor);
+	glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseColor);
+	glMaterialfv(GL_FRONT, GL_SPECULAR, specularColor);
+
+	glDepthFunc(GL_LESS);
+
+	if (!InitFont())
+		cerr << "font creation failed" << endl;
+	else
+		cout << "successfully created font" << endl;
+
+
+	//////////////////////////////
+
+	//GLfloat lmodel_ambient[] = {1.0f, 1.0f, 1.0f, 1.0f};
+	GLfloat lmodel_ambient[] = {0.7f, 0.7f, 0.8f, 1.0f};
+
+	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
+	//glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
+	glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
+	glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SINGLE_COLOR_EXT);
+}
+
+
+void DrawHelpMessage() 
+{
+	const char *message[] = 
+	{
+		"Help information",
+		"",
+		"'F1'           - shows/dismisses this message",
+		"'F2'           - shows/hides bird eye view",
+		"'F3'           - shows/hides bounds (boxes or tight bounds)",
+		"'F4',          - shows/hides parameters",
+		"'F5'           - shows/hides statistics",
+		"'F6',          - toggles between fly/walkmode",
+		"'F7',          - cycles throw render modes",
+		"'F8',          - enables/disables ambient occlusion (only deferred)",
+		"'F9',          - shows pure algorithm render time (using glFinish)",
+		"'SPACE'        - cycles through occlusion culling algorithms",
+		"",
+		"'MOUSE LEFT'        - turn left/right, move forward/backward",
+		"'MOUSE RIGHT'       - turn left/right, move forward/backward",
+		"'MOUSE MIDDLE'      - move up/down, left/right",
+		"'CURSOR UP/DOWN'    - move forward/backward",
+		"'CURSOR LEFT/RIGHT' - turn left/right",
+		"",
+		"'-'/'+'        - decreases/increases max batch size",
+		"'1'/'2'        - downward/upward motion",
+		"'3'/'4'        - decreases/increases triangles per virtual bvh leaf (sets bvh depth)",
+		"'5'/'6'        - decreases/increases assumed visible frames",
+		"",
+		"'R'            - use render queue",
+		"'B'            - use tight bounds",
+		"'M'            - use multiqueries",
+		"'O'            - use CHC optimization (geometry queries for leaves)",
+		0,
+	};
+	
+	
+	glColor4f(0.0f, 1.0f , 0.0f, 0.2f); // 20% green. 
+
+	glRecti(30, 30, winWidth - 30, winHeight - 30);
+
+	glEnd();
+
+	glColor3f(1.0f, 1.0f, 1.0f);
+	
+	glEnable(GL_TEXTURE_2D);
+	myfont.Begin();
+
+	int x = 40, y = 30;
+
+	for(int i = 0; message[i] != 0; ++ i) 
+	{
+		if(message[i][0] == '\0') 
+		{
+			y += 15;
+		} 
+		else 
+		{
+			myfont.DrawString(message[i], x, winHeight - y);
+			y += 25;
+		}
+	}
+	glDisable(GL_TEXTURE_2D);
+}
+
+
+RenderTraverser *CreateTraverser(Camera *cam)
+{
+	RenderTraverser *tr;
+	
+	bvh->ResetNodeClassifications();
+
+	switch (renderMode)
+	{
+	case RenderTraverser::CULL_FRUSTUM:
+		tr = new FrustumCullingTraverser();
+		break;
+	case RenderTraverser::STOP_AND_WAIT:
+		tr = new StopAndWaitTraverser();
+		break;
+	case RenderTraverser::CHC:
+		tr = new CHCTraverser();
+		break;
+	case RenderTraverser::CHCPLUSPLUS:
+		tr = new CHCPlusPlusTraverser();
+		break;
+	
+	default:
+		tr = new FrustumCullingTraverser();
+	}
+
+	tr->SetCamera(cam);
+	tr->SetHierarchy(bvh);
+	tr->SetRenderQueue(renderQueue);
+	tr->SetRenderState(&state);
+	tr->SetUseOptimization(useOptimization);
+	tr->SetUseRenderQueue(useRenderQueue);
+	tr->SetVisibilityThreshold(threshold);
+	tr->SetAssumedVisibleFrames(assumedVisibleFrames);
+	tr->SetMaxBatchSize(maxBatchSize);
+	tr->SetUseMultiQueries(useMultiQueries);
+	tr->SetUseTightBounds(useTightBounds);
+	tr->SetUseDepthPass((renderMethod == RENDER_DEPTH_PASS) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED));
+	tr->SetRenderQueue(renderQueue);
+
+	return tr;
+}
+
+
+void SetupLighting()
+{
+	glEnable(GL_LIGHT0);
+	glDisable(GL_LIGHT1);
+	
+	Vector3 lightDir = -light->GetDirection();
+
+
+	///////////
+	//-- first light: sunlight
+
+	GLfloat ambient[] = {0.25f, 0.25f, 0.3f, 1.0f};
+	GLfloat diffuse[] = {1.0f, 0.95f, 0.85f, 1.0f};
+	GLfloat specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
+	
+
+	const bool useToneMapping = ((renderMethod == RENDER_DEPTH_PASS_DEFERRED) || (renderMethod == RENDER_DEFERRED)) && useHDR;
+
+	Vector3 sunAmbient;
+	Vector3 sunDiffuse;
+
+	preetham->ComputeSunColor(lightDir, sunAmbient, sunDiffuse, !useToneMapping);
+
+	ambient[0] = sunAmbient.x;
+	ambient[1] = sunAmbient.y;
+	ambient[2] = sunAmbient.z;
+
+	// no tone mapping => scale
+	if (!useToneMapping)
+	{
+		const float maxComponent = sunDiffuse.MaxComponent();
+		sunDiffuse /= maxComponent;
+	}
+
+	diffuse[0] = sunDiffuse.x;
+	diffuse[1] = sunDiffuse.y;
+	diffuse[2] = sunDiffuse.z;
+
+	glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
+	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
+	glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
+
+	GLfloat position[] = {lightDir.x, lightDir.y, lightDir.z, 0.0f};
+	glLightfv(GL_LIGHT0, GL_POSITION, position);
+}
+
+
+void SetupEyeView()
+{
+	// store matrix of last frame
+	oldViewProjMat = viewProjMat;
+
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+	gluPerspective(fov, winAspectRatio, nearDist, farDist);
+
+	glMatrixMode(GL_MODELVIEW);
+	
+	// set up the camera view
+	camera->SetupCameraView();
+
+		
+	/////////////////
+
+	Matrix4x4 matViewing, matProjection;
+
+	camera->GetModelViewMatrix(matViewing);
+	camera->GetProjectionMatrix(matProjection);
+
+	// store matrix for later use
+	viewProjMat = matViewing * matProjection;
+	
+	if ((renderMethod == RENDER_DEFERRED) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
+	{
+		cgGLSetMatrixParameterfc(Transform3::sModelMatrixParam, (const float *)IdentityMatrix().x);
+	}
+}
+
+
+void KeyHorizontalMotion(float shift)
+{
+	Vector3 hvec = -camera->GetDirection();
+	hvec.z = 0;
+
+	Vector3 pos = camera->GetPosition();
+	pos += hvec * shift;
+	
+	camera->SetPosition(pos);
+}
+
+
+void KeyVerticalMotion(float shift)
+{
+	Vector3 uvec = Vector3(0, 0, shift);
+
+	Vector3 pos = camera->GetPosition();
+	pos += uvec;
+	
+	camera->SetPosition(pos);
+}
+
+
+static void ComputeViewVectors(Vector3 &tl, Vector3 &tr, Vector3 &bl, Vector3 &br)
+{
+	Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr;
+
+	camera->ComputePoints(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr);
+
+	bl = Normalize(nbl - fbl);
+	br = Normalize(nbr - fbr);
+	tl = Normalize(ntl - ftl);
+	tr = Normalize(ntr - ftr);
+}
+
+
+void InitDeferredRendering()
+{
+	if (!fbo) InitFBO();
+	fbo->Bind();
+
+	// multisampling does not work with deferred shading
+	glDisable(GL_MULTISAMPLE_ARB);
+
+	state.SetRenderPassType(RenderState::DEFERRED);
+
+	cgGLEnableProfile(RenderState::sCgVertexProfile);
+	cgGLBindProgram(sCgMrtVertexProgram);
+
+	cgGLEnableProfile(RenderState::sCgFragmentProfile);
+	cgGLBindProgram(RenderState::sCgMrtFragmentProgram);
+
+	const Vector3 pos = camera->GetPosition();
+
+	cgGLSetParameter3f(sEyePosParam, pos.x, pos.y, pos.z);
+	cgGLSetParameter3f(sEyePosParamTex, pos.x, pos.y, pos.z);
+
+	Vector3 tl, tr, bl, br;
+	ComputeViewVectors(tl, tr, bl, br);
+
+	cgGLSetParameter3f(sBLParam, bl.x, bl.y, bl.z);
+	cgGLSetParameter3f(sBRParam, br.x, br.y, br.z);
+	cgGLSetParameter3f(sTLParam, tl.x, tl.y, tl.z);
+	cgGLSetParameter3f(sTRParam, tr.x, tr.y, tr.z);
+
+	cgGLSetParameter3f(sBLParamTex, bl.x, bl.y, bl.z);
+	cgGLSetParameter3f(sBRParamTex, br.x, br.y, br.z);
+	cgGLSetParameter3f(sTLParamTex, tl.x, tl.y, tl.z);
+	cgGLSetParameter3f(sTRParamTex, tr.x, tr.y, tr.z);
+
+	// draw to 3 color buffers
+	// a color, normal, and positions buffer
+	if (sCurrentMrtSet == 0)
+	{
+		DeferredRenderer::colorBufferIdx = 0;
+		glDrawBuffers(2, mrt);
+	}
+	else 
+	{
+		DeferredRenderer::colorBufferIdx = 3;
+		glDrawBuffers(2, mrt2);
+	}
+
+	sCurrentMrtSet = 1 - sCurrentMrtSet;
+}
+
+
+// the main rendering loop
+void Display() 
+{	
+	Vector3 oldPos = camera->GetPosition();
+
+	if (leftKeyPressed)
+		camera->Pitch(KeyRotationAngle());
+	if (rightKeyPressed)
+		camera->Pitch(-KeyRotationAngle());
+	if (upKeyPressed)
+		KeyHorizontalMotion(-KeyShift());
+	if (downKeyPressed)
+		KeyHorizontalMotion(KeyShift());
+	if (ascendKeyPressed)
+		KeyVerticalMotion(KeyShift());
+	if (descendKeyPressed)
+		KeyVerticalMotion(-KeyShift());
+
+	// place view on ground
+	if (!flyMode) PlaceViewer(oldPos);
+
+	if (showAlgorithmTime)
+	{
+		glFinish();
+		algTimer.Start();
+	}
+	
+
+
+	if ((!shadowMap || !shadowTraverser) && (showShadowMap || renderLightView))
+	{
+		if (!shadowMap)
+			shadowMap = new ShadowMap(light, shadowSize, bvh->GetBox(), camera);
+
+		if (!shadowTraverser)
+			shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
+
+	}
+
+	
+	// bring eye modelview matrix up-to-date
+	SetupEyeView();
+
+	// hack
+	int oldRenderMethod = renderMethod;
+
+	if (renderLightView)
+		renderMethod = RenderState::FIXED;
+
+	glEnableClientState(GL_VERTEX_ARRAY);
+
+
+	// render with the specified method (forward rendering, forward + depth, deferred)
+	switch (renderMethod)
+	{
+	case RENDER_FIXED:
+	
+		glEnable(GL_MULTISAMPLE_ARB);
+		
+		state.SetRenderPassType(RenderState::FIXED);
+		glEnable(GL_LIGHTING);
+
+		cgGLDisableProfile(RenderState::sCgFragmentProfile);
+		cgGLDisableProfile(RenderState::sCgVertexProfile);
+
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+		glEnableClientState(GL_NORMAL_ARRAY);
+
+		break;
+
+	case RENDER_DEPTH_PASS_DEFERRED:
+
+		glDisable(GL_MULTISAMPLE_ARB);
+		state.SetUseAlphaToCoverage(false);
+
+		state.SetRenderPassType(RenderState::DEPTH_PASS);
+
+		if (!fbo) InitFBO(); fbo->Bind();
+
+		glDrawBuffers(1, mrt);
+
+		cgGLDisableProfile(RenderState::sCgFragmentProfile);
+		cgGLDisableProfile(RenderState::sCgVertexProfile);
+
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+		// the scene is rendered withouth any shading	
+		glShadeModel(GL_FLAT);
+		glDisable(GL_LIGHTING);
+		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+
+		break;
+
+	case RENDER_DEPTH_PASS:
+
+		glEnable(GL_MULTISAMPLE_ARB);
+
+		cgGLDisableProfile(RenderState::sCgFragmentProfile);
+		cgGLDisableProfile(RenderState::sCgVertexProfile);
+
+		state.SetRenderPassType(RenderState::DEPTH_PASS);
+
+		// the scene is rendered withouth any shading	
+		glShadeModel(GL_FLAT);
+		glDisable(GL_LIGHTING);
+	
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+
+		break;
+	
+	case RenderState::DEFERRED:
+
+		if (showShadowMap && !renderLightView)
+			RenderShadowMap(camera->GetFar());
+
+		//glPushAttrib(GL_VIEWPORT_BIT);
+		glViewport(0, 0, texWidth, texHeight);
+
+		InitDeferredRendering();
+		
+		glEnableClientState(GL_NORMAL_ARRAY);
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+		break;
+	}
+
+	glDepthFunc(GL_LESS);
+
+	glDisable(GL_TEXTURE_2D);
+	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+		
+
+	// reset lod levels for current frame
+	LODLevel::InitFrame(camera->GetPosition());
+
+	// set up lights
+	SetupLighting();
+
+
+	if (renderLightView)
+	{
+		// change CHC++ set of state variables (must be done for each change of camera because
+		// otherwise the temporal coherency is broken
+		BvhNode::SetCurrentState(1);
+		shadowMap->RenderShadowView(shadowTraverser, viewProjMat);
+		BvhNode::SetCurrentState(0);
+	}
+	else
+	{
+		// actually render the scene geometry using the specified algorithm
+		traverser->RenderScene();
+		
+		buddha->Render(&state);
+		renderQueue->Apply();
+	}
+
+
+	/////////
+	//-- do the rest of the rendering
+	
+	// reset depth pass and render visible objects
+	if ((renderMethod == RENDER_DEPTH_PASS) ||
+		(renderMethod == RENDER_DEPTH_PASS_DEFERRED))
+	{
+		RenderVisibleObjects();
+	}
+	
+
+	///////////////
+	//-- render sky
+
+	// q: should we render sky after deferred shading? 
+	// this would conveniently solves some issues (e.g, skys without shadows)
+
+	RenderSky();
+
+
+	if ((renderMethod == RENDER_DEFERRED) ||
+		(renderMethod == RENDER_DEPTH_PASS_DEFERRED))
+	{
+		FrameBufferObject::Release();
+
+		cgGLDisableProfile(RenderState::sCgVertexProfile);
+		cgGLDisableProfile(RenderState::sCgFragmentProfile);
+
+		if (!ssaoShader) ssaoShader = 
+			new DeferredRenderer(texWidth, texHeight, camera, farDist / MAX_DEPTH_CONST);
+		
+		DeferredRenderer::SHADING_METHOD shadingMethod;
+
+		if (useAdvancedShading)
+		{
+			if (useGlobIllum)
+				shadingMethod = DeferredRenderer::GI;
+			else
+				shadingMethod = DeferredRenderer::SSAO;
+		}
+		else
+			shadingMethod = DeferredRenderer::DEFAULT;
+
+
+		ssaoShader->SetShadingMethod(shadingMethod);
+		ssaoShader->SetSamplingMethod(samplingMethod);
+		ssaoShader->SetUseTemporalCoherence(useTemporalCoherence);
+
+		ShadowMap *sm = showShadowMap ? shadowMap : NULL;
+		ssaoShader->Render(fbo, oldViewProjMat, viewProjMat, ssaoTempCohFactor, light, useHDR, sm);
+	}
+
+
+	state.SetRenderPassType(RenderState::FIXED);
+	state.Reset();
+
+
+	glDisableClientState(GL_VERTEX_ARRAY);
+	glDisableClientState(GL_NORMAL_ARRAY);
+	
+	renderMethod = oldRenderMethod;
+
+
+	///////////
+
+
+	if (showAlgorithmTime)
+	{
+		glFinish();
+
+		algTime = algTimer.Elapsedms();
+		perfGraph->AddData(algTime);
+
+		perfGraph->Draw();
+	}
+	else
+	{
+		if (visMode) DisplayVisualization();
+	}
+
+	glFlush();
+
+	const bool restart = true;
+	elapsedTime = frameTimer.Elapsedms(restart);
+
+	DisplayStats();
+
+	glutSwapBuffers();
+}
+
+
+#pragma warning( disable : 4100 )
+void KeyBoard(unsigned char c, int x, int y) 
+{
+	switch(c) 
+	{
+	case 27:
+		CleanUp();
+		exit(0);
+		break;
+	case 32: // space
+		renderMode = (renderMode + 1) % RenderTraverser::NUM_TRAVERSAL_TYPES;
+
+		DEL_PTR(traverser);
+		traverser = CreateTraverser(camera);
+
+		if (shadowTraverser)
+		{
+			// shadow traverser has to be recomputed
+			DEL_PTR(shadowTraverser);
+			shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
+		}
+
+		break;
+	case '+':
+		if (maxBatchSize < 10)
+			maxBatchSize = 10;
+		else
+			maxBatchSize += 10;
+
+		traverser->SetMaxBatchSize(maxBatchSize);
+		break;
+	case '-':
+		maxBatchSize -= 10;
+		if (maxBatchSize < 0) maxBatchSize = 1;
+		traverser->SetMaxBatchSize(maxBatchSize);		
+		break;
+	case 'M':
+	case 'm':
+		useMultiQueries = !useMultiQueries;
+		traverser->SetUseMultiQueries(useMultiQueries);
+		break;
+	case '1':
+		descendKeyPressed = true;
+		break;
+	case '2':
+		ascendKeyPressed = true;
+		break;
+	case '3':
+		if (trianglesPerVirtualLeaf >= 100)
+			trianglesPerVirtualLeaf -= 100;
+		bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
+		break;
+	case '4':
+		trianglesPerVirtualLeaf += 100;
+		bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
+		break;
+	case '5':
+		assumedVisibleFrames -= 1;
+		if (assumedVisibleFrames < 1) assumedVisibleFrames = 1;
+		traverser->SetAssumedVisibleFrames(assumedVisibleFrames);
+		break;
+	case '6':
+		assumedVisibleFrames += 1;
+		traverser->SetAssumedVisibleFrames(assumedVisibleFrames);		
+		break;
+	case '7':
+		ssaoTempCohFactor *= 0.5f;
+		break;
+	case '8':
+		ssaoTempCohFactor *= 2.0f;
+		//if (ssaoTempCohFactor > 1.0f) ssaoExpFactor = 1.0f;
+		break;
+	case '9':
+		useLODs = !useLODs;
+		SceneEntity::SetUseLODs(useLODs);
+		break;
+	case 'P':
+	case 'p':
+		samplingMethod = DeferredRenderer::SAMPLING_METHOD((samplingMethod + 1) % 3);
+		cout << "ssao sampling method: " << samplingMethod << endl;
+		break;
+	case 'Y':
+	case 'y':
+		showShadowMap = !showShadowMap;
+		break;
+	case 'g':
+	case 'G':
+		useGlobIllum = !useGlobIllum;
+		break;
+	case 't':
+	case 'T':
+		useTemporalCoherence = !useTemporalCoherence;
+		break;
+	case 'o':
+	case 'O':
+		useOptimization = !useOptimization;
+		traverser->SetUseOptimization(useOptimization);
+		break;
+	case 'a':
+	case 'A':
+		leftKeyPressed = true;
+		break;
+	case 'd':
+	case 'D':
+		rightKeyPressed = true;
+		break;
+	case 'w':
+	case 'W':
+		upKeyPressed = true;
+		break;
+	case 's':
+	case 'S':
+		downKeyPressed = true;
+		break;
+	case 'r':
+	case 'R':
+		useRenderQueue = !useRenderQueue;
+		traverser->SetUseRenderQueue(useRenderQueue);
+		
+		break;
+	case 'b':
+	case 'B':
+		useTightBounds = !useTightBounds;
+		traverser->SetUseTightBounds(useTightBounds);
+		break;
+	case 'l':
+	case 'L':
+		renderLightView = !renderLightView;
+		break;
+	case 'h':
+	case 'H':
+		useHDR = !useHDR;
+		break;
+	default:
+		return;
+	}
+
+	glutPostRedisplay();
+}
+
+
+void SpecialKeyUp(int c, int x, int y) 
+{
+	switch (c) 
+	{
+	case GLUT_KEY_LEFT:
+		leftKeyPressed = false;
+		break;
+	case GLUT_KEY_RIGHT:
+		rightKeyPressed = false;
+		break;
+	case GLUT_KEY_UP:
+		upKeyPressed = false;
+		break;
+	case GLUT_KEY_DOWN:
+		downKeyPressed = false;
+		break;
+	case GLUT_ACTIVE_ALT:
+		altKeyPressed = false;
+		break;
+	default:
+		return;
+	}
+}
+
+
+void KeyUp(unsigned char c, int x, int y) 
+{
+	switch (c) 
+	{
+
+	case 'A':
+	case 'a':
+		leftKeyPressed = false;
+		break;
+	case 'D':
+	case 'd':
+		rightKeyPressed = false;
+		break;
+	case 'W':
+	case 'w':
+		upKeyPressed = false;
+		break;
+	case 'S':
+	case 's':
+		downKeyPressed = false;
+		break;
+	case '1':
+		descendKeyPressed = false;
+		break;
+	case '2':
+		ascendKeyPressed = false;
+		break;
+	
+	default:
+		return;
+	}
+	//glutPostRedisplay();
+}
+
+
+void Special(int c, int x, int y) 
+{
+	switch(c) 
+	{
+	case GLUT_KEY_F1:
+		showHelp = !showHelp;
+		break;
+	case GLUT_KEY_F2:
+		visMode = !visMode;
+		break;
+	case GLUT_KEY_F3:
+		showBoundingVolumes = !showBoundingVolumes;
+		traverser->SetShowBounds(showBoundingVolumes);
+		break;
+	case GLUT_KEY_F4:
+		showOptions = !showOptions;
+		break;
+	case GLUT_KEY_F5:
+		showStatistics = !showStatistics;
+		break;
+	case GLUT_KEY_F6:
+		flyMode = !flyMode;
+		break;
+	case GLUT_KEY_F7:
+
+		renderMethod = (renderMethod + 1) % 4;
+
+		traverser->SetUseDepthPass(
+			(renderMethod == RENDER_DEPTH_PASS) || 
+			(renderMethod == RENDER_DEPTH_PASS_DEFERRED)
+			);
+		
+		break;
+	case GLUT_KEY_F8:
+		useAdvancedShading = !useAdvancedShading;
+
+		break;
+	case GLUT_KEY_F9:
+		showAlgorithmTime = !showAlgorithmTime;
+		break;
+	case GLUT_KEY_F10:
+		moveLight = !moveLight;
+		break;
+	case GLUT_KEY_LEFT:
+		{
+			leftKeyPressed = true;
+			camera->Pitch(KeyRotationAngle());
+		}
+		break;
+	case GLUT_KEY_RIGHT:
+		{
+			rightKeyPressed = true;
+			camera->Pitch(-KeyRotationAngle());
+		}
+		break;
+	case GLUT_KEY_UP:
+		{
+			upKeyPressed = true;
+			KeyHorizontalMotion(KeyShift());
+		}
+		break;
+	case GLUT_KEY_DOWN:
+		{
+			downKeyPressed = true;
+			KeyHorizontalMotion(-KeyShift());
+		}
+		break;
+	default:
+		return;
+
+	}
+
+	glutPostRedisplay();
+}
+
+#pragma warning( default : 4100 )
+
+
+void Reshape(int w, int h) 
+{
+	winAspectRatio = 1.0f;
+
+	glViewport(0, 0, w, h);
+	
+	winWidth = w;
+	winHeight = h;
+
+	if (w) winAspectRatio = (float) w / (float) h;
+
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+
+	gluPerspective(fov, winAspectRatio, nearDist, farDist);
+
+	glMatrixMode(GL_MODELVIEW);
+
+	glutPostRedisplay();
+}
+
+
+void Mouse(int button, int state, int x, int y) 
+{
+	if ((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN))
+	{
+		xEyeBegin = x;
+		yMotionBegin = y;
+
+		glutMotionFunc(LeftMotion);
+	}
+	else if ((button == GLUT_RIGHT_BUTTON) && (state == GLUT_DOWN))
+	{
+		xEyeBegin = x;
+		yEyeBegin = y;
+		yMotionBegin = y;
+
+		if (!moveLight)
+			glutMotionFunc(RightMotion);
+		else
+			glutMotionFunc(RightMotionLight);
+	}
+	else if ((button == GLUT_MIDDLE_BUTTON) && (state == GLUT_DOWN))
+	{
+		horizontalMotionBegin = x;
+		verticalMotionBegin = y;
+		glutMotionFunc(MiddleMotion);
+	}
+
+	glutPostRedisplay();
+}
+
+
+/**	rotation for left/right mouse drag
+	motion for up/down mouse drag
+*/
+void LeftMotion(int x, int y) 
+{
+	Vector3 viewDir = camera->GetDirection();
+	Vector3 pos = camera->GetPosition();
+
+	// don't move in the vertical direction
+	Vector3 horView(viewDir[0], viewDir[1], 0);
+	
+	float eyeXAngle = 0.2f *  M_PI * (xEyeBegin - x) / 180.0;
+
+	camera->Pitch(eyeXAngle);
+
+	pos += horView * (yMotionBegin - y) * 0.2f;
+	
+	camera->SetPosition(pos);
+	
+	xEyeBegin = x;
+	yMotionBegin = y;
+
+	glutPostRedisplay();
+}
+
+
+void RightMotionLight(int x, int y) 
+{
+	float theta = 0.2f * M_PI * (xEyeBegin - x) / 180.0f;
+	float phi = 0.2f * M_PI * (yMotionBegin - y) / 180.0f;
+	
+	Vector3 lightDir = light->GetDirection();
+
+	Matrix4x4 roty = RotationYMatrix(theta);
+	Matrix4x4 rotx = RotationXMatrix(phi);
+
+	lightDir = roty * lightDir;
+	lightDir = rotx * lightDir;
+
+	// normalize to avoid accumulating errors
+	lightDir.Normalize();
+
+	light->SetDirection(lightDir);
+
+	xEyeBegin = x;
+	yMotionBegin = y;
+
+	glutPostRedisplay();
+}
+
+
+/**	rotation for left / right mouse drag
+	motion for up / down mouse drag
+*/
+void RightMotion(int x, int y) 
+{
+	float eyeXAngle = 0.2f *  M_PI * (xEyeBegin - x) / 180.0;
+	float eyeYAngle = -0.2f *  M_PI * (yEyeBegin - y) / 180.0;
+
+	camera->Yaw(eyeYAngle);
+	camera->Pitch(eyeXAngle);
+
+	xEyeBegin = x;
+	yEyeBegin = y;
+
+	glutPostRedisplay();
+}
+
+
+// strafe
+void MiddleMotion(int x, int y) 
+{
+	Vector3 viewDir = camera->GetDirection();
+	Vector3 pos = camera->GetPosition();
+
+	// the 90 degree rotated view vector 
+	// y zero so we don't move in the vertical
+	Vector3 rVec(viewDir[0], viewDir[1], 0);
+	
+	Matrix4x4 rot = RotationZMatrix(M_PI * 0.5f);
+	rVec = rot * rVec;
+	
+	pos -= rVec * (x - horizontalMotionBegin) * 0.1f;
+	pos[2] += (verticalMotionBegin - y) * 0.1f;
+
+	camera->SetPosition(pos);
+
+	horizontalMotionBegin = x;
+	verticalMotionBegin = y;
+
+	glutPostRedisplay();
+}
+
+
+void InitExtensions(void) 
+{
+	GLenum err = glewInit();
+
+	if (GLEW_OK != err) 
+	{
+		// problem: glewInit failed, something is seriously wrong
+		fprintf(stderr,"Error: %s\n", glewGetErrorString(err));
+		exit(1);
+	}
+	if  (!GLEW_ARB_occlusion_query)
+	{
+		printf("I require the GL_ARB_occlusion_query to work.\n");
+		exit(1);
+	}
+}
+
+
+void Begin2D() 
+{
+	glDisable(GL_LIGHTING);
+	glDisable(GL_DEPTH_TEST);
+
+	glMatrixMode(GL_PROJECTION);
+	glPushMatrix();
+	glLoadIdentity();
+
+	gluOrtho2D(0, winWidth, 0, winHeight);
+
+	glMatrixMode(GL_MODELVIEW);
+	glPushMatrix();
+	glLoadIdentity();
+}
+
+
+void End2D() 
+{
+	glMatrixMode(GL_PROJECTION);
+	glPopMatrix();
+
+	glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
+
+	glEnable(GL_LIGHTING);
+	glEnable(GL_DEPTH_TEST);
+}
+
+
+// displays the visualisation of culling algorithm
+void DisplayVisualization()
+{
+	visualization->SetFrameId(traverser->GetCurrentFrameId());
+	
+	Begin2D();
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	glEnable(GL_BLEND);
+	glColor4f(0.0f ,0.0f, 0.0f, 0.5f); 
+
+	glRecti(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth, winHeight);
+	glDisable(GL_BLEND);
+	End2D();
+	
+	
+	AxisAlignedBox3 box = bvh->GetBox();
+
+	const float offs = box.Size().x * 0.3f;
+	
+	Vector3 vizpos = Vector3(box.Min().x, box.Min().y  - box.Size().y * 0.35f, box.Min().z + box.Size().z * 50);
+	
+	visCamera->SetPosition(vizpos);
+	visCamera->ResetPitchAndYaw();
+	
+	glPushAttrib(GL_VIEWPORT_BIT);
+	glViewport(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth / 3, winHeight / 3);
+
+	glMatrixMode(GL_PROJECTION);
+	glPushMatrix();
+
+	glLoadIdentity();
+	
+	glOrtho(-offs, offs, -offs, offs, 0.0f, box.Size().z * 100.0f); 
+
+	glMatrixMode(GL_MODELVIEW);
+	glPushMatrix();
+
+	visCamera->SetupCameraView();
+
+	Matrix4x4 rotZ = RotationZMatrix(-camera->GetPitch());
+	glMultMatrixf((float *)rotZ.x);
+
+	// inverse translation in order to fix current position
+	Vector3 pos = camera->GetPosition();
+	glTranslatef(-pos.x, -pos.y, -pos.z);
+
+
+	GLfloat position[] = {0.8f, 1.0f, 1.5f, 0.0f};
+	glLightfv(GL_LIGHT0, GL_POSITION, position);
+
+	GLfloat position1[] = {bvh->GetBox().Center().x, bvh->GetBox().Max().y, bvh->GetBox().Center().z, 1.0f};
+	glLightfv(GL_LIGHT1, GL_POSITION, position1);
+
+	glClear(GL_DEPTH_BUFFER_BIT);
+
+
+	////////////
+	//-- visualization of the occlusion culling
+
+	visualization->Render();
+
+	
+	// reset previous settings
+	glPopAttrib();
+
+	glMatrixMode(GL_PROJECTION);
+	glPopMatrix();
+	glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
+}
+
+
+// cleanup routine after the main loop
+void CleanUp()
+{
+	DEL_PTR(traverser);
+	DEL_PTR(sceneQuery);
+	DEL_PTR(bvh);
+	DEL_PTR(visualization);
+	DEL_PTR(camera);
+	DEL_PTR(loader);
+	DEL_PTR(renderQueue);
+	DEL_PTR(perfGraph);
+
+	DEL_PTR(fbo);
+	DEL_PTR(ssaoShader);
+
+	if (sCgMrtVertexProgram)
+		cgDestroyProgram(sCgMrtVertexProgram);
+	if (RenderState::sCgMrtFragmentProgram)
+		cgDestroyProgram(RenderState::sCgMrtFragmentProgram);
+	if (RenderState::sCgMrtFragmentTexProgram)
+		cgDestroyProgram(RenderState::sCgMrtFragmentTexProgram);
+	
+	if (sCgContext)
+		cgDestroyContext(sCgContext);
+}
+
+
+// this function inserts a dezimal point after each 1000
+void CalcDecimalPoint(string &str, int d, int len)
+{
+	static vector<int> numbers;
+	numbers.clear();
+
+	static string shortStr;
+	shortStr.clear();
+
+	static char hstr[100];
+
+	while (d != 0)
+	{
+		numbers.push_back(d % 1000);
+		d /= 1000;
+	}
+
+	// first element without leading zeros
+	if (numbers.size() > 0)
+	{
+		sprintf(hstr, "%d", numbers.back());
+		shortStr.append(hstr);
+	}
+	
+	for (int i = (int)numbers.size() - 2; i >= 0; i--)
+	{
+		sprintf(hstr, ",%03d", numbers[i]);
+		shortStr.append(hstr);
+	}
+
+	int dif = len - (int)shortStr.size();
+
+	for (int i = 0; i < dif; ++ i)
+	{
+		str += " ";
+	}
+
+	str.append(shortStr);
+}
+
+
+void DisplayStats()
+{
+	static char msg[9][300];
+
+	static double frameTime = elapsedTime;
+	static double renderTime = algTime;
+
+	const float expFactor = 0.1f;
+
+	// if some strange render time spike happened in this frame => don't count
+	if (elapsedTime < 500) frameTime = elapsedTime * expFactor + (1.0f - expFactor) * elapsedTime;
+	
+	static float rTime = 1000.0f;
+
+	if (showAlgorithmTime)
+	{
+		if (algTime < 500) renderTime = algTime * expFactor + (1.0f - expFactor) * renderTime;
+	}
+
+	accumulatedTime += elapsedTime;
+
+	if (accumulatedTime > 500) // update every fraction of a second
+	{	
+		accumulatedTime = 0;
+
+		if (frameTime) fps = 1e3f / (float)frameTime;
+
+		rTime = renderTime;
+
+		if (renderLightView && shadowTraverser)
+		{
+			renderedTriangles = shadowTraverser->GetStats().mNumRenderedTriangles;
+			renderedObjects = shadowTraverser->GetStats().mNumRenderedGeometry;
+			renderedNodes = shadowTraverser->GetStats().mNumRenderedNodes;
+		}
+		else if (showShadowMap && shadowTraverser)
+		{
+			renderedNodes = traverser->GetStats().mNumRenderedNodes + shadowTraverser->GetStats().mNumRenderedNodes;
+			renderedObjects = traverser->GetStats().mNumRenderedGeometry + shadowTraverser->GetStats().mNumRenderedGeometry;
+			renderedTriangles = traverser->GetStats().mNumRenderedTriangles + shadowTraverser->GetStats().mNumRenderedTriangles;
+		}
+		else
+		{
+			renderedTriangles = traverser->GetStats().mNumRenderedTriangles;
+			renderedObjects = traverser->GetStats().mNumRenderedGeometry;
+			renderedNodes = traverser->GetStats().mNumRenderedNodes;
+		}
+
+		traversedNodes = traverser->GetStats().mNumTraversedNodes;
+		frustumCulledNodes = traverser->GetStats().mNumFrustumCulledNodes;
+		queryCulledNodes = traverser->GetStats().mNumQueryCulledNodes;
+		issuedQueries = traverser->GetStats().mNumIssuedQueries;
+		stateChanges = traverser->GetStats().mNumStateChanges;
+		numBatches = traverser->GetStats().mNumBatches;
+	}
+
+
+	Begin2D();
+
+	glEnable(GL_BLEND);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+	if (showHelp)
+	{	
+		DrawHelpMessage();
+	}
+	else
+	{
+		if (showOptions)
+		{
+			glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
+			glRecti(5, winHeight - 95, winWidth * 2 / 3 - 5, winHeight - 5);
+		}
+
+		if (showStatistics)
+		{
+			glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
+			glRecti(5, winHeight - 165, winWidth * 2 / 3 - 5, winHeight - 100);
+		}
+
+		glEnable(GL_TEXTURE_2D);
+
+		myfont.Begin();
+
+		if (showOptions)
+		{
+			glColor3f(0.0f, 1.0f, 0.0f);
+
+			int i = 0;
+
+			static char *renderMethodStr[] = {"forward", "depth pass + forward", "deferred shading", "depth pass + deferred"};
+	
+			sprintf(msg[i ++], "multiqueries: %d, tight bounds: %d, render queue: %d", 
+							useMultiQueries, useTightBounds, useRenderQueue);
+
+			sprintf(msg[i ++], "render technique: %s, SSAO: %d", renderMethodStr[renderMethod], useAdvancedShading);
+
+			sprintf(msg[i ++], "triangles per virtual leaf: %5d", trianglesPerVirtualLeaf);
+
+			sprintf(msg[i ++], "assumed visible frames: %4d, max batch size: %4d", 
+				assumedVisibleFrames, maxBatchSize);
+
+			for (int j = 0; j < 4; ++ j)
+				myfont.DrawString(msg[j], 10.0f, winHeight - 5 - j * 20);
+		}
+
+		if (showStatistics)
+		{
+			glColor3f(1.0f, 1.0f, 0.0f);
+
+			string objStr, totalObjStr;
+			string triStr, totalTriStr;
+
+			int len = 10;
+			CalcDecimalPoint(objStr, renderedObjects, len);
+			CalcDecimalPoint(totalObjStr, (int)loader->GetNumEntities(), len);
+
+			CalcDecimalPoint(triStr, renderedTriangles, len);
+			CalcDecimalPoint(totalTriStr, bvh->GetBvhStats().mTriangles, len);
+
+			int i = 4;
+
+			if (0)
+			{
+				sprintf(msg[i ++], "rendered: %s of %s objects, %s of %s triangles", 
+					objStr.c_str(), totalObjStr.c_str(), triStr.c_str(), totalTriStr.c_str()); 
+			}
+			else
+			{
+				sprintf(msg[i ++], "rendered: %6d of %6d nodes, %s of %s triangles", 
+					renderedNodes, bvh->GetNumVirtualNodes(), triStr.c_str(), totalTriStr.c_str()); 
+			}
+
+			sprintf(msg[i ++], "traversed: %5d, frustum culled: %5d, query culled: %5d",
+				traversedNodes, frustumCulledNodes, queryCulledNodes);
+
+			sprintf(msg[i ++], "issued queries: %5d, state changes: %5d, render batches: %5d", 
+				issuedQueries, stateChanges, numBatches);
+
+			for (int j = 4; j < 7; ++ j)
+				myfont.DrawString(msg[j], 10.0f, winHeight - (j + 1) * 20);
+		}
+
+		glColor3f(1.0f, 1.0f, 1.0f);
+		static char *alg_str[] = {"Frustum Cull", "Stop and Wait", "CHC", "CHC ++"};
+		
+		if (!showAlgorithmTime)
+				sprintf(msg[7], "%s:  %6.1f fps", alg_str[renderMode], fps);
+		else
+			sprintf(msg[7], "%s:  %6.1f ms", alg_str[renderMode], rTime);
+		
+		myfont.DrawString(msg[7], 1.3f, 690.0f, 760.0f);//, top_color, bottom_color);
+		
+		//sprintf(msg[8], "algorithm time: %6.1f ms", rTime);
+		//myfont.DrawString(msg[8], 720.0f, 730.0f);		
+	}
+
+	glDisable(GL_BLEND);
+	glDisable(GL_TEXTURE_2D);
+
+	End2D();
+}	
+
+
+void RenderSky()
+{
+	cgGLEnableProfile(RenderState::sCgVertexProfile);
+
+	if ((renderMethod == RENDER_DEFERRED) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
+		state.SetRenderPassType(RenderState::DEFERRED);
+
+	const bool useToneMapping = ((renderMethod == RENDER_DEPTH_PASS_DEFERRED) || (renderMethod == RENDER_DEFERRED)) && useHDR;
+
+	preetham->RenderSkyDome(-light->GetDirection(), camera, &state, !useToneMapping);
+
+	cgGLDisableProfile(RenderState::sCgVertexProfile);
+	cgGLDisableProfile(RenderState::sCgFragmentProfile);
+}
+
+
+// render visible object from depth pass
+void RenderVisibleObjects()
+{
+	if (renderMethod == RENDER_DEPTH_PASS_DEFERRED)
+	{
+		if (showShadowMap && !renderLightView)
+		{
+			float minVisibleDist = min(camera->GetFar(), traverser->GetMaxVisibleDistance());
+			RenderShadowMap(minVisibleDist);
+		}
+
+		glDisable(GL_LIGHTING);
+		glViewport(0, 0, texWidth, texHeight);
+
+		InitDeferredRendering();
+	}
+	else
+	{
+		glEnable(GL_LIGHTING);
+		state.SetRenderPassType(RenderState::FIXED);
+	}
+
+	glShadeModel(GL_SMOOTH);
+	glEnableClientState(GL_NORMAL_ARRAY);
+
+	// draw all objects that have exactly the same depth as the current sample
+	glDepthFunc(GL_LEQUAL);
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+	glClear(GL_COLOR_BUFFER_BIT);
+
+	state.SetUseAlphaToCoverage(true);
+	state.Reset();
+
+	//cout << "visible: " << (int)traverser->GetVisibleObjects().size() << endl;
+
+	SceneEntityContainer::const_iterator sit, 
+		sit_end = traverser->GetVisibleObjects().end();
+
+	for (sit = traverser->GetVisibleObjects().begin(); sit != sit_end; ++ sit)
+	{
+		renderQueue->Enqueue(*sit);
+	}
+
+	renderQueue->Apply();
+
+	glDepthFunc(GL_LESS);
+	state.Reset();
+
+	PrintGLerror("visibleobjects");
+}
+
+
+void PlaceViewer(const Vector3 &oldPos)
+{
+	Vector3 playerPos = camera->GetPosition();
+	bool validIntersect = sceneQuery->CalcIntersection(playerPos);
+
+	if (validIntersect) 
+		// && ((playerPos.z - oldPos.z) < bvh->GetBox().Size(2) * 1e-1f))
+	{
+		camera->SetPosition(playerPos);
+	}
+}
+
+
+void RenderShadowMap(float newfar)
+{
+	cgGLDisableProfile(RenderState::sCgFragmentProfile);
+	cgGLDisableProfile(RenderState::sCgVertexProfile);
+
+	glDisableClientState(GL_NORMAL_ARRAY);
+
+	state.SetRenderPassType(RenderState::DEPTH_PASS);
+	state.LockCullFaceEnabled(true);
+	state.SetUseAlphaToCoverage(false);
+
+	// change CHC++ set of state variables 
+	// this must be done for each change of camera because
+	// otherwise the temporal coherency is broken
+	BvhNode::SetCurrentState(1);
+
+	// hack: temporarily change camera far plane
+	camera->SetFar(newfar);
+	glDisable(GL_CULL_FACE);
+	
+	// the scene is rendered withouth any shading	
+	shadowMap->ComputeShadowMap(shadowTraverser, viewProjMat);
+
+	glEnable(GL_CULL_FACE);
+	camera->SetFar(farDist);
+
+	state.SetUseAlphaToCoverage(true);
+	state.LockCullFaceEnabled(false);
+
+	glEnableClientState(GL_NORMAL_ARRAY);
+
+	// change back state
+	BvhNode::SetCurrentState(0);
+}
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp	(revision 3019)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp	(revision 3020)
@@ -1771,17 +1771,18 @@
 	DEL_PTR(renderQueue);
 	DEL_PTR(perfGraph);
-
 	DEL_PTR(fbo);
 	DEL_PTR(ssaoShader);
-
 	DEL_PTR(light);
 	DEL_PTR(visCamera);
-
 	DEL_PTR(preetham);
-
-	if (sCgMrtVertexProgram)
+	DEL_PTR(shadowMap);
+	DEL_PTR(shadowTraverser);
+
+	if (sCgMrtVertexProgram) 
 		cgDestroyProgram(sCgMrtVertexProgram);
+
 	if (RenderState::sCgMrtFragmentProgram)
 		cgDestroyProgram(RenderState::sCgMrtFragmentProgram);
+
 	if (RenderState::sCgMrtFragmentTexProgram)
 		cgDestroyProgram(RenderState::sCgMrtFragmentTexProgram);
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/DeferredRenderer.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/DeferredRenderer.cpp	(revision 3019)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/DeferredRenderer.cpp	(revision 3020)
@@ -1293,5 +1293,5 @@
 
 	const float minKey = 0.09f;
-	const float maxKey = 0.45f;
+	const float maxKey = 0.36f;
 
 	const float lightIntensity = DotProd(-light->GetDirection(), Vector3::UNIT_Z());
