source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp @ 3235

Revision 3235, 60.6 KB checked in by mattausch, 15 years ago (diff)
Line 
1// chcdemo.cpp : Defines the entry point for the console application.
2//
3
4
5#include "common.h"
6
7#ifdef _CRT_SET
8        #define _CRTDBG_MAP_ALLOC
9        #include <stdlib.h>
10        #include <crtdbg.h>
11
12        // redefine new operator
13        #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
14        #define new DEBUG_NEW
15#endif
16
17#include <math.h>
18#include <time.h>
19#include "glInterface.h"
20
21
22#include "RenderTraverser.h"
23#include "SceneEntity.h"
24#include "Vector3.h"
25#include "Matrix4x4.h"
26#include "ResourceManager.h"
27#include "Bvh.h"
28#include "Camera.h"
29#include "Geometry.h"
30#include "BvhLoader.h"
31#include "FrustumCullingTraverser.h"
32#include "StopAndWaitTraverser.h"
33#include "CHCTraverser.h"
34#include "CHCPlusPlusTraverser.h"
35#include "Visualization.h"
36#include "RenderState.h"
37#include "Timer/PerfTimer.h"
38#include "SceneQuery.h"
39#include "RenderQueue.h"
40#include "Material.h"
41#include "glfont2.h"
42#include "PerformanceGraph.h"
43#include "Environment.h"
44#include "Halton.h"
45#include "Transform3.h"
46#include "SampleGenerator.h"
47#include "FrameBufferObject.h"
48#include "DeferredRenderer.h"
49#include "ShadowMapping.h"
50#include "Light.h"
51#include "SceneEntityConverter.h"
52#include "SkyPreetham.h"
53#include "Texture.h"
54#include "ShaderManager.h"
55#include "MotionPath.h"
56#include "ShaderProgram.h"
57#include "Shape.h"
58#include "WalkThroughRecorder.h"
59#include "StatsWriter.h"
60#include "Halton.h"
61
62
63using namespace std;
64using namespace CHCDemoEngine;
65
66
67/// the environment for the program parameter
68static Environment env;
69
70
71GLuint fontTex;
72/// the fbo used for MRT
73FrameBufferObject *fbo = NULL;
74/// the renderable scene geometry
75SceneEntityContainer sceneEntities;
76/// the dynamic objects in the scene
77SceneEntityContainer dynamicObjects;
78// traverses and renders the hierarchy
79RenderTraverser *traverser = NULL;
80/// the hierarchy
81Bvh *bvh = NULL;
82/// handles scene loading
83ResourceManager *resourceManager = NULL;
84/// handles scene loading
85ShaderManager *shaderManager = NULL;
86/// the scene camera
87PerspectiveCamera *camera = NULL;
88/// the scene camera
89PerspectiveCamera *visCamera = NULL;
90/// the visualization
91Visualization *visualization = NULL;
92/// the current render renderState
93RenderState renderState;
94/// the rendering algorithm
95int renderMode = RenderTraverser::CHCPLUSPLUS;
96/// eye near plane distance
97const float nearDist = 0.2f;
98//const float nearDist = 1.0f;
99/// eye far plane distance
100float farDist = 1e6f;
101/// the field of view
102const float fov = 50.0f;
103
104SceneQuery *sceneQuery = NULL;
105RenderQueue *renderQueue = NULL;
106/// traverses and renders the hierarchy
107RenderTraverser *shadowTraverser = NULL;
108/// the skylight + skydome model
109SkyPreetham *preetham = NULL;
110
111MotionPath *motionPath = NULL;
112/// max depth where candidates for tighter bounds are searched
113int maxDepthForTestingChildren = 3;
114
115bool ssaoUseFullResolution = false;
116
117/// store the frames as tga
118bool recordFrames = false;
119/// record the taken path
120bool recordPath = false;
121/// replays the recorded path
122bool replayPath = false;
123/// frame number for replay
124int currentReplayFrame = -1;
125
126string recordedFramesSuffix("frames");
127string statsFilename("stats");
128
129/// the walkThroughRecorder
130WalkThroughRecorder *walkThroughRecorder = NULL;
131WalkThroughPlayer *walkThroughPlayer = NULL;
132StatsWriter *statsWriter = NULL;
133
134bool makeSnapShot = false;
135
136
137/// the technique used for rendering
138enum RenderTechnique
139{
140        FORWARD,
141        DEFERRED,
142        DEPTH_PASS
143};
144
145
146/// the used render type for this render pass
147enum RenderMethod
148{
149        RENDER_FORWARD,
150        RENDER_DEPTH_PASS,
151        RENDER_DEFERRED,
152        RENDER_DEPTH_PASS_DEFERRED,
153        RENDER_NUM_RENDER_TYPES
154};
155
156/// one of four possible render methods
157int renderMethod = RENDER_FORWARD;
158
159static int winWidth = 1024;
160static int winHeight = 768;
161static float winAspectRatio = 1.0f;
162
163/// these values get scaled with the frame rate
164static float keyForwardMotion = 30.0f;
165static float keyRotation = 1.5f;
166
167/// elapsed time in milliseconds
168double elapsedTime = 1000.0;
169double algTime = 1000.0;
170double accumulatedTime = 1000.0;
171float fps = 1e3f;
172float turbitity = 5.0f;
173
174// ssao parameters
175float ssaoKernelRadius = 1e-8f;
176float ssaoSampleIntensity = 0.2f;
177float ssaoFilterRadius = 12.0f;
178float ssaoTempCohFactor = 255.0;
179bool sortSamples = true;
180
181int shadowSize = 2048;
182
183/// the hud font
184glfont::GLFont myfont;
185
186// rendertexture
187int texWidth = 1024;
188int texHeight = 768;
189
190int renderedObjects = 0;
191int renderedNodes = 0;
192int renderedTriangles = 0;
193
194int issuedQueries = 0;
195int traversedNodes = 0;
196int frustumCulledNodes = 0;
197int queryCulledNodes = 0;
198int stateChanges = 0;
199int numBatches = 0;
200
201// mouse navigation renderState
202int xEyeBegin = 0;
203int yEyeBegin = 0;
204int yMotionBegin = 0;
205int verticalMotionBegin = 0;
206int horizontalMotionBegin = 0;
207
208bool leftKeyPressed = false;
209bool rightKeyPressed = false;
210bool upKeyPressed = false;
211bool downKeyPressed = false;
212bool descendKeyPressed = false;
213bool ascendKeyPressed = false;
214bool leftStrafeKeyPressed = false;
215bool rightStrafeKeyPressed = false;
216
217bool altKeyPressed = false;
218
219bool showHelp = false;
220bool showStatistics = false;
221bool showOptions = true;
222bool showBoundingVolumes = false;
223bool visMode = false;
224
225bool useOptimization = false;
226bool useTightBounds = true;
227bool useRenderQueue = true;
228bool useMultiQueries = true;
229bool flyMode = true;
230
231bool useGlobIllum = false;
232bool useTemporalCoherence = true;
233bool showAlgorithmTime = false;
234
235bool useFullScreen = false;
236bool useLODs = true;
237bool moveLight = false;
238
239bool useAdvancedShading = false;
240bool showShadowMap = false;
241bool renderLightView = false;
242bool useHDR = true;
243bool useAntiAliasing = true;
244bool useLenseFlare = true;
245
246PerfTimer frameTimer, algTimer;
247/// the performance graph window
248PerformanceGraph *perfGraph = NULL;
249
250int sCurrentMrtSet = 0;
251
252static Matrix4x4 invTrafo = IdentityMatrix();
253
254
255//////////////
256//-- algorithm parameters
257
258/// the pixel threshold where a node is still considered invisible
259/// (should be zero for conservative visibility)
260int threshold;
261int assumedVisibleFrames = 10;
262int maxBatchSize = 50;
263int trianglesPerVirtualLeaf = INITIAL_TRIANGLES_PER_VIRTUAL_LEAVES;
264
265//////////////
266
267enum {CAMERA_PASS = 0, LIGHT_PASS = 1};
268
269
270//DeferredRenderer::SAMPLING_METHOD samplingMethod = DeferredRenderer::SAMPLING_POISSON;
271DeferredRenderer::SAMPLING_METHOD samplingMethod = DeferredRenderer::SAMPLING_QUADRATIC;
272
273ShadowMap *shadowMap = NULL;
274DirectionalLight *light = NULL;
275DeferredRenderer *deferredShader = NULL;
276
277
278SceneEntity *buddha = NULL;
279SceneEntity *skyDome = NULL;
280SceneEntity *sunBox = NULL;
281
282GLuint sunQuery = 0;
283
284
285////////////////////
286//--- function forward declarations
287
288void InitExtensions();
289void InitGLstate();
290
291void DisplayVisualization();
292/// destroys all allocated resources
293void CleanUp();
294void SetupEyeView();
295void SetupLighting();
296void DisplayStats();
297/// draw the help screen
298void DrawHelpMessage();
299/// render the sky dome
300void RenderSky();
301/// render the objects found visible in the depth pass
302void RenderVisibleObjects();
303
304int TestSunVisible();
305
306void Begin2D();
307void End2D();
308/// the main loop
309void MainLoop();
310
311void KeyBoard(unsigned char c, int x, int y);
312void Special(int c, int x, int y);
313void KeyUp(unsigned char c, int x, int y);
314void SpecialKeyUp(int c, int x, int y);
315void Reshape(int w, int h);
316void Mouse(int button, int renderState, int x, int y);
317void LeftMotion(int x, int y);
318void RightMotion(int x, int y);
319void MiddleMotion(int x, int y);
320void KeyHorizontalMotion(float shift);
321void KeyVerticalMotion(float shift);
322/// returns the string representation of a number with the decimal points
323void CalcDecimalPoint(string &str, int d);
324/// Creates the traversal method (vfc, stopandwait, chc, chc++)
325RenderTraverser *CreateTraverser(PerspectiveCamera *cam);
326/// place the viewer on the floor plane
327void PlaceViewer(const Vector3 &oldPos);
328// initialise the frame buffer objects
329void InitFBO();
330/// changes the sunlight direction
331void RightMotionLight(int x, int y);
332/// render the shader map
333void RenderShadowMap(float newfar);
334/// function that touches each material once in order to accelarate render queue
335void PrepareRenderQueue();
336/// loads the specified model
337void LoadModel(const string &model, SceneEntityContainer &entities);
338
339inline float KeyRotationAngle() { return keyRotation * elapsedTime * 1e-3f; }
340inline float KeyShift() { return keyForwardMotion * elapsedTime * 1e-3f; }
341
342void CreateAnimation();
343
344SceneQuery *GetOrCreateSceneQuery();
345
346
347// new view projection matrix of the camera
348static Matrix4x4 viewProjMat = IdentityMatrix();
349// the old view projection matrix of the camera
350static Matrix4x4 oldViewProjMat = IdentityMatrix();
351
352
353
354static void PrintGLerror(char *msg)
355{
356        GLenum errCode;
357        const GLubyte *errStr;
358       
359        if ((errCode = glGetError()) != GL_NO_ERROR)
360        {
361                errStr = gluErrorString(errCode);
362                fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg);
363        }
364}
365
366
367int main(int argc, char* argv[])
368{
369#ifdef _CRT_SET
370        //Now just call this function at the start of your program and if you're
371        //compiling in debug mode (F5), any leaks will be displayed in the Output
372        //window when the program shuts down. If you're not in debug mode this will
373        //be ignored. Use it as you will!
374        //note: from GDNet Direct [3.8.04 - 3.14.04] void detectMemoryLeaks() {
375
376        _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);
377        _CrtSetReportMode(_CRT_ASSERT,_CRTDBG_MODE_FILE);
378        _CrtSetReportFile(_CRT_ASSERT,_CRTDBG_FILE_STDERR);
379#endif
380
381        cout << "=== reading environment file ===" << endl << endl;
382
383        int returnCode = 0;
384
385        Vector3 camPos(.0f, .0f, .0f);
386        Vector3 camDir(.0f, 1.0f, .0f);
387        Vector3 lightDir(-0.8f, 1.0f, -0.7f);
388
389        cout << "=== reading environment file ===" << endl << endl;
390
391        const string envFileName = "default.env";
392        if (!env.Read(envFileName))
393        {
394                cerr << "loading environment " << envFileName << " failed!" << endl;
395        }
396        else
397        {
398                env.GetIntParam(string("assumedVisibleFrames"), assumedVisibleFrames);
399                env.GetIntParam(string("maxBatchSize"), maxBatchSize);
400                env.GetIntParam(string("trianglesPerVirtualLeaf"), trianglesPerVirtualLeaf);
401                env.GetIntParam(string("winWidth"), winWidth);
402                env.GetIntParam(string("winHeight"), winHeight);
403                env.GetIntParam(string("shadowSize"), shadowSize);
404                env.GetIntParam(string("maxDepthForTestingChildren"), maxDepthForTestingChildren);
405
406                env.GetFloatParam(string("keyForwardMotion"), keyForwardMotion);
407                env.GetFloatParam(string("keyRotation"), keyRotation);
408                env.GetFloatParam(string("tempCohFactor"), ssaoTempCohFactor);
409                env.GetFloatParam(string("turbitity"), turbitity);
410               
411                env.GetVectorParam(string("camPosition"), camPos);
412                env.GetVectorParam(string("camDirection"), camDir);
413                env.GetVectorParam(string("lightDirection"), lightDir);
414
415                env.GetBoolParam(string("useFullScreen"), useFullScreen);
416                env.GetBoolParam(string("useLODs"), useLODs);
417                env.GetBoolParam(string("useHDR"), useHDR);
418                env.GetBoolParam(string("useAA"), useAntiAliasing);
419                env.GetBoolParam(string("useLenseFlare"), useLenseFlare);
420                env.GetBoolParam(string("useAdvancedShading"), useAdvancedShading);
421
422                env.GetIntParam(string("renderMethod"), renderMethod);
423
424                env.GetFloatParam(string("ssaoKernelRadius"), ssaoKernelRadius);
425                env.GetFloatParam(string("ssaoSampleIntensity"), ssaoSampleIntensity);
426                env.GetBoolParam(string("ssaoUseFullResolution"), ssaoUseFullResolution);
427
428                env.GetStringParam(string("recordedFramesSuffix"), recordedFramesSuffix);
429                env.GetStringParam(string("statsFilename"), statsFilename);
430
431                //env.GetStringParam(string("modelPath"), model_path);
432                //env.GetIntParam(string("numSssaoSamples"), numSsaoSamples);
433
434                texWidth = winWidth;
435                texHeight = winHeight;
436
437                cout << "assumedVisibleFrames: " << assumedVisibleFrames << endl;
438                cout << "maxBatchSize: " << maxBatchSize << endl;
439                cout << "trianglesPerVirtualLeaf: " << trianglesPerVirtualLeaf << endl;
440
441                cout << "keyForwardMotion: " << keyForwardMotion << endl;
442                cout << "keyRotation: " << keyRotation << endl;
443                cout << "winWidth: " << winWidth << endl;
444                cout << "winHeight: " << winHeight << endl;
445                cout << "useFullScreen: " << useFullScreen << endl;
446                cout << "useLODs: " << useLODs << endl;
447                cout << "camPosition: " << camPos << endl;
448                cout << "shadow size: " << shadowSize << endl;
449                cout << "render method: " << renderMethod << endl;
450                cout << "use antialiasing: " << useAntiAliasing << endl;
451                cout << "use lense flare: " << useLenseFlare << endl;
452                cout << "use advanced shading: " << useAdvancedShading << endl;
453                cout << "turbitity: " << turbitity << endl;
454                cout << "temporal coherence: " << ssaoTempCohFactor << endl;
455                cout << "sample intensity: " << ssaoSampleIntensity << endl;
456                cout << "kernel radius: " << ssaoKernelRadius << endl;
457                cout << "ssao full resolution: " << ssaoUseFullResolution << endl;
458                cout << "recorded frames suffix: " << recordedFramesSuffix << endl;
459                cout << "stats filename: " << statsFilename << endl;
460
461                //cout << "model path: " << model_path << endl;
462                cout << "**** end parameters ****" << endl << endl;
463        }
464
465        ///////////////////////////
466
467        camera = new PerspectiveCamera(winWidth / winHeight, fov);
468        camera->SetNear(nearDist);
469        camera->SetFar(1000);
470
471        camera->SetDirection(camDir);
472        camera->SetPosition(camPos);
473
474        visCamera = new PerspectiveCamera(winWidth / winHeight, fov);
475        visCamera->SetNear(0.0f);
476        visCamera->Yaw(.5 * M_PI);
477
478        // create a new light
479        light = new DirectionalLight(lightDir, RgbaColor(1, 1, 1, 1), RgbaColor(1, 1, 1, 1));
480        // the render queue for material sorting
481        renderQueue = new RenderQueue(&renderState);
482
483        glutInitWindowSize(winWidth, winHeight);
484        glutInit(&argc, argv);
485        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE);
486        //glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
487        //glutInitDisplayString("samples=2");
488
489        SceneEntity::SetUseLODs(useLODs);
490
491        if (!useFullScreen)
492        {
493                glutCreateWindow("FriendlyCulling");
494        }
495        else
496        {
497                glutGameModeString( "1024x768:32@75" );
498                glutEnterGameMode();
499        }
500
501        glutDisplayFunc(MainLoop);
502        glutKeyboardFunc(KeyBoard);
503        glutSpecialFunc(Special);
504        glutReshapeFunc(Reshape);
505        glutMouseFunc(Mouse);
506        glutIdleFunc(MainLoop);
507        glutKeyboardUpFunc(KeyUp);
508        glutSpecialUpFunc(SpecialKeyUp);
509        glutIgnoreKeyRepeat(true);
510
511        // initialise gl graphics
512        InitExtensions();
513        InitGLstate();
514
515        glEnable(GL_MULTISAMPLE_ARB);
516        glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
517
518        LeftMotion(0, 0);
519        MiddleMotion(0, 0);
520
521        perfGraph = new PerformanceGraph(1000);
522
523        resourceManager = ResourceManager::GetSingleton();
524        shaderManager = ShaderManager::GetSingleton();
525
526
527        ///////////
528        //-- load the static scene geometry
529
530        LoadModel("city.dem", sceneEntities);
531
532
533        //////////
534        //-- load some dynamic stuff
535
536        //resourceManager->mUseNormalMapping = true;
537        //resourceManager->mUseNormalMapping = false;
538
539        resourceManager->mUseSpecialColors = true;
540
541        //LoadModel("fisch.dem", dynamicObjects);
542        LoadModel("hbuddha.dem", dynamicObjects);
543
544        //LoadModel("venusm.dem", dynamicObjects);
545        //LoadModel("camel.dem", dynamicObjects);
546        //LoadModel("toyplane2.dem", dynamicObjects);
547        //LoadModel("elephal.dem", dynamicObjects);
548
549        resourceManager->mUseNormalMapping = false;
550        resourceManager->mUseSpecialColors = false;
551
552        buddha = dynamicObjects.back();
553       
554        const Vector3 sceneCenter(470.398f, 240.364f, 181.7f);
555        //const Vector3 sceneCenter(470.398f, 240.364f, 180.3);
556       
557        Matrix4x4 transl = TranslationMatrix(sceneCenter);
558        buddha->GetTransform()->SetMatrix(transl);
559
560        for (int i = 0; i < 10; ++ i)
561        {
562                SceneEntity *ent = new SceneEntity(*buddha);
563                resourceManager->AddSceneEntity(ent);
564
565                Vector3 offs = Vector3::ZERO();
566
567                offs.x = RandomValue(.0f, 50.0f);
568                offs.y = RandomValue(.0f, 50.0f);
569
570                Vector3 newPos = sceneCenter + offs;
571
572                transl = TranslationMatrix(newPos);
573                Transform3 *transform = resourceManager->CreateTransform(transl);
574
575                ent->SetTransform(transform);
576                dynamicObjects.push_back(ent);
577        }
578
579
580        //LoadModel("vienna_full_hp.dem", dynamicObjects);
581        //dynamicObjects.back()->GetTransform()->SetMatrix(transl);
582
583
584        ///////////
585        //-- load the associated static bvh
586
587        const string bvh_filename = string(model_path + "city.bvh");
588
589        BvhLoader bvhLoader;
590        bvh = bvhLoader.Load(bvh_filename, sceneEntities, dynamicObjects, maxDepthForTestingChildren);
591
592        if (!bvh)
593        {
594                cerr << "loading bvh " << bvh_filename << " failed" << endl;
595                CleanUp();
596                exit(0);
597        }
598
599        /// set the depth of the bvh depending on the triangles per leaf node
600        bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
601
602        // set far plane based on scene extent
603        farDist = 10.0f * Magnitude(bvh->GetBox().Diagonal());
604        camera->SetFar(farDist);
605
606
607        //////////////////
608        //-- setup the skydome model
609
610        LoadModel("sky.dem", sceneEntities);
611        skyDome = sceneEntities.back();
612
613        /// the turbitity of the sky (from clear to hazy, use <3 for clear sky)
614        preetham = new SkyPreetham(turbitity, skyDome);
615
616        CreateAnimation();
617
618
619        //////////////////////////
620        //-- a bounding box representing the sun pos in order to test visibility
621
622        Transform3 *trafo = resourceManager->CreateTransform(IdentityMatrix());
623
624        // make it slightly bigger to simulate sun diameter
625        const float size = 25.0f;
626        AxisAlignedBox3 sbox(Vector3(-size), Vector3(size));
627
628        SceneEntityConverter conv;
629
630        // toto clean up material
631        Material *mat = resourceManager->CreateMaterial();
632
633        mat->GetTechnique(0)->SetDepthWriteEnabled(false);
634        mat->GetTechnique(0)->SetColorWriteEnabled(false);
635
636        sunBox = conv.ConvertBox(sbox, mat, trafo);
637       
638        resourceManager->AddSceneEntity(sunBox);
639
640        /// create single occlusion query that handles sun visibility
641        glGenQueriesARB(1, &sunQuery);
642
643
644        //////////
645        //-- initialize the traversal algorithm
646
647        traverser = CreateTraverser(camera);
648       
649        // the bird-eye visualization
650        visualization = new Visualization(bvh, camera, NULL, &renderState);
651
652        // this function assign the render queue bucket ids of the materials in beforehand
653        // => probably less overhead for new parts of the scene that are not yet assigned
654        PrepareRenderQueue();
655        /// forward rendering is the default
656        renderState.SetRenderTechnique(FORWARD);
657        // frame time is restarted every frame
658        frameTimer.Start();
659
660        Halton::TestHalton(7, 1);
661        Halton::TestHalton(7, 2);
662
663        HaltonSequence::TestHalton(15, 2);
664        HaltonSequence::TestHalton(15, 1);
665
666        Halton::TestPrime();
667
668        // the rendering loop
669        glutMainLoop();
670       
671        // clean up
672        CleanUp();
673       
674        return 0;
675}
676
677
678void InitFBO()
679{
680        PrintGLerror("fbo start");
681
682        // this fbo basicly stores the scene information we get from standard rendering of a frame
683        // we store diffuse colors, eye space depth and normals
684        fbo = new FrameBufferObject(texWidth, texHeight, FrameBufferObject::DEPTH_32);
685
686        // the diffuse color buffer
687        fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, ColorBufferObject::FILTER_NEAREST);
688        // the normals buffer
689        //fbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
690        fbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
691        // a rgb buffer which could hold material properties
692        //fbo->AddColorBuffer(ColorBufferObject::RGB_UBYTE, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
693        // buffer holding the difference vector to the old frame
694        fbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
695        // another color buffer
696        fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, ColorBufferObject::FILTER_NEAREST);
697
698        for (int i = 0; i < 4; ++ i)
699        {
700                FrameBufferObject::InitBuffer(fbo, i);
701        }
702
703        PrintGLerror("init fbo");
704}
705
706
707bool InitFont(void)
708{
709        glEnable(GL_TEXTURE_2D);
710
711        glGenTextures(1, &fontTex);
712        glBindTexture(GL_TEXTURE_2D, fontTex);
713
714        if (!myfont.Create("data/fonts/verdana.glf", fontTex))
715                return false;
716
717        glDisable(GL_TEXTURE_2D);
718       
719        return true;
720}
721
722
723void InitGLstate()
724{
725        glClearColor(0.4f, 0.4f, 0.4f, 1.0f);
726       
727        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
728        glPixelStorei(GL_PACK_ALIGNMENT,1);
729       
730        glDepthFunc(GL_LESS);
731        glEnable(GL_DEPTH_TEST);
732
733        glColor3f(1.0f, 1.0f, 1.0f);
734        glShadeModel(GL_SMOOTH);
735       
736        glMaterialf(GL_FRONT, GL_SHININESS, 64);
737        glEnable(GL_NORMALIZE);
738               
739        glDisable(GL_ALPHA_TEST);
740        glAlphaFunc(GL_GEQUAL, 0.5f);
741
742        glFrontFace(GL_CCW);
743        glCullFace(GL_BACK);
744        glEnable(GL_CULL_FACE);
745
746        glDisable(GL_TEXTURE_2D);
747
748        GLfloat ambientColor[] = {0.2, 0.2, 0.2, 1.0};
749        GLfloat diffuseColor[] = {1.0, 0.0, 0.0, 1.0};
750        GLfloat specularColor[] = {0.0, 0.0, 0.0, 1.0};
751
752        glMaterialfv(GL_FRONT, GL_AMBIENT, ambientColor);
753        glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseColor);
754        glMaterialfv(GL_FRONT, GL_SPECULAR, specularColor);
755
756        glDepthFunc(GL_LESS);
757
758        if (!InitFont())
759                cerr << "font creation failed" << endl;
760        else
761                cout << "successfully created font" << endl;
762
763
764        //////////////////////////////
765
766        //GLfloat lmodel_ambient[] = {1.0f, 1.0f, 1.0f, 1.0f};
767        GLfloat lmodel_ambient[] = {0.7f, 0.7f, 0.8f, 1.0f};
768
769        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
770        //glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
771        glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
772        glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SINGLE_COLOR_EXT);
773}
774
775
776void DrawHelpMessage()
777{
778        const char *message[] =
779        {
780                "Help information",
781                "",
782                "'F1'           - shows/dismisses this message",
783                "'F2'           - shows/hides bird eye view",
784                "'F3'           - shows/hides bounds (boxes or tight bounds)",
785                "'F4',          - shows/hides parameters",
786                "'F5'           - shows/hides statistics",
787                "'F6',          - toggles between fly/walkmode",
788                "'F7',          - cycles throw render modes",
789                "'F8',          - enables/disables ambient occlusion (only deferred)",
790                "'F9',          - shows pure algorithm render time (using glFinish)",
791                "'SPACE'        - cycles through occlusion culling algorithms",
792                "",
793                "'MOUSE LEFT'        - turn left/right, move forward/backward",
794                "'MOUSE RIGHT'       - turn left/right, move forward/backward",
795                "'MOUSE MIDDLE'      - move up/down, left/right",
796                "'CURSOR UP/DOWN'    - move forward/backward",
797                "'CURSOR LEFT/RIGHT' - turn left/right",
798                "",
799                "'-'/'+'        - decreases/increases max batch size",
800                "'1'/'2'        - downward/upward motion",
801                "'3'/'4'        - decreases/increases triangles per virtual bvh leaf (sets bvh depth)",
802                "'5'/'6'        - decreases/increases assumed visible frames",
803                "",
804                "'R'            - use render queue",
805                "'B'            - use tight bounds",
806                "'M'            - use multiqueries",
807                "'O'            - use CHC optimization (geometry queries for leaves)",
808                0,
809        };
810       
811       
812        glColor4f(0.0f, 1.0f , 0.0f, 0.2f); // 20% green.
813
814        glRecti(30, 30, winWidth - 30, winHeight - 30);
815
816        glEnd();
817
818        glColor3f(1.0f, 1.0f, 1.0f);
819       
820        glEnable(GL_TEXTURE_2D);
821        myfont.Begin();
822
823        int x = 40, y = 30;
824
825        for(int i = 0; message[i] != 0; ++ i)
826        {
827                if(message[i][0] == '\0')
828                {
829                        y += 15;
830                }
831                else
832                {
833                        myfont.DrawString(message[i], x, winHeight - y);
834                        y += 25;
835                }
836        }
837        glDisable(GL_TEXTURE_2D);
838}
839
840
841RenderTraverser *CreateTraverser(PerspectiveCamera *cam)
842{
843        RenderTraverser *tr;
844       
845        switch (renderMode)
846        {
847        case RenderTraverser::CULL_FRUSTUM:
848                tr = new FrustumCullingTraverser();
849                break;
850        case RenderTraverser::STOP_AND_WAIT:
851                tr = new StopAndWaitTraverser();
852                break;
853        case RenderTraverser::CHC:
854                tr = new CHCTraverser();
855                break;
856        case RenderTraverser::CHCPLUSPLUS:
857                tr = new CHCPlusPlusTraverser();
858                break;
859       
860        default:
861                tr = new FrustumCullingTraverser();
862        }
863
864        tr->SetCamera(cam);
865        tr->SetHierarchy(bvh);
866        tr->SetRenderQueue(renderQueue);
867        tr->SetRenderState(&renderState);
868        tr->SetUseOptimization(useOptimization);
869        tr->SetUseRenderQueue(useRenderQueue);
870        tr->SetVisibilityThreshold(threshold);
871        tr->SetAssumedVisibleFrames(assumedVisibleFrames);
872        tr->SetMaxBatchSize(maxBatchSize);
873        tr->SetUseMultiQueries(useMultiQueries);
874        tr->SetUseTightBounds(useTightBounds);
875        tr->SetUseDepthPass((renderMethod == RENDER_DEPTH_PASS) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED));
876        tr->SetRenderQueue(renderQueue);
877        tr->SetShowBounds(showBoundingVolumes);
878
879        bvh->ResetNodeClassifications();
880
881
882        return tr;
883}
884
885/** Setup sunlight
886*/
887void SetupLighting()
888{
889        glEnable(GL_LIGHT0);
890        glDisable(GL_LIGHT1);
891       
892        Vector3 lightDir = -light->GetDirection();
893
894
895        ///////////
896        //-- first light: sunlight
897
898        GLfloat ambient[] = {0.25f, 0.25f, 0.3f, 1.0f};
899        GLfloat diffuse[] = {1.0f, 0.95f, 0.85f, 1.0f};
900        GLfloat specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
901       
902
903        const bool useHDRValues =
904                ((renderMethod == RENDER_DEPTH_PASS_DEFERRED) ||
905                 (renderMethod == RENDER_DEFERRED)) && useHDR;
906
907
908        Vector3 sunAmbient;
909        Vector3 sunDiffuse;
910
911#if 1
912        preetham->ComputeSunColor(lightDir, sunAmbient, sunDiffuse, !useHDRValues);
913
914        ambient[0] = sunAmbient.x;
915        ambient[1] = sunAmbient.y;
916        ambient[2] = sunAmbient.z;
917
918        diffuse[0] = sunDiffuse.x;
919        diffuse[1] = sunDiffuse.y;
920        diffuse[2] = sunDiffuse.z;
921
922#else
923       
924        ambient[0] = .2f;
925        ambient[1] = .2f;
926        ambient[2] = .2f;
927
928        diffuse[0] = 1.0f;
929        diffuse[1] = 1.0f;
930        diffuse[2] = 1.0f;
931
932#endif
933
934        glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
935        glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
936        glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
937
938        GLfloat position[] = {lightDir.x, lightDir.y, lightDir.z, 0.0f};
939        glLightfv(GL_LIGHT0, GL_POSITION, position);
940}
941
942
943void SetupEyeView()
944{
945        // store matrix of last frame
946        oldViewProjMat = viewProjMat;
947
948        camera->SetupViewProjection();
949
950
951        /////////////////
952        //-- compute view projection matrix and store for later use
953
954        Matrix4x4 matViewing, matProjection;
955
956        camera->GetModelViewMatrix(matViewing);
957        camera->GetProjectionMatrix(matProjection);
958
959        viewProjMat = matViewing * matProjection;
960}
961
962
963void KeyHorizontalMotion(float shift)
964{
965        Vector3 hvec = -camera->GetDirection();
966        hvec.z = 0;
967
968        Vector3 pos = camera->GetPosition();
969        pos += hvec * shift;
970       
971        camera->SetPosition(pos);
972}
973
974
975void KeyVerticalMotion(float shift)
976{
977        Vector3 uvec = Vector3(0, 0, shift);
978
979        Vector3 pos = camera->GetPosition();
980        pos += uvec;
981       
982        camera->SetPosition(pos);
983}
984
985
986void KeyStrafe(float shift)
987{
988        Vector3 viewDir = camera->GetDirection();
989        Vector3 pos = camera->GetPosition();
990
991        // the 90 degree rotated view vector
992        // z zero so we don't move in the vertical
993        Vector3 rVec(viewDir[0], viewDir[1], 0);
994
995        Matrix4x4 rot = RotationZMatrix(M_PI * 0.5f);
996        rVec = rot * rVec;
997        pos += rVec * shift;
998
999        camera->SetPosition(pos);
1000}
1001
1002
1003/** Initialize the deferred rendering pass.
1004*/
1005void InitDeferredRendering()
1006{
1007        if (!fbo) InitFBO();
1008        fbo->Bind();
1009
1010        // multisampling does not work with deferred shading
1011        glDisable(GL_MULTISAMPLE_ARB);
1012        renderState.SetRenderTechnique(DEFERRED);
1013
1014
1015        // draw to 3 render targets
1016        if (sCurrentMrtSet == 0)
1017        {
1018                DeferredRenderer::colorBufferIdx = 0;
1019                glDrawBuffers(3, mrt);
1020        }
1021        else
1022        {
1023                DeferredRenderer::colorBufferIdx = 3;
1024                glDrawBuffers(3, mrt2);
1025        }
1026
1027        sCurrentMrtSet = 1 - sCurrentMrtSet;
1028}
1029
1030
1031/** the main rendering loop
1032*/
1033void MainLoop()
1034{       
1035        Matrix4x4 oldTrafo = buddha->GetTransform()->GetMatrix();
1036        Vector3 buddhaPos = motionPath->GetCurrentPosition();
1037        Matrix4x4 trafo = TranslationMatrix(buddhaPos);
1038       
1039        buddha->GetTransform()->SetMatrix(trafo);
1040
1041#if TODO
1042        /*for (int i = 0; i < 10; ++ i)
1043        {
1044                SceneEntity *ent = dynamicObjects[i];
1045                Vector3 newPos = ent->GetWorldCenter();
1046
1047                if (GetOrCreateSceneQuery()->CalcIntersection(newPos))
1048                {
1049                        Matrix4x4 mat = TranslationMatrix(newPos - ent->GetCenter());
1050                        ent->GetTransform()->SetMatrix(mat);
1051                }
1052        }*/
1053#endif
1054
1055
1056        /////////////////////////
1057        //-- update animations
1058
1059        //const float rotAngle = M_PI * 1e-3f;
1060        const float rotAngle = 1.0f * M_PI / 180.0f;
1061
1062        Matrix4x4 rotMatrix = RotationZMatrix(rotAngle);
1063        dynamicObjects[1]->GetTransform()->MultMatrix(rotMatrix);
1064
1065        motionPath->Move(0.01f);
1066
1067
1068
1069        /////////////
1070
1071        static Vector3 oldPos = camera->GetPosition();
1072        static Vector3 oldDir = camera->GetDirection();
1073
1074        if (leftKeyPressed)
1075                camera->Pitch(KeyRotationAngle());
1076        if (rightKeyPressed)
1077                camera->Pitch(-KeyRotationAngle());
1078        if (upKeyPressed)
1079                KeyHorizontalMotion(-KeyShift());
1080        if (downKeyPressed)
1081                KeyHorizontalMotion(KeyShift());
1082        if (ascendKeyPressed)
1083                KeyVerticalMotion(KeyShift());
1084        if (descendKeyPressed)
1085                KeyVerticalMotion(-KeyShift());
1086        if (leftStrafeKeyPressed)
1087                KeyStrafe(KeyShift());
1088        if (rightStrafeKeyPressed)
1089                KeyStrafe(-KeyShift());
1090
1091
1092        // place view on ground
1093        if (!flyMode) PlaceViewer(oldPos);
1094
1095        if (showAlgorithmTime)
1096        {
1097                glFinish();
1098                algTimer.Start();
1099        }
1100       
1101        // don't allow replay on record
1102        if (replayPath && !recordPath)
1103        {
1104                if (!walkThroughPlayer)
1105                        walkThroughPlayer = new WalkThroughPlayer("frames.log");
1106               
1107                ++ currentReplayFrame;
1108
1109                // reset if end of walkthrough is reached
1110                if (!walkThroughPlayer->ReadNextFrame(camera))
1111                {
1112                        currentReplayFrame = -1;
1113                        replayPath = false;
1114                }
1115        }
1116
1117        if ((!shadowMap || !shadowTraverser) && (showShadowMap || renderLightView))
1118        {
1119                if (!shadowMap)
1120                        shadowMap = new ShadowMap(light, shadowSize, bvh->GetBox(), camera);
1121
1122                if (!shadowTraverser)
1123                        shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
1124
1125        }
1126       
1127        // bring eye modelview matrix up-to-date
1128        SetupEyeView();
1129       
1130        // set frame related parameters for GPU programs
1131        GPUProgramParameters::InitFrame(camera, light);
1132
1133        if (recordPath)
1134        {
1135                if (!walkThroughRecorder)
1136                        walkThroughRecorder = new WalkThroughRecorder("frames.log");
1137               
1138                if ((Distance(oldPos, camera->GetPosition()) > 1e-6f) ||
1139                        (DotProd(oldDir, camera->GetDirection()) < 1.0f - 1e-6f))
1140                {
1141                        walkThroughRecorder->WriteFrame(camera);
1142                }
1143        }
1144
1145        // hack: store current rendering method and restore later
1146        int oldRenderMethod = renderMethod;
1147        // for rendering the light view, we use forward rendering
1148        if (renderLightView) renderMethod = FORWARD;
1149
1150        /// enable vbo vertex array
1151        glEnableClientState(GL_VERTEX_ARRAY);
1152
1153        // render with the specified method (forward rendering, forward + depth, deferred)
1154        switch (renderMethod)
1155        {
1156        case RENDER_FORWARD:
1157       
1158                glEnable(GL_MULTISAMPLE_ARB);
1159                renderState.SetRenderTechnique(FORWARD);
1160               
1161                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1162                glEnableClientState(GL_NORMAL_ARRAY);
1163                break;
1164
1165        case RENDER_DEPTH_PASS_DEFERRED:
1166
1167                glDisable(GL_MULTISAMPLE_ARB);
1168                renderState.SetUseAlphaToCoverage(false);
1169                renderState.SetRenderTechnique(DEPTH_PASS);
1170
1171                if (!fbo) InitFBO();
1172                fbo->Bind();
1173                // render to single depth texture
1174                glDrawBuffers(1, mrt);
1175                // clear buffer once
1176                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1177
1178                // the scene is rendered withouth any shading
1179                // (should be handled by render renderState)
1180                glShadeModel(GL_FLAT);
1181                break;
1182
1183        case RENDER_DEPTH_PASS:
1184
1185                glEnable(GL_MULTISAMPLE_ARB);
1186                renderState.SetRenderTechnique(DEPTH_PASS);
1187
1188                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1189
1190                // the scene is rendered withouth any shading
1191                // (should be handled by render renderState)
1192                glShadeModel(GL_FLAT);
1193                break;
1194       
1195        case RENDER_DEFERRED:
1196
1197                if (showShadowMap && !renderLightView)
1198                        RenderShadowMap(camera->GetFar());
1199
1200                //glPushAttrib(GL_VIEWPORT_BIT);
1201                glViewport(0, 0, texWidth, texHeight);
1202
1203                InitDeferredRendering();
1204               
1205                glEnableClientState(GL_NORMAL_ARRAY);
1206                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1207                break;
1208        }
1209
1210        glDepthFunc(GL_LESS);
1211        glDisable(GL_TEXTURE_2D);
1212        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1213               
1214
1215        // set proper lod levels for current frame using current eye point
1216        LODLevel::InitFrame(camera->GetPosition());
1217        // set up sunlight
1218        SetupLighting();
1219
1220
1221        if (renderLightView)
1222        {
1223                // change CHC++ set of renderState variables:
1224                // must be done for each change of camera because otherwise
1225                // the temporal coherency is broken
1226                BvhNode::SetCurrentState(LIGHT_PASS);
1227                shadowMap->RenderShadowView(shadowTraverser, viewProjMat);
1228                BvhNode::SetCurrentState(CAMERA_PASS);
1229        }
1230        else
1231        {
1232                // actually render the scene geometry using the specified algorithm
1233                traverser->RenderScene();
1234        }
1235
1236
1237        /////////
1238        //-- do the rest of the rendering
1239       
1240        // reset depth pass and render visible objects
1241        if ((renderMethod == RENDER_DEPTH_PASS) ||
1242                (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
1243        {
1244                RenderVisibleObjects();
1245        }
1246
1247        const bool useDeferred =
1248                ((renderMethod == RENDER_DEFERRED) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED));
1249
1250        // if no lense flare => just set sun to invisible
1251        const int sunVisiblePixels = useLenseFlare  &&  useDeferred ? TestSunVisible() : 0;
1252
1253
1254        ///////////////
1255        //-- render sky
1256
1257        // q: should we render sky after deferred shading?
1258        // this would conveniently solves some issues (e.g, skys without shadows)
1259
1260        RenderSky();
1261
1262
1263        //////////////////////////////
1264
1265        if (useDeferred)
1266        {
1267                FrameBufferObject::Release();
1268
1269                if (!deferredShader) deferredShader =
1270                        new DeferredRenderer(texWidth, texHeight, camera, ssaoUseFullResolution);
1271               
1272                DeferredRenderer::SHADING_METHOD shadingMethod;
1273
1274                if (useAdvancedShading)
1275                {
1276                        if (useGlobIllum)
1277                                shadingMethod = DeferredRenderer::GI;
1278                        else
1279                                shadingMethod = DeferredRenderer::SSAO;
1280                }
1281                else
1282                {
1283                        shadingMethod = DeferredRenderer::DEFAULT;
1284                }
1285
1286                static int snapShotIdx = 0;
1287
1288                deferredShader->SetSunVisiblePixels(sunVisiblePixels);
1289                deferredShader->SetShadingMethod(shadingMethod);
1290                deferredShader->SetSamplingMethod(samplingMethod);
1291                deferredShader->SetKernelRadius(ssaoKernelRadius);
1292                deferredShader->SetSampleIntensity(ssaoSampleIntensity);
1293                deferredShader->SetSsaoFilterRadius(ssaoFilterRadius);
1294                deferredShader->SetUseTemporalCoherence(useTemporalCoherence);
1295                deferredShader->SetSortSamples(sortSamples);
1296
1297                if (recordFrames && replayPath)
1298                        deferredShader->SetSaveFrame(recordedFramesSuffix, currentReplayFrame);
1299                else if (makeSnapShot)
1300                        deferredShader->SetSaveFrame("snap", snapShotIdx ++);           
1301                else
1302                        deferredShader->SetSaveFrame("", -1);           
1303
1304                //if (makeSnapShot) makeSnapShot = false;
1305
1306                ShadowMap *sm = showShadowMap ? shadowMap : NULL;
1307                deferredShader->Render(fbo, ssaoTempCohFactor, light, useHDR, useAntiAliasing, sm);
1308        }
1309
1310
1311        renderState.SetRenderTechnique(FORWARD);
1312        renderState.Reset();
1313
1314
1315        glDisableClientState(GL_VERTEX_ARRAY);
1316        glDisableClientState(GL_NORMAL_ARRAY);
1317       
1318        renderMethod = oldRenderMethod;
1319
1320
1321        ///////////
1322
1323
1324        if (showAlgorithmTime)
1325        {
1326                glFinish();
1327
1328                algTime = algTimer.Elapsedms();
1329                perfGraph->AddData(algTime);
1330
1331                perfGraph->Draw();
1332        }
1333        else
1334        {
1335                if (visMode) DisplayVisualization();
1336        }
1337
1338        glFlush();
1339
1340        const bool restart = true;
1341        elapsedTime = frameTimer.Elapsedms(restart);
1342
1343        // statistics
1344        DisplayStats();
1345
1346        glutSwapBuffers();
1347
1348        oldPos = camera->GetPosition();
1349        oldDir = camera->GetDirection();
1350}
1351
1352
1353#pragma warning(disable : 4100)
1354void KeyBoard(unsigned char c, int x, int y)
1355{
1356        switch(c)
1357        {
1358        case 27:
1359                // write out current position on exit
1360                Debug << "camPosition=" << camera->GetPosition().x << " " << camera->GetPosition().y << " " << camera->GetPosition().z << endl;
1361                Debug << "camDirection=" << camera->GetDirection().x << " " << camera->GetDirection().y << " " << camera->GetDirection().z << endl;
1362
1363                CleanUp();
1364                exit(0);
1365        case 32: // space
1366                renderMode = (renderMode + 1) % RenderTraverser::NUM_TRAVERSAL_TYPES;
1367
1368                DEL_PTR(traverser);
1369                traverser = CreateTraverser(camera);
1370
1371                if (shadowTraverser)
1372                {
1373                        // shadow traverser has to be recomputed
1374                        DEL_PTR(shadowTraverser);
1375                        shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
1376                }
1377
1378                break;
1379        case '+':
1380                if (maxBatchSize < 10)
1381                        maxBatchSize = 10;
1382                else
1383                        maxBatchSize += 10;
1384
1385                traverser->SetMaxBatchSize(maxBatchSize);
1386                break;
1387        case '-':
1388                maxBatchSize -= 10;
1389                if (maxBatchSize < 0) maxBatchSize = 1;
1390                traverser->SetMaxBatchSize(maxBatchSize);               
1391                break;
1392        case 'M':
1393        case 'm':
1394                useMultiQueries = !useMultiQueries;
1395                traverser->SetUseMultiQueries(useMultiQueries);
1396                break;
1397        case '1':
1398                descendKeyPressed = true;
1399                break;
1400        case '2':
1401                ascendKeyPressed = true;
1402                break;
1403        case '3':
1404                if (trianglesPerVirtualLeaf >= 100) trianglesPerVirtualLeaf -= 100;
1405                bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
1406                break;
1407        case '4':
1408                trianglesPerVirtualLeaf += 100;
1409                bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
1410                break;
1411        case '5':
1412                assumedVisibleFrames -= 1;
1413                if (assumedVisibleFrames < 1) assumedVisibleFrames = 1;
1414                traverser->SetAssumedVisibleFrames(assumedVisibleFrames);
1415                break;
1416        case '6':
1417                assumedVisibleFrames += 1;
1418                traverser->SetAssumedVisibleFrames(assumedVisibleFrames);               
1419                break;
1420        case '7':
1421                ssaoTempCohFactor *= 1.0f / 1.2f;
1422                cout << "new temporal coherence factor: " << ssaoTempCohFactor << endl;
1423                break;
1424        case '8':
1425                ssaoTempCohFactor *= 1.2f;
1426                cout << "new temporal coherence factor: " << ssaoTempCohFactor << endl;
1427                break;
1428        case '9':
1429                ssaoKernelRadius *= 0.8f;
1430                cout << "new ssao kernel radius: " << ssaoKernelRadius << endl;
1431                break;
1432        case '0':
1433                ssaoKernelRadius *= 1.0f / 0.8f;
1434                cout << "new ssao kernel radius: " << ssaoKernelRadius << endl;
1435                break;
1436        case 'n':
1437                ssaoSampleIntensity *= 0.9f;
1438                cout << "new ssao sample intensity: " << ssaoSampleIntensity << endl;
1439                break;
1440        case 'N':
1441                ssaoSampleIntensity *= 1.0f / 0.9f;
1442                cout << "new ssao sample intensity: " << ssaoSampleIntensity << endl;
1443                break;
1444        case 'o':
1445                ssaoFilterRadius *= 0.9f;
1446                cout << "new ssao filter radius: " << ssaoFilterRadius << endl;
1447                break;
1448        case 'O':
1449                ssaoFilterRadius *= 1.0f / 0.9f;
1450                cout << "new ssao filter radius: " << ssaoFilterRadius << endl;
1451                break;
1452        /*      case 'o':
1453        case 'O':
1454                useOptimization = !useOptimization;
1455                // chc optimization of using the objects instead of
1456                // the bounding boxes for querying previously visible nodes
1457                traverser->SetUseOptimization(useOptimization);
1458                break;*/
1459        case 'l':
1460        case 'L':
1461                useLODs = !useLODs;
1462                SceneEntity::SetUseLODs(useLODs);
1463                cout << "using LODs: " << useLODs << endl;
1464                break;
1465        case 'P':
1466        case 'p':
1467                samplingMethod = DeferredRenderer::SAMPLING_METHOD((samplingMethod + 1) % 3);
1468                cout << "ssao sampling method: " << samplingMethod << endl;
1469                break;
1470        case 'Y':
1471        case 'y':
1472                showShadowMap = !showShadowMap;
1473                break;
1474        case 'g':
1475        case 'G':
1476                useGlobIllum = !useGlobIllum;
1477                break;
1478        case 't':
1479        case 'T':
1480                useTemporalCoherence = !useTemporalCoherence;
1481                break;
1482        case 'a':
1483        case 'A':
1484                leftKeyPressed = true;
1485                break;
1486        case 'd':
1487        case 'D':
1488                rightKeyPressed = true;
1489                break;
1490        case 'w':
1491        case 'W':
1492                upKeyPressed = true;
1493                break;
1494        case 's':
1495        case 'S':
1496                downKeyPressed = true;
1497                break;
1498        case 'j':
1499        case 'J':
1500                leftStrafeKeyPressed = true;
1501                break;
1502        case 'k':
1503        case 'K':
1504                rightStrafeKeyPressed = true;
1505                break;
1506        case 'r':
1507        case 'R':
1508                useRenderQueue = !useRenderQueue;
1509                traverser->SetUseRenderQueue(useRenderQueue);
1510                break;
1511        case 'b':
1512        case 'B':
1513                useTightBounds = !useTightBounds;
1514                traverser->SetUseTightBounds(useTightBounds);
1515                break;
1516        case 'v':
1517        case 'V':
1518                renderLightView = !renderLightView;
1519                break;
1520        case 'h':
1521        case 'H':
1522                useHDR = !useHDR;
1523                break;
1524        case 'i':
1525        case 'I':
1526                useAntiAliasing = !useAntiAliasing;
1527                break;
1528        case 'c':
1529        case 'C':
1530                useLenseFlare = !useLenseFlare;
1531                break;
1532        case 'u':
1533        case 'U':
1534                // move light source instead of camera tilt
1535                moveLight = !moveLight;
1536                break;
1537        case '#':
1538                // make a snapshot of the current frame
1539                makeSnapShot = true;
1540                break;
1541        default:
1542                return;
1543        }
1544
1545        glutPostRedisplay();
1546}
1547
1548
1549void SpecialKeyUp(int c, int x, int y)
1550{
1551        switch (c)
1552        {
1553        case GLUT_KEY_LEFT:
1554                leftKeyPressed = false;
1555                break;
1556        case GLUT_KEY_RIGHT:
1557                rightKeyPressed = false;
1558                break;
1559        case GLUT_KEY_UP:
1560                upKeyPressed = false;
1561                break;
1562        case GLUT_KEY_DOWN:
1563                downKeyPressed = false;
1564                break;
1565        case GLUT_ACTIVE_ALT:
1566                altKeyPressed = false;
1567                break;
1568        default:
1569                return;
1570        }
1571}
1572
1573
1574void KeyUp(unsigned char c, int x, int y)
1575{
1576        switch (c)
1577        {
1578
1579        case 'A':
1580        case 'a':
1581                leftKeyPressed = false;
1582                break;
1583        case 'D':
1584        case 'd':
1585                rightKeyPressed = false;
1586                break;
1587        case 'W':
1588        case 'w':
1589                upKeyPressed = false;
1590                break;
1591        case 'S':
1592        case 's':
1593                downKeyPressed = false;
1594                break;
1595        case '1':
1596                descendKeyPressed = false;
1597                break;
1598        case '2':
1599                ascendKeyPressed = false;
1600                break;
1601        case 'j':
1602        case 'J':
1603                leftStrafeKeyPressed = false;
1604                break;
1605        case 'k':
1606        case 'K':
1607                rightStrafeKeyPressed = false;
1608                break;
1609        default:
1610                return;
1611        }
1612        //glutPostRedisplay();
1613}
1614
1615
1616void Special(int c, int x, int y)
1617{
1618        switch(c)
1619        {
1620        case GLUT_KEY_F1:
1621                showHelp = !showHelp;
1622                break;
1623        case GLUT_KEY_F2:
1624                visMode = !visMode;
1625                break;
1626        case GLUT_KEY_F3:
1627                showBoundingVolumes = !showBoundingVolumes;
1628                traverser->SetShowBounds(showBoundingVolumes);
1629                break;
1630        case GLUT_KEY_F4:
1631                showOptions = !showOptions;
1632                break;
1633        case GLUT_KEY_F5:
1634                showStatistics = !showStatistics;
1635                break;
1636        case GLUT_KEY_F6:
1637                flyMode = !flyMode;
1638                break;
1639        case GLUT_KEY_F7:
1640
1641                renderMethod = (renderMethod + 1) % 4;
1642
1643                traverser->SetUseDepthPass(
1644                        (renderMethod == RENDER_DEPTH_PASS) ||
1645                        (renderMethod == RENDER_DEPTH_PASS_DEFERRED)
1646                        );
1647               
1648                break;
1649        case GLUT_KEY_F8:
1650                useAdvancedShading = !useAdvancedShading;
1651                break;
1652        case GLUT_KEY_F9:
1653                showAlgorithmTime = !showAlgorithmTime;
1654                break;
1655        case GLUT_KEY_F10:
1656                replayPath = !replayPath;
1657
1658                if (replayPath)
1659                {
1660                        cout << "replaying path" << endl;
1661                        currentReplayFrame = -1;
1662                }
1663                else
1664                {
1665                        cout << "finished replaying path" << endl;
1666                }
1667
1668                break;
1669        case GLUT_KEY_F11:
1670                recordPath = !recordPath;
1671               
1672                if (recordPath)
1673                {
1674                        cout << "recording path" << endl;
1675                }
1676                else
1677                {
1678                        cout << "finished recording path" << endl;
1679                        // start over with new frame recording next time
1680                        DEL_PTR(walkThroughRecorder);
1681                }
1682
1683                break;
1684        case GLUT_KEY_F12:
1685                recordFrames = !recordFrames;
1686
1687                if (recordFrames)
1688                        cout << "recording frames on replaying" << endl;
1689                else
1690                        cout << "finished recording frames on replaying" << endl;
1691                break;
1692        case GLUT_KEY_LEFT:
1693                {
1694                        leftKeyPressed = true;
1695                        camera->Pitch(KeyRotationAngle());
1696                }
1697                break;
1698        case GLUT_KEY_RIGHT:
1699                {
1700                        rightKeyPressed = true;
1701                        camera->Pitch(-KeyRotationAngle());
1702                }
1703                break;
1704        case GLUT_KEY_UP:
1705                {
1706                        upKeyPressed = true;
1707                        KeyHorizontalMotion(KeyShift());
1708                }
1709                break;
1710        case GLUT_KEY_DOWN:
1711                {
1712                        downKeyPressed = true;
1713                        KeyHorizontalMotion(-KeyShift());
1714                }
1715                break;
1716        default:
1717                return;
1718
1719        }
1720
1721        glutPostRedisplay();
1722}
1723
1724#pragma warning( default : 4100 )
1725
1726
1727void Reshape(int w, int h)
1728{
1729        winAspectRatio = 1.0f;
1730
1731        glViewport(0, 0, w, h);
1732       
1733        winWidth = w;
1734        winHeight = h;
1735
1736        if (w) winAspectRatio = (float) w / (float) h;
1737
1738        glMatrixMode(GL_PROJECTION);
1739        glLoadIdentity();
1740
1741        gluPerspective(fov, winAspectRatio, nearDist, farDist);
1742
1743        glMatrixMode(GL_MODELVIEW);
1744
1745        glutPostRedisplay();
1746}
1747
1748
1749void Mouse(int button, int renderState, int x, int y)
1750{
1751        if ((button == GLUT_LEFT_BUTTON) && (renderState == GLUT_DOWN))
1752        {
1753                xEyeBegin = x;
1754                yMotionBegin = y;
1755
1756                glutMotionFunc(LeftMotion);
1757        }
1758        else if ((button == GLUT_RIGHT_BUTTON) && (renderState == GLUT_DOWN))
1759        {
1760                xEyeBegin = x;
1761                yEyeBegin = y;
1762                yMotionBegin = y;
1763
1764                if (!moveLight)
1765                        glutMotionFunc(RightMotion);
1766                else
1767                        glutMotionFunc(RightMotionLight);
1768        }
1769        else if ((button == GLUT_MIDDLE_BUTTON) && (renderState == GLUT_DOWN))
1770        {
1771                horizontalMotionBegin = x;
1772                verticalMotionBegin = y;
1773                glutMotionFunc(MiddleMotion);
1774        }
1775
1776        glutPostRedisplay();
1777}
1778
1779
1780/**     rotation for left/right mouse drag
1781        motion for up/down mouse drag
1782*/
1783void LeftMotion(int x, int y)
1784{
1785        Vector3 viewDir = camera->GetDirection();
1786        Vector3 pos = camera->GetPosition();
1787
1788        // don't move in the vertical direction
1789        Vector3 horView(viewDir[0], viewDir[1], 0);
1790       
1791        float eyeXAngle = 0.2f *  M_PI * (xEyeBegin - x) / 180.0;
1792
1793        camera->Pitch(eyeXAngle);
1794
1795        pos += horView * (yMotionBegin - y) * 0.2f;
1796       
1797        camera->SetPosition(pos);
1798       
1799        xEyeBegin = x;
1800        yMotionBegin = y;
1801
1802        glutPostRedisplay();
1803}
1804
1805
1806void RightMotionLight(int x, int y)
1807{
1808        float theta = 0.2f * M_PI * (xEyeBegin - x) / 180.0f;
1809        float phi = 0.2f * M_PI * (yMotionBegin - y) / 180.0f;
1810       
1811        Vector3 lightDir = light->GetDirection();
1812
1813        Matrix4x4 roty = RotationYMatrix(theta);
1814        Matrix4x4 rotx = RotationXMatrix(phi);
1815
1816        lightDir = roty * lightDir;
1817        lightDir = rotx * lightDir;
1818
1819        // normalize to avoid accumulating errors
1820        lightDir.Normalize();
1821
1822        light->SetDirection(lightDir);
1823
1824        xEyeBegin = x;
1825        yMotionBegin = y;
1826
1827        glutPostRedisplay();
1828}
1829
1830
1831/**     rotation for left / right mouse drag
1832        motion for up / down mouse drag
1833*/
1834void RightMotion(int x, int y)
1835{
1836        float eyeXAngle = 0.2f *  M_PI * (xEyeBegin - x) / 180.0;
1837        float eyeYAngle = -0.2f *  M_PI * (yEyeBegin - y) / 180.0;
1838
1839        camera->Yaw(eyeYAngle);
1840        camera->Pitch(eyeXAngle);
1841
1842        xEyeBegin = x;
1843        yEyeBegin = y;
1844
1845        glutPostRedisplay();
1846}
1847
1848
1849/** strafe
1850*/
1851void MiddleMotion(int x, int y)
1852{
1853        Vector3 viewDir = camera->GetDirection();
1854        Vector3 pos = camera->GetPosition();
1855
1856        // the 90 degree rotated view vector
1857        // y zero so we don't move in the vertical
1858        Vector3 rVec(viewDir[0], viewDir[1], 0);
1859       
1860        Matrix4x4 rot = RotationZMatrix(M_PI * 0.5f);
1861        rVec = rot * rVec;
1862       
1863        pos -= rVec * (x - horizontalMotionBegin) * 0.1f;
1864        pos[2] += (verticalMotionBegin - y) * 0.1f;
1865
1866        camera->SetPosition(pos);
1867
1868        horizontalMotionBegin = x;
1869        verticalMotionBegin = y;
1870
1871        glutPostRedisplay();
1872}
1873
1874
1875void InitExtensions(void)
1876{
1877        GLenum err = glewInit();
1878
1879        if (GLEW_OK != err)
1880        {
1881                // problem: glewInit failed, something is seriously wrong
1882                fprintf(stderr,"Error: %s\n", glewGetErrorString(err));
1883                exit(1);
1884        }
1885        if  (!GLEW_ARB_occlusion_query)
1886        {
1887                printf("I require the GL_ARB_occlusion_query to work.\n");
1888                exit(1);
1889        }
1890}
1891
1892
1893void Begin2D()
1894{
1895        glDisable(GL_LIGHTING);
1896        glDisable(GL_DEPTH_TEST);
1897
1898        glMatrixMode(GL_PROJECTION);
1899        glPushMatrix();
1900        glLoadIdentity();
1901
1902        gluOrtho2D(0, winWidth, 0, winHeight);
1903
1904        glMatrixMode(GL_MODELVIEW);
1905        glPushMatrix();
1906        glLoadIdentity();
1907}
1908
1909
1910void End2D()
1911{
1912        glMatrixMode(GL_PROJECTION);
1913        glPopMatrix();
1914
1915        glMatrixMode(GL_MODELVIEW);
1916        glPopMatrix();
1917
1918        glEnable(GL_LIGHTING);
1919        glEnable(GL_DEPTH_TEST);
1920}
1921
1922
1923// displays the visualisation of culling algorithm
1924void DisplayVisualization()
1925{
1926        visualization->SetFrameId(traverser->GetCurrentFrameId());
1927       
1928        Begin2D();
1929        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1930        glEnable(GL_BLEND);
1931        glColor4f(0.0f ,0.0f, 0.0f, 0.5f);
1932
1933        glRecti(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth, winHeight);
1934        glDisable(GL_BLEND);
1935        End2D();
1936       
1937       
1938        AxisAlignedBox3 box = bvh->GetBox();
1939
1940        const float offs = box.Size().x * 0.3f;
1941       
1942        Vector3 vizpos = Vector3(box.Min().x, box.Min().y  - box.Size().y * 0.35f, box.Min().z + box.Size().z * 50);
1943       
1944        visCamera->SetPosition(vizpos);
1945        visCamera->ResetPitchAndYaw();
1946       
1947        glPushAttrib(GL_VIEWPORT_BIT);
1948        glViewport(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth / 3, winHeight / 3);
1949
1950        glMatrixMode(GL_PROJECTION);
1951        glPushMatrix();
1952
1953        glLoadIdentity();
1954        glOrtho(-offs, offs, -offs, offs, 0.0f, box.Size().z * 100.0f);
1955
1956        glMatrixMode(GL_MODELVIEW);
1957        glPushMatrix();
1958
1959        visCamera->SetupCameraView();
1960
1961        Matrix4x4 rotZ = RotationZMatrix(-camera->GetPitch());
1962        glMultMatrixf((float *)rotZ.x);
1963
1964        // inverse translation in order to fix current position
1965        Vector3 pos = camera->GetPosition();
1966        glTranslatef(-pos.x, -pos.y, -pos.z);
1967
1968
1969        GLfloat position[] = {0.8f, 1.0f, 1.5f, 0.0f};
1970        glLightfv(GL_LIGHT0, GL_POSITION, position);
1971
1972        GLfloat position1[] = {bvh->GetBox().Center().x, bvh->GetBox().Max().y, bvh->GetBox().Center().z, 1.0f};
1973        glLightfv(GL_LIGHT1, GL_POSITION, position1);
1974
1975        glClear(GL_DEPTH_BUFFER_BIT);
1976
1977
1978        ////////////
1979        //-- visualization of the occlusion culling
1980
1981        visualization->Render(showShadowMap);
1982
1983       
1984        // reset previous settings
1985        glPopAttrib();
1986
1987        glMatrixMode(GL_PROJECTION);
1988        glPopMatrix();
1989        glMatrixMode(GL_MODELVIEW);
1990        glPopMatrix();
1991}
1992
1993
1994// cleanup routine after the main loop
1995void CleanUp()
1996{
1997        DEL_PTR(traverser);
1998        DEL_PTR(sceneQuery);
1999        DEL_PTR(bvh);
2000        DEL_PTR(visualization);
2001        DEL_PTR(camera);
2002        DEL_PTR(renderQueue);
2003        DEL_PTR(perfGraph);
2004        DEL_PTR(fbo);
2005        DEL_PTR(deferredShader);
2006        DEL_PTR(light);
2007        DEL_PTR(visCamera);
2008        DEL_PTR(preetham);
2009        DEL_PTR(shadowMap);
2010        DEL_PTR(shadowTraverser);
2011        DEL_PTR(motionPath);
2012        DEL_PTR(walkThroughRecorder);
2013        DEL_PTR(walkThroughPlayer);
2014        DEL_PTR(statsWriter);
2015
2016        ResourceManager::DelSingleton();
2017        ShaderManager::DelSingleton();
2018
2019        resourceManager = NULL;
2020        shaderManager = NULL;
2021}
2022
2023
2024// this function inserts a dezimal point after each 1000
2025void CalcDecimalPoint(string &str, int d, int len)
2026{
2027        static vector<int> numbers;
2028        numbers.clear();
2029
2030        static string shortStr;
2031        shortStr.clear();
2032
2033        static char hstr[100];
2034
2035        while (d != 0)
2036        {
2037                numbers.push_back(d % 1000);
2038                d /= 1000;
2039        }
2040
2041        // first element without leading zeros
2042        if (numbers.size() > 0)
2043        {
2044                sprintf(hstr, "%d", numbers.back());
2045                shortStr.append(hstr);
2046        }
2047       
2048        for (int i = (int)numbers.size() - 2; i >= 0; i--)
2049        {
2050                sprintf(hstr, ",%03d", numbers[i]);
2051                shortStr.append(hstr);
2052        }
2053
2054        int dif = len - (int)shortStr.size();
2055
2056        for (int i = 0; i < dif; ++ i)
2057        {
2058                str += " ";
2059        }
2060
2061        str.append(shortStr);
2062}
2063
2064
2065void DisplayStats()
2066{
2067        static char msg[9][300];
2068
2069        static double frameTime = elapsedTime;
2070        static double renderTime = algTime;
2071
2072        const float expFactor = 0.1f;
2073
2074        // if some strange render time spike happened in this frame => don't count
2075        if (elapsedTime < 500) frameTime = elapsedTime * expFactor + (1.0f - expFactor) * elapsedTime;
2076       
2077        static float rTime = 1000.0f;
2078
2079        // the render time used up purely for the traversal algorithm using glfinish
2080        if (showAlgorithmTime)
2081        {
2082                if (algTime < 500) renderTime = algTime * expFactor + (1.0f - expFactor) * renderTime;
2083        }
2084
2085        accumulatedTime += elapsedTime;
2086
2087        if (accumulatedTime > 500) // update every fraction of a second
2088        {       
2089                accumulatedTime = 0;
2090
2091                if (frameTime) fps = 1e3f / (float)frameTime;
2092
2093                rTime = renderTime;
2094
2095                if (renderLightView && shadowTraverser)
2096                {
2097                        renderedTriangles = shadowTraverser->GetStats().mNumRenderedTriangles;
2098                        renderedObjects = shadowTraverser->GetStats().mNumRenderedGeometry;
2099                        renderedNodes = shadowTraverser->GetStats().mNumRenderedNodes;
2100                }
2101                else if (showShadowMap && shadowTraverser)
2102                {
2103                        renderedNodes = traverser->GetStats().mNumRenderedNodes + shadowTraverser->GetStats().mNumRenderedNodes;
2104                        renderedObjects = traverser->GetStats().mNumRenderedGeometry + shadowTraverser->GetStats().mNumRenderedGeometry;
2105                        renderedTriangles = traverser->GetStats().mNumRenderedTriangles + shadowTraverser->GetStats().mNumRenderedTriangles;
2106                }
2107                else
2108                {
2109                        renderedTriangles = traverser->GetStats().mNumRenderedTriangles;
2110                        renderedObjects = traverser->GetStats().mNumRenderedGeometry;
2111                        renderedNodes = traverser->GetStats().mNumRenderedNodes;
2112                }
2113
2114                traversedNodes = traverser->GetStats().mNumTraversedNodes;
2115                frustumCulledNodes = traverser->GetStats().mNumFrustumCulledNodes;
2116                queryCulledNodes = traverser->GetStats().mNumQueryCulledNodes;
2117                issuedQueries = traverser->GetStats().mNumIssuedQueries;
2118                stateChanges = traverser->GetStats().mNumStateChanges;
2119                numBatches = traverser->GetStats().mNumBatches;
2120        }
2121
2122
2123        ////////////////
2124        //-- record stats on walkthrough
2125
2126        static float accTime = .0f;
2127        static float averageTime = .0f;
2128
2129        if (currentReplayFrame > -1)
2130        {
2131                accTime += frameTime;
2132                averageTime = accTime / (currentReplayFrame + 1);
2133
2134                if (!statsWriter)
2135                        statsWriter = new StatsWriter(statsFilename);
2136                       
2137                FrameStats frameStats;
2138                frameStats.mFrame = currentReplayFrame;
2139                frameStats.mFPS = 1e3f / (float)frameTime;
2140                frameStats.mTime = frameTime;
2141                frameStats.mNodes = renderedNodes;
2142                frameStats.mObjects = renderedObjects;
2143                frameStats.mTriangles = renderedTriangles;
2144
2145                statsWriter->WriteFrameStats(frameStats);
2146        }
2147        else if (statsWriter)
2148        {
2149                Debug << "average frame time " << averageTime << " for traversal algorithm " << renderMode << endl;
2150
2151                // reset average frame time
2152                averageTime = accTime = .0f;
2153
2154                DEL_PTR(statsWriter);
2155        }
2156
2157
2158        Begin2D();
2159
2160        glEnable(GL_BLEND);
2161        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2162
2163        if (showHelp)
2164        {       
2165                DrawHelpMessage();
2166        }
2167        else
2168        {
2169                if (showOptions)
2170                {
2171                        glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
2172                        glRecti(5, winHeight - 95, winWidth * 2 / 3 - 5, winHeight - 5);
2173                }
2174
2175                if (showStatistics)
2176                {
2177                        glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
2178                        glRecti(5, winHeight - 165, winWidth * 2 / 3 - 5, winHeight - 100);
2179                }
2180
2181                glEnable(GL_TEXTURE_2D);
2182                myfont.Begin();
2183
2184                if (showOptions)
2185                {
2186                        glColor3f(0.0f, 1.0f, 0.0f);
2187                        int i = 0;
2188
2189                        static char *renderMethodStr[] =
2190                                {"forward", "depth pass + forward", "deferred shading", "depth pass + deferred"};
2191                        sprintf(msg[i ++], "multiqueries: %d, tight bounds: %d, render queue: %d",
2192                                        useMultiQueries, useTightBounds, useRenderQueue);
2193                        sprintf(msg[i ++], "render technique: %s, SSAO: %d", renderMethodStr[renderMethod], useAdvancedShading);
2194                        sprintf(msg[i ++], "triangles per virtual leaf: %5d", trianglesPerVirtualLeaf);
2195                        sprintf(msg[i ++], "assumed visible frames: %4d, max batch size: %4d",
2196                                assumedVisibleFrames, maxBatchSize);
2197
2198                        for (int j = 0; j < 4; ++ j)
2199                                myfont.DrawString(msg[j], 10.0f, winHeight - 5 - j * 20);
2200                }
2201
2202                if (showStatistics)
2203                {
2204                        glColor3f(1.0f, 1.0f, 0.0f);
2205
2206                        string objStr, totalObjStr;
2207                        string triStr, totalTriStr;
2208
2209                        int len = 10;
2210                        CalcDecimalPoint(objStr, renderedObjects, len);
2211                        CalcDecimalPoint(totalObjStr, (int)resourceManager->GetNumEntities(), len);
2212
2213                        CalcDecimalPoint(triStr, renderedTriangles, len);
2214                        CalcDecimalPoint(totalTriStr, bvh->GetBvhStats().mTriangles, len);
2215
2216                        int i = 4;
2217
2218                        if (0)
2219                        {
2220                                sprintf(msg[i ++], "rendered: %s of %s objects, %s of %s triangles",
2221                                        objStr.c_str(), totalObjStr.c_str(), triStr.c_str(), totalTriStr.c_str());
2222                        }
2223                        else
2224                        {
2225                                sprintf(msg[i ++], "rendered: %6d of %6d nodes, %s of %s triangles",
2226                                        renderedNodes, bvh->GetNumVirtualNodes(), triStr.c_str(), totalTriStr.c_str());
2227                        }
2228
2229                        sprintf(msg[i ++], "traversed: %5d, frustum culled: %5d, query culled: %5d",
2230                                traversedNodes, frustumCulledNodes, queryCulledNodes);
2231                        sprintf(msg[i ++], "issued queries: %5d, renderState changes: %5d, render batches: %5d",
2232                                issuedQueries, stateChanges, numBatches);
2233
2234                        for (int j = 4; j < 7; ++ j)
2235                                myfont.DrawString(msg[j], 10.0f, winHeight - (j + 1) * 20);
2236                }
2237
2238                glColor3f(1.0f, 1.0f, 1.0f);
2239                static char *alg_str[] = {"Frustum Cull", "Stop and Wait", "CHC", "CHC ++"};
2240               
2241                if (!showAlgorithmTime)
2242                        sprintf(msg[7], "%s:  %6.1f fps", alg_str[renderMode], fps);
2243                else
2244                        sprintf(msg[7], "%s:  %6.1f ms", alg_str[renderMode], rTime);
2245               
2246                myfont.DrawString(msg[7], 1.3f, 690.0f, 760.0f);//, top_color, bottom_color);
2247               
2248                //sprintf(msg[8], "algorithm time: %6.1f ms", rTime);
2249                //myfont.DrawString(msg[8], 720.0f, 730.0f);           
2250        }
2251
2252        glDisable(GL_BLEND);
2253        glDisable(GL_TEXTURE_2D);
2254
2255        End2D();
2256}       
2257
2258
2259void RenderSky()
2260{
2261        if ((renderMethod == RENDER_DEFERRED) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
2262                renderState.SetRenderTechnique(DEFERRED);
2263
2264        const bool useToneMapping =
2265                ((renderMethod == RENDER_DEPTH_PASS_DEFERRED) ||
2266                 (renderMethod == RENDER_DEFERRED)) && useHDR;
2267       
2268        preetham->RenderSkyDome(-light->GetDirection(), camera, &renderState, !useToneMapping);
2269
2270        /// once again reset the renderState just to make sure
2271        renderState.Reset();
2272}
2273
2274
2275// render visible object from depth pass
2276void RenderVisibleObjects()
2277{
2278        if (renderMethod == RENDER_DEPTH_PASS_DEFERRED)
2279        {
2280                if (showShadowMap && !renderLightView)
2281                {
2282                        // usethe maximal visible distance to focus shadow map
2283                        const float newFar = min(camera->GetFar(), traverser->GetMaxVisibleDistance());
2284                        RenderShadowMap(newFar);
2285                }
2286                // initialize deferred rendering
2287                InitDeferredRendering();
2288        }
2289        else
2290        {
2291                renderState.SetRenderTechnique(FORWARD);
2292        }
2293
2294
2295        /////////////////
2296        //-- reset gl renderState before the final visible objects pass
2297
2298        renderState.Reset();
2299
2300        glEnableClientState(GL_NORMAL_ARRAY);
2301        /// switch back to smooth shading
2302        glShadeModel(GL_SMOOTH);
2303        /// reset alpha to coverage flag
2304        renderState.SetUseAlphaToCoverage(true);
2305        // clear color
2306        glClear(GL_COLOR_BUFFER_BIT);
2307       
2308        // draw only objects having exactly the same depth as the current sample
2309        glDepthFunc(GL_EQUAL);
2310
2311        //cout << "visible: " << (int)traverser->GetVisibleObjects().size() << endl;
2312
2313        SceneEntityContainer::const_iterator sit,
2314                sit_end = traverser->GetVisibleObjects().end();
2315
2316        for (sit = traverser->GetVisibleObjects().begin(); sit != sit_end; ++ sit)
2317        {
2318                renderQueue->Enqueue(*sit);
2319        }
2320        /// now render out everything in one giant pass
2321        renderQueue->Apply();
2322
2323        // switch back to standard depth func
2324        glDepthFunc(GL_LESS);
2325        renderState.Reset();
2326
2327        PrintGLerror("visibleobjects");
2328}
2329
2330
2331SceneQuery *GetOrCreateSceneQuery()
2332{
2333        if (!sceneQuery)
2334                sceneQuery = new SceneQuery(bvh->GetBox(), traverser, &renderState);
2335
2336        return sceneQuery;
2337}
2338
2339
2340void PlaceViewer(const Vector3 &oldPos)
2341{
2342        Vector3 playerPos = camera->GetPosition();
2343        bool validIntersect = GetOrCreateSceneQuery()->CalcIntersection(playerPos);
2344
2345        if (validIntersect)
2346                // && ((playerPos.z - oldPos.z) < bvh->GetBox().Size(2) * 1e-1f))
2347        {
2348                camera->SetPosition(playerPos);
2349        }
2350}
2351
2352
2353void RenderShadowMap(float newfar)
2354{
2355        glDisableClientState(GL_NORMAL_ARRAY);
2356        renderState.SetRenderTechnique(DEPTH_PASS);
2357       
2358        // hack: disable cull face because of alpha textured balconies
2359        glDisable(GL_CULL_FACE);
2360        renderState.LockCullFaceEnabled(true);
2361
2362        /// don't use alpha to coverage for the depth map (problems with fbo rendering)
2363        renderState.SetUseAlphaToCoverage(false);
2364
2365        // change CHC++ set of renderState variables
2366        // this must be done for each change of camera because
2367        // otherwise the temporal coherency is broken
2368        BvhNode::SetCurrentState(LIGHT_PASS);
2369        // hack: temporarily change camera far plane
2370        camera->SetFar(newfar);
2371        // the scene is rendered withouth any shading   
2372        shadowMap->ComputeShadowMap(shadowTraverser, viewProjMat);
2373
2374        camera->SetFar(farDist);
2375
2376        renderState.SetUseAlphaToCoverage(true);
2377        renderState.LockCullFaceEnabled(false);
2378        glEnable(GL_CULL_FACE);
2379
2380        glEnableClientState(GL_NORMAL_ARRAY);
2381        // change back renderState
2382        BvhNode::SetCurrentState(CAMERA_PASS);
2383}
2384
2385
2386/** Touch each material once in order to preload the render queue
2387        bucket id of each material
2388*/
2389void PrepareRenderQueue()
2390{
2391        for (int i = 0; i < 3; ++ i)
2392        {
2393                renderState.SetRenderTechnique(i);
2394
2395                // fill all shapes into the render queue        once so we can establish the buckets
2396                ShapeContainer::const_iterator sit, sit_end = (*resourceManager->GetShapes()).end();
2397
2398                for (sit = (*resourceManager->GetShapes()).begin(); sit != sit_end; ++ sit)
2399                {
2400                        static Transform3 dummy(IdentityMatrix());
2401                        renderQueue->Enqueue(*sit, NULL);
2402                }
2403       
2404                // just clear queue again
2405                renderQueue->Clear();
2406        }
2407}
2408
2409
2410void LoadModel(const string &model, SceneEntityContainer &entities)
2411{
2412        const string filename = string(model_path + model);
2413
2414        cout << "\nloading model " << filename << endl;
2415        if (resourceManager->Load(filename, entities))
2416        {
2417                cout << "model " << filename << " successfully loaded" << endl;
2418        }
2419        else
2420        {
2421                cerr << "loading model " << filename << " failed" << endl;
2422
2423                CleanUp();
2424                exit(0);
2425        }
2426}
2427
2428
2429void CreateAnimation()
2430{
2431        const float radius = 5.0f;
2432        const Vector3 center(480.398f, 268.364f, 181.3);
2433
2434        VertexArray vertices;
2435
2436        /*for (int i = 0; i < 360; ++ i)
2437        {
2438                float angle = (float)i * M_PI / 180.0f;
2439
2440                Vector3 offs = Vector3(cos(angle) * radius, sin(angle) * radius, 0);
2441                vertices.push_back(center + offs);
2442        }*/
2443
2444        for (int i = 0; i < 5; ++ i)
2445        {
2446                Vector3 offs = Vector3(i, 0, 0);
2447                vertices.push_back(center + offs);
2448        }
2449
2450       
2451        for (int i = 0; i < 5; ++ i)
2452        {
2453                Vector3 offs = Vector3(4 -i, 0, 0);
2454                vertices.push_back(center + offs);
2455        }
2456
2457        motionPath = new MotionPath(vertices);
2458}
2459
2460/** This function returns the number of visible pixels of a
2461        bounding box representing the sun.
2462*/
2463int TestSunVisible()
2464{
2465        // assume sun is at a far away point along the light vector
2466        Vector3 sunPos = light->GetDirection() * -1e3f;
2467        sunPos += camera->GetPosition();
2468
2469        sunBox->GetTransform()->SetMatrix(TranslationMatrix(sunPos));
2470
2471        glBeginQueryARB(GL_SAMPLES_PASSED_ARB, sunQuery);
2472
2473        sunBox->Render(&renderState);
2474
2475        glEndQueryARB(GL_SAMPLES_PASSED_ARB);
2476
2477        GLuint sampleCount;
2478
2479        glGetQueryObjectuivARB(sunQuery, GL_QUERY_RESULT_ARB, &sampleCount);
2480
2481        return sampleCount;
2482}
Note: See TracBrowser for help on using the repository browser.