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

Revision 3227, 60.5 KB checked in by mattausch, 16 years ago (diff)

worked on sampling / convergence

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