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

Revision 3045, 45.6 KB checked in by mattausch, 16 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 "ObjConverter.h"
53#include "SkyPreetham.h"
54#include "Texture.h"
55#include "EntityMerger.h"
56
57using namespace std;
58using namespace CHCDemoEngine;
59
60
61static Environment env;
62
63#define MAX_DEPTH_CONST 10.0f
64
65
66GLuint fontTex;
67/// fbo
68FrameBufferObject *fbo = NULL;
69/// the renderable scene geometry
70SceneEntityContainer sceneEntities;
71// traverses and renders the hierarchy
72RenderTraverser *traverser = NULL;
73/// the hierarchy
74Bvh *bvh = NULL;
75/// handles scene loading
76ResourceManager *loader = NULL;
77/// the scene camera
78Camera *camera = NULL;
79/// the scene camera
80Camera *visCamera = NULL;
81/// the visualization
82Visualization *visualization = NULL;
83/// the current render state
84RenderState state;
85/// the rendering algorithm
86int renderMode = RenderTraverser::CHCPLUSPLUS;
87/// eye near plane distance
88float nearDist = 0.2f;
89/// eye far plane distance
90float farDist = 1e6f;
91/// the field of view
92float fov = 50.0f;
93/// the pixel threshold where a node is still considered invisible
94int threshold;
95
96int assumedVisibleFrames = 10;
97
98int maxBatchSize = 50;
99
100int trianglesPerVirtualLeaf = INITIAL_TRIANGLES_PER_VIRTUAL_LEAVES;
101
102SceneQuery *sceneQuery = NULL;
103RenderQueue *renderQueue = NULL;
104
105// traverses and renders the hierarchy
106RenderTraverser *shadowTraverser = NULL;
107
108SkyPreetham *preetham = NULL;
109
110
111/// the used render type for this render pass
112enum RenderMethod
113{
114        RENDER_FORWARD,
115        RENDER_DEPTH_PASS,
116        RENDER_DEFERRED,
117        RENDER_DEPTH_PASS_DEFERRED,
118        RENDER_NUM_RENDER_TYPES
119};
120
121/// one of four possible render methods
122int renderMethod = RENDER_FORWARD;
123
124
125/// these values get scaled with the frame rate
126static float keyForwardMotion = 30.0f;
127static float keyRotation = 1.5f;
128
129/// elapsed time in milliseconds
130double elapsedTime = 1000.0f;
131double algTime = 1000.0f;
132
133static int winWidth = 1024;
134static int winHeight = 768;
135
136int shadowSize = 2048;
137
138static float winAspectRatio = 1.0f;
139
140double accumulatedTime = 1000;
141float fps = 1e3f;
142
143glfont::GLFont myfont;
144
145// rendertexture
146static int texWidth = 1024;
147static int texHeight = 768;
148
149int renderedObjects = 0;
150int renderedNodes = 0;
151int renderedTriangles = 0;
152
153int issuedQueries = 0;
154int traversedNodes = 0;
155int frustumCulledNodes = 0;
156int queryCulledNodes = 0;
157int stateChanges = 0;
158int numBatches = 0;
159
160
161// mouse navigation state
162int xEyeBegin = 0;
163int yEyeBegin = 0;
164int yMotionBegin = 0;
165int verticalMotionBegin = 0;
166int horizontalMotionBegin = 0;
167
168
169bool leftKeyPressed = false;
170bool rightKeyPressed = false;
171bool upKeyPressed = false;
172bool downKeyPressed = false;
173bool descendKeyPressed = false;
174bool ascendKeyPressed = false;
175
176bool showHelp = false;
177bool showStatistics = false;
178bool showOptions = true;
179bool showBoundingVolumes = false;
180bool visMode = false;
181
182bool useOptimization = false;
183bool useTightBounds = true;
184bool useRenderQueue = true;
185bool useMultiQueries = true;
186bool flyMode = true;
187
188bool useGlobIllum = false;
189bool useTemporalCoherence = true;
190bool showAlgorithmTime = false;
191
192bool useFullScreen = false;
193bool useLODs = true;
194bool moveLight = false;
195
196bool useAdvancedShading = false;
197bool showShadowMap = false;
198bool renderLightView = false;
199
200bool altKeyPressed = false;
201
202bool useHDR = true;
203
204static float ssaoTempCohFactor = 255.0;
205
206
207PerfTimer frameTimer, algTimer;
208
209static int sCurrentMrtSet = 0;
210
211PerformanceGraph *perfGraph = NULL;
212
213
214//DeferredRenderer::SAMPLING_METHOD samplingMethod = DeferredRenderer::SAMPLING_POISSON;
215DeferredRenderer::SAMPLING_METHOD samplingMethod = DeferredRenderer::SAMPLING_QUADRATIC;
216
217ShadowMap *shadowMap = NULL;
218DirectionalLight *light = NULL;
219DeferredRenderer *ssaoShader = NULL;
220
221SceneEntity *cube = NULL;
222SceneEntity *aeroplane = NULL;
223SceneEntity *skyDome = NULL;
224
225
226
227// function forward declarations
228void InitExtensions();
229void DisplayVisualization();
230void InitGLstate();
231void InitRenderTexture();
232void CleanUp();
233void SetupEyeView();
234void UpdateEyeMtx();
235void SetupLighting();
236void DisplayStats();
237void Output(int x, int y, const char *string);
238void DrawHelpMessage();
239void RenderSky();
240void RenderVisibleObjects();
241
242void Begin2D();
243void End2D();
244void KeyBoard(unsigned char c, int x, int y);
245void DrawStatistics();
246void Display();
247void Special(int c, int x, int y);
248void KeyUp(unsigned char c, int x, int y);
249void SpecialKeyUp(int c, int x, int y);
250void Reshape(int w, int h);
251void Mouse(int button, int state, int x, int y);
252void LeftMotion(int x, int y);
253void RightMotion(int x, int y);
254void MiddleMotion(int x, int y);
255void CalcDecimalPoint(string &str, int d);
256
257RenderTraverser *CreateTraverser(Camera *cam);
258
259void KeyHorizontalMotion(float shift);
260void KeyVerticalMotion(float shift);
261
262void PlaceViewer(const Vector3 &oldPos);
263
264inline float KeyRotationAngle() { return keyRotation * elapsedTime * 1e-3f; }
265inline float KeyShift() { return keyForwardMotion * elapsedTime * 1e-3f; }
266// initialise the frame buffer objects
267void InitFBO();
268
269void RightMotionLight(int x, int y);
270
271void RenderShadowMap(float newfar);
272
273static Matrix4x4 viewProjMat = IdentityMatrix();
274static Matrix4x4 oldViewProjMat = IdentityMatrix();
275
276
277
278static void PrintGLerror(char *msg)
279{
280        GLenum errCode;
281        const GLubyte *errStr;
282       
283        if ((errCode = glGetError()) != GL_NO_ERROR)
284        {
285                errStr = gluErrorString(errCode);
286                fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg);
287        }
288}
289
290
291int main(int argc, char* argv[])
292{
293/*
294#ifdef _CRT_SET
295
296        //Now just call this function at the start of your program and if you're
297        //compiling in debug mode (F5), any leaks will be displayed in the Output
298        //window when the program shuts down. If you're not in debug mode this will
299        //be ignored. Use it as you will!
300        //note: from GDNet Direct [3.8.04 - 3.14.04] void detectMemoryLeaks() {
301
302        _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);
303        _CrtSetReportMode(_CRT_ASSERT,_CRTDBG_MODE_FILE);
304        _CrtSetReportFile(_CRT_ASSERT,_CRTDBG_FILE_STDERR);
305#endif
306*/
307        cout << "=== reading environment file ===" << endl << endl;
308
309        int returnCode = 0;
310
311        Vector3 camPos(.0f, .0f, .0f);
312        Vector3 camDir(.0f, 1.0f, .0f);
313        Vector3 lightDir(-0.8f, 1.0f, -0.7f);
314
315        cout << "=== reading environment file ===" << endl << endl;
316
317        const string envFileName = "default.env";
318        if (!env.Read(envFileName))
319        {
320                cerr << "loading environment " << envFileName << " failed!" << endl;
321        }
322        else
323        {
324                env.GetIntParam(string("assumedVisibleFrames"), assumedVisibleFrames);
325                env.GetIntParam(string("maxBatchSize"), maxBatchSize);
326                env.GetIntParam(string("trianglesPerVirtualLeaf"), trianglesPerVirtualLeaf);
327
328                env.GetFloatParam(string("keyForwardMotion"), keyForwardMotion);
329                env.GetFloatParam(string("keyRotation"), keyRotation);
330
331                env.GetIntParam(string("winWidth"), winWidth);
332                env.GetIntParam(string("winHeight"), winHeight);
333
334                env.GetBoolParam(string("useFullScreen"), useFullScreen);
335                env.GetFloatParam(string("tempCohFactor"), ssaoTempCohFactor);
336                env.GetVectorParam(string("camPosition"), camPos);
337                env.GetVectorParam(string("camDirection"), camDir);
338                env.GetVectorParam(string("lightDirection"), lightDir);
339
340                env.GetBoolParam(string("useLODs"), useLODs);
341                env.GetIntParam(string("shadowSize"), shadowSize);
342
343                env.GetBoolParam(string("useHDR"), useHDR);
344
345                //env.GetStringParam(string("modelPath"), model_path);
346                //env.GetIntParam(string("numSssaoSamples"), numSsaoSamples);
347
348                cout << "assumedVisibleFrames: " << assumedVisibleFrames << endl;
349                cout << "maxBatchSize: " << maxBatchSize << endl;
350                cout << "trianglesPerVirtualLeaf: " << trianglesPerVirtualLeaf << endl;
351
352                cout << "keyForwardMotion: " << keyForwardMotion << endl;
353                cout << "keyRotation: " << keyRotation << endl;
354                cout << "winWidth: " << winWidth << endl;
355                cout << "winHeight: " << winHeight << endl;
356                cout << "useFullScreen: " << useFullScreen << endl;
357                cout << "useLODs: " << useLODs << endl;
358                cout << "camPosition: " << camPos << endl;
359                cout << "temporal coherence: " << ssaoTempCohFactor << endl;
360                cout << "shadow size: " << shadowSize << endl;
361
362                //cout << "model path: " << model_path << endl;
363
364                cout << "**** end parameters ****" << endl << endl;
365        }
366
367        ///////////////////////////
368
369        camera = new Camera(winWidth, winHeight, fov);
370        camera->SetNear(nearDist);
371        camera->SetFar(1000);
372
373        camera->SetDirection(camDir);
374        camera->SetPosition(camPos);
375
376        visCamera = new Camera(winWidth, winHeight, fov);
377        visCamera->SetNear(0.0f);
378        visCamera->Yaw(.5 * M_PI);
379
380        // create a new light
381        light = new DirectionalLight(lightDir, RgbaColor(1, 1, 1, 1), RgbaColor(1, 1, 1, 1));
382
383
384        renderQueue = new RenderQueue(&state, camera);
385
386        glutInitWindowSize(winWidth, winHeight);
387        glutInit(&argc, argv);
388        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE);
389        //glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
390        //glutInitDisplayString("samples=2");
391
392        SceneEntity::SetUseLODs(useLODs);
393
394        if (!useFullScreen)
395        {
396                glutCreateWindow("FriendlyCulling");
397        }
398        else
399        {
400                glutGameModeString( "1024x768:32@75" );
401                glutEnterGameMode();
402        }
403
404        glutDisplayFunc(Display);
405        glutKeyboardFunc(KeyBoard);
406        glutSpecialFunc(Special);
407        glutReshapeFunc(Reshape);
408        glutMouseFunc(Mouse);
409        glutIdleFunc(Display);
410        glutKeyboardUpFunc(KeyUp);
411        glutSpecialUpFunc(SpecialKeyUp);
412        glutIgnoreKeyRepeat(true);
413
414        // initialise gl graphics
415        InitExtensions();
416        InitGLstate();
417
418        glEnable(GL_MULTISAMPLE_ARB);
419        glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
420
421        LeftMotion(0, 0);
422        MiddleMotion(0, 0);
423
424        perfGraph = new PerformanceGraph(1000);
425
426        loader = ResourceManager::GetSingleton();
427
428        const string filename = string(model_path + "city.dem");
429       
430        if (loader->Load(filename, sceneEntities))
431                cout << "model " << filename << " loaded" << endl;
432        else
433        {
434                cerr << "loading model " << filename << " failed" << endl;
435                CleanUp();
436                exit(0);
437        }
438       
439
440        const string bvh_filename = string(model_path + "city.bvh");
441        BvhLoader bvhLoader;
442        bvh = bvhLoader.Load(bvh_filename, sceneEntities);
443
444        if (!bvh)
445        {
446                cerr << "loading bvh " << bvh_filename << " failed" << endl;
447                CleanUp();
448                exit(0);
449        }
450
451        // set far plane based on scene extent
452        farDist = 10.0f * Magnitude(bvh->GetBox().Diagonal());
453        bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
454
455        camera->SetFar(Magnitude(bvh->GetBox().Diagonal()));
456       
457        Vector3 cubeCenter(470.398f, 240.364f, 182.5f);
458       
459        Matrix4x4 transl = TranslationMatrix(cubeCenter);
460
461        SceneEntityContainer dummy;
462       
463        string skyDomeStr(model_path + "sky.dem");
464
465        if (loader->Load(skyDomeStr, sceneEntities))
466        {
467                cout << "successfully loaded " << sceneEntities.size() << " scene entities" << endl;
468        }
469        else
470        {
471                cerr << "loading file " << skyDomeStr << " failed" << endl;
472
473                CleanUp();
474                exit(0);
475        }
476
477        skyDome = sceneEntities.back();
478
479        const float turbitiy = 5.0f;
480        preetham = new SkyPreetham(turbitiy, skyDome);
481
482        // initialize the render traverser
483        traverser = CreateTraverser(camera);
484
485        visualization = new Visualization(bvh, camera, NULL, &state);
486       
487        state.SetRenderPassType(RenderState::FORWARD);
488
489        // frame time is restarted every frame
490        frameTimer.Start();
491        // the rendering loop
492        glutMainLoop();
493        // clean up
494        CleanUp();
495       
496        return 0;
497}
498
499
500void InitFBO()
501{
502        PrintGLerror("fbo start");
503
504        // this fbo basicly stores the scene information we get from standard rendering of a frame
505        // we store colors, normals, positions (for the ssao)
506        fbo = new FrameBufferObject(texWidth, texHeight, FrameBufferObject::DEPTH_32);
507        //fbo = new FrameBufferObject(texWidth, texHeight, FrameBufferObject::DEPTH_24);
508
509        // the diffuse color buffer
510        fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, ColorBufferObject::FILTER_NEAREST);
511        // the normals buffer
512        fbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
513        // the positions buffer
514        //fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
515        fbo->AddColorBuffer(ColorBufferObject::RGB_UBYTE, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
516        // another color buffer
517        fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, ColorBufferObject::FILTER_NEAREST);
518
519        PrintGLerror("fbo");
520}
521
522
523bool InitFont(void)
524{
525        glEnable(GL_TEXTURE_2D);
526
527        glGenTextures(1, &fontTex);
528        glBindTexture(GL_TEXTURE_2D, fontTex);
529
530        if (!myfont.Create("data/fonts/verdana.glf", fontTex))
531                return false;
532
533        glDisable(GL_TEXTURE_2D);
534       
535        return true;
536}
537
538
539void InitGLstate()
540{
541        glClearColor(0.4f, 0.4f, 0.4f, 1.0f);
542       
543        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
544        glPixelStorei(GL_PACK_ALIGNMENT,1);
545       
546        glDepthFunc(GL_LESS);
547        glEnable(GL_DEPTH_TEST);
548
549        glColor3f(1.0f, 1.0f, 1.0f);
550        glShadeModel(GL_SMOOTH);
551       
552        glMaterialf(GL_FRONT, GL_SHININESS, 64);
553        glEnable(GL_NORMALIZE);
554               
555        glDisable(GL_ALPHA_TEST);
556        glAlphaFunc(GL_GEQUAL, 0.5f);
557
558        glFrontFace(GL_CCW);
559        glCullFace(GL_BACK);
560        glEnable(GL_CULL_FACE);
561
562        glDisable(GL_TEXTURE_2D);
563
564        GLfloat ambientColor[] = {0.2, 0.2, 0.2, 1.0};
565        GLfloat diffuseColor[] = {1.0, 0.0, 0.0, 1.0};
566        GLfloat specularColor[] = {0.0, 0.0, 0.0, 1.0};
567
568        glMaterialfv(GL_FRONT, GL_AMBIENT, ambientColor);
569        glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseColor);
570        glMaterialfv(GL_FRONT, GL_SPECULAR, specularColor);
571
572        glDepthFunc(GL_LESS);
573
574        if (!InitFont())
575                cerr << "font creation failed" << endl;
576        else
577                cout << "successfully created font" << endl;
578
579
580        //////////////////////////////
581
582        //GLfloat lmodel_ambient[] = {1.0f, 1.0f, 1.0f, 1.0f};
583        GLfloat lmodel_ambient[] = {0.7f, 0.7f, 0.8f, 1.0f};
584
585        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
586        //glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
587        glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
588        glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SINGLE_COLOR_EXT);
589}
590
591
592void DrawHelpMessage()
593{
594        const char *message[] =
595        {
596                "Help information",
597                "",
598                "'F1'           - shows/dismisses this message",
599                "'F2'           - shows/hides bird eye view",
600                "'F3'           - shows/hides bounds (boxes or tight bounds)",
601                "'F4',          - shows/hides parameters",
602                "'F5'           - shows/hides statistics",
603                "'F6',          - toggles between fly/walkmode",
604                "'F7',          - cycles throw render modes",
605                "'F8',          - enables/disables ambient occlusion (only deferred)",
606                "'F9',          - shows pure algorithm render time (using glFinish)",
607                "'SPACE'        - cycles through occlusion culling algorithms",
608                "",
609                "'MOUSE LEFT'        - turn left/right, move forward/backward",
610                "'MOUSE RIGHT'       - turn left/right, move forward/backward",
611                "'MOUSE MIDDLE'      - move up/down, left/right",
612                "'CURSOR UP/DOWN'    - move forward/backward",
613                "'CURSOR LEFT/RIGHT' - turn left/right",
614                "",
615                "'-'/'+'        - decreases/increases max batch size",
616                "'1'/'2'        - downward/upward motion",
617                "'3'/'4'        - decreases/increases triangles per virtual bvh leaf (sets bvh depth)",
618                "'5'/'6'        - decreases/increases assumed visible frames",
619                "",
620                "'R'            - use render queue",
621                "'B'            - use tight bounds",
622                "'M'            - use multiqueries",
623                "'O'            - use CHC optimization (geometry queries for leaves)",
624                0,
625        };
626       
627       
628        glColor4f(0.0f, 1.0f , 0.0f, 0.2f); // 20% green.
629
630        glRecti(30, 30, winWidth - 30, winHeight - 30);
631
632        glEnd();
633
634        glColor3f(1.0f, 1.0f, 1.0f);
635       
636        glEnable(GL_TEXTURE_2D);
637        myfont.Begin();
638
639        int x = 40, y = 30;
640
641        for(int i = 0; message[i] != 0; ++ i)
642        {
643                if(message[i][0] == '\0')
644                {
645                        y += 15;
646                }
647                else
648                {
649                        myfont.DrawString(message[i], x, winHeight - y);
650                        y += 25;
651                }
652        }
653        glDisable(GL_TEXTURE_2D);
654}
655
656
657RenderTraverser *CreateTraverser(Camera *cam)
658{
659        RenderTraverser *tr;
660       
661        bvh->ResetNodeClassifications();
662
663        switch (renderMode)
664        {
665        case RenderTraverser::CULL_FRUSTUM:
666                tr = new FrustumCullingTraverser();
667                break;
668        case RenderTraverser::STOP_AND_WAIT:
669                tr = new StopAndWaitTraverser();
670                break;
671        case RenderTraverser::CHC:
672                tr = new CHCTraverser();
673                break;
674        case RenderTraverser::CHCPLUSPLUS:
675                tr = new CHCPlusPlusTraverser();
676                break;
677       
678        default:
679                tr = new FrustumCullingTraverser();
680        }
681
682        tr->SetCamera(cam);
683        tr->SetHierarchy(bvh);
684        tr->SetRenderQueue(renderQueue);
685        tr->SetRenderState(&state);
686        tr->SetUseOptimization(useOptimization);
687        tr->SetUseRenderQueue(useRenderQueue);
688        tr->SetVisibilityThreshold(threshold);
689        tr->SetAssumedVisibleFrames(assumedVisibleFrames);
690        tr->SetMaxBatchSize(maxBatchSize);
691        tr->SetUseMultiQueries(useMultiQueries);
692        tr->SetUseTightBounds(useTightBounds);
693        tr->SetUseDepthPass((renderMethod == RENDER_DEPTH_PASS) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED));
694        tr->SetRenderQueue(renderQueue);
695
696        return tr;
697}
698
699
700void SetupLighting()
701{
702        glEnable(GL_LIGHT0);
703        glDisable(GL_LIGHT1);
704       
705        Vector3 lightDir = -light->GetDirection();
706
707
708        ///////////
709        //-- first light: sunlight
710
711        GLfloat ambient[] = {0.25f, 0.25f, 0.3f, 1.0f};
712        GLfloat diffuse[] = {1.0f, 0.95f, 0.85f, 1.0f};
713        GLfloat specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
714       
715
716        const bool useToneMapping = ((renderMethod == RENDER_DEPTH_PASS_DEFERRED) || (renderMethod == RENDER_DEFERRED)) && useHDR;
717
718        Vector3 sunAmbient;
719        Vector3 sunDiffuse;
720
721        preetham->ComputeSunColor(lightDir, sunAmbient, sunDiffuse, !useToneMapping);
722
723        ambient[0] = sunAmbient.x;
724        ambient[1] = sunAmbient.y;
725        ambient[2] = sunAmbient.z;
726
727        // no tone mapping => scale
728        if (!useToneMapping)
729        {
730                const float maxComponent = sunDiffuse.MaxComponent();
731                sunDiffuse /= maxComponent;
732        }
733
734        diffuse[0] = sunDiffuse.x;
735        diffuse[1] = sunDiffuse.y;
736        diffuse[2] = sunDiffuse.z;
737
738        glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
739        glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
740        glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
741
742        GLfloat position[] = {lightDir.x, lightDir.y, lightDir.z, 0.0f};
743        glLightfv(GL_LIGHT0, GL_POSITION, position);
744}
745
746
747void SetupEyeView()
748{
749        // store matrix of last frame
750        oldViewProjMat = viewProjMat;
751
752        glMatrixMode(GL_PROJECTION);
753        glLoadIdentity();
754        gluPerspective(fov, winAspectRatio, nearDist, farDist);
755
756        glMatrixMode(GL_MODELVIEW);
757       
758        // set up the camera view
759        camera->SetupCameraView();
760
761               
762        /////////////////
763
764        Matrix4x4 matViewing, matProjection;
765
766        camera->GetModelViewMatrix(matViewing);
767        camera->GetProjectionMatrix(matProjection);
768
769        // store matrix for later use
770        viewProjMat = matViewing * matProjection;
771}
772
773
774void KeyHorizontalMotion(float shift)
775{
776        Vector3 hvec = -camera->GetDirection();
777        hvec.z = 0;
778
779        Vector3 pos = camera->GetPosition();
780        pos += hvec * shift;
781       
782        camera->SetPosition(pos);
783}
784
785
786void KeyVerticalMotion(float shift)
787{
788        Vector3 uvec = Vector3(0, 0, shift);
789
790        Vector3 pos = camera->GetPosition();
791        pos += uvec;
792       
793        camera->SetPosition(pos);
794}
795
796
797static void ComputeViewVectors(Vector3 &tl, Vector3 &tr, Vector3 &bl, Vector3 &br)
798{
799        Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr;
800
801        camera->ComputePoints(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr);
802
803        bl = Normalize(nbl - fbl);
804        br = Normalize(nbr - fbr);
805        tl = Normalize(ntl - ftl);
806        tr = Normalize(ntr - ftr);
807}
808
809
810void InitDeferredRendering()
811{
812        if (!fbo) InitFBO();
813        fbo->Bind();
814
815        // multisampling does not work with deferred shading
816        glDisable(GL_MULTISAMPLE_ARB);
817
818        state.SetRenderPassType(RenderState::DEFERRED);
819
820        loader->EnableVertexProfile();
821        loader->EnableFragmentProfile();
822
823        const Vector3 pos = camera->GetPosition();
824
825
826        // draw to 3 color buffers
827        // a color, normal, and positions buffer
828        if (sCurrentMrtSet == 0)
829        {
830                DeferredRenderer::colorBufferIdx = 0;
831                glDrawBuffers(2, mrt);
832        }
833        else
834        {
835                DeferredRenderer::colorBufferIdx = 3;
836                glDrawBuffers(2, mrt2);
837        }
838
839        sCurrentMrtSet = 1 - sCurrentMrtSet;
840}
841
842
843// the main rendering loop
844void Display()
845{       
846        Vector3 oldPos = camera->GetPosition();
847
848        if (leftKeyPressed)
849                camera->Pitch(KeyRotationAngle());
850        if (rightKeyPressed)
851                camera->Pitch(-KeyRotationAngle());
852        if (upKeyPressed)
853                KeyHorizontalMotion(-KeyShift());
854        if (downKeyPressed)
855                KeyHorizontalMotion(KeyShift());
856        if (ascendKeyPressed)
857                KeyVerticalMotion(KeyShift());
858        if (descendKeyPressed)
859                KeyVerticalMotion(-KeyShift());
860
861        // place view on ground
862        if (!flyMode) PlaceViewer(oldPos);
863
864        if (showAlgorithmTime)
865        {
866                glFinish();
867                algTimer.Start();
868        }
869       
870
871        if ((!shadowMap || !shadowTraverser) && (showShadowMap || renderLightView))
872        {
873                if (!shadowMap)
874                        shadowMap = new ShadowMap(light, shadowSize, bvh->GetBox(), camera);
875
876                if (!shadowTraverser)
877                        shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
878
879        }
880       
881        // bring eye modelview matrix up-to-date
882        SetupEyeView();
883
884        // set GPU related parameters
885        GPUProgramParameters::InitFrame(camera);
886
887
888        // hack
889        int oldRenderMethod = renderMethod;
890        // for rendering the light view, we use forward rendering
891        if (renderLightView)
892                renderMethod = RenderState::FORWARD;
893
894        glEnableClientState(GL_VERTEX_ARRAY);
895
896
897        // render with the specified method (forward rendering, forward + depth, deferred)
898        switch (renderMethod)
899        {
900        case RENDER_FORWARD:
901       
902                glEnable(GL_MULTISAMPLE_ARB);
903               
904                state.SetRenderPassType(RenderState::FORWARD);
905                glEnable(GL_LIGHTING);
906
907                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
908
909                glEnableClientState(GL_NORMAL_ARRAY);
910
911                break;
912
913        case RENDER_DEPTH_PASS_DEFERRED:
914
915                glDisable(GL_MULTISAMPLE_ARB);
916                state.SetUseAlphaToCoverage(false);
917
918                state.SetRenderPassType(RenderState::DEPTH_PASS);
919
920                if (!fbo) InitFBO(); fbo->Bind();
921
922                glDrawBuffers(1, mrt);
923
924                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
925
926                // the scene is rendered withouth any shading   
927                glShadeModel(GL_FLAT);
928                glDisable(GL_LIGHTING);
929                glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
930
931
932                break;
933
934        case RENDER_DEPTH_PASS:
935
936                glEnable(GL_MULTISAMPLE_ARB);
937               
938                state.SetRenderPassType(RenderState::DEPTH_PASS);
939
940                // the scene is rendered withouth any shading   
941                glShadeModel(GL_FLAT);
942                glDisable(GL_LIGHTING);
943       
944                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
945                glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
946
947
948                break;
949       
950        case RenderState::DEFERRED:
951
952                if (showShadowMap && !renderLightView)
953                        RenderShadowMap(camera->GetFar());
954
955                //glPushAttrib(GL_VIEWPORT_BIT);
956                glViewport(0, 0, texWidth, texHeight);
957
958                InitDeferredRendering();
959               
960                glEnableClientState(GL_NORMAL_ARRAY);
961                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
962
963                break;
964        }
965
966        glDepthFunc(GL_LESS);
967
968        glDisable(GL_TEXTURE_2D);
969        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
970               
971
972        // reset lod levels for current frame
973        LODLevel::InitFrame(camera->GetPosition());
974
975        // set up lights
976        SetupLighting();
977
978
979        if (renderLightView)
980        {
981                // change CHC++ set of state variables (must be done for each change of camera because
982                // otherwise the temporal coherency is broken
983                BvhNode::SetCurrentState(1);
984                shadowMap->RenderShadowView(shadowTraverser, viewProjMat);
985                BvhNode::SetCurrentState(0);
986        }
987        else
988        {
989                // actually render the scene geometry using the specified algorithm
990                traverser->RenderScene();
991        }
992
993
994        /////////
995        //-- do the rest of the rendering
996       
997        // reset depth pass and render visible objects
998        if ((renderMethod == RENDER_DEPTH_PASS) ||
999                (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
1000        {
1001                RenderVisibleObjects();
1002        }
1003       
1004
1005        ///////////////
1006        //-- render sky
1007
1008        // q: should we render sky after deferred shading?
1009        // this would conveniently solves some issues (e.g, skys without shadows)
1010
1011        RenderSky();
1012
1013
1014        if ((renderMethod == RENDER_DEFERRED) ||
1015                (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
1016        {
1017                FrameBufferObject::Release();
1018
1019                //loader->DisableVertexProfile();
1020                //loader->DisableFragmentProfile();
1021
1022                if (!ssaoShader) ssaoShader =
1023                        new DeferredRenderer(texWidth, texHeight, camera, farDist / MAX_DEPTH_CONST);
1024               
1025                DeferredRenderer::SHADING_METHOD shadingMethod;
1026
1027                if (useAdvancedShading)
1028                {
1029                        if (useGlobIllum)
1030                                shadingMethod = DeferredRenderer::GI;
1031                        else
1032                                shadingMethod = DeferredRenderer::SSAO;
1033                }
1034                else
1035                        shadingMethod = DeferredRenderer::DEFAULT;
1036
1037
1038                ssaoShader->SetShadingMethod(shadingMethod);
1039                ssaoShader->SetSamplingMethod(samplingMethod);
1040                ssaoShader->SetUseTemporalCoherence(useTemporalCoherence);
1041
1042                ShadowMap *sm = showShadowMap ? shadowMap : NULL;
1043                ssaoShader->Render(fbo, oldViewProjMat, viewProjMat, ssaoTempCohFactor, light, useHDR, sm);
1044        }
1045
1046
1047        state.SetRenderPassType(RenderState::FORWARD);
1048        state.Reset();
1049
1050
1051        glDisableClientState(GL_VERTEX_ARRAY);
1052        glDisableClientState(GL_NORMAL_ARRAY);
1053       
1054        renderMethod = oldRenderMethod;
1055
1056
1057        ///////////
1058
1059
1060        if (showAlgorithmTime)
1061        {
1062                glFinish();
1063
1064                algTime = algTimer.Elapsedms();
1065                perfGraph->AddData(algTime);
1066
1067                perfGraph->Draw();
1068        }
1069        else
1070        {
1071                if (visMode) DisplayVisualization();
1072        }
1073
1074        glFlush();
1075
1076        const bool restart = true;
1077        elapsedTime = frameTimer.Elapsedms(restart);
1078
1079        DisplayStats();
1080
1081        glutSwapBuffers();
1082}
1083
1084
1085#pragma warning( disable : 4100 )
1086void KeyBoard(unsigned char c, int x, int y)
1087{
1088        switch(c)
1089        {
1090        case 27:
1091                CleanUp();
1092                exit(0);
1093                break;
1094        case 32: // space
1095                renderMode = (renderMode + 1) % RenderTraverser::NUM_TRAVERSAL_TYPES;
1096
1097                DEL_PTR(traverser);
1098                traverser = CreateTraverser(camera);
1099
1100                if (shadowTraverser)
1101                {
1102                        // shadow traverser has to be recomputed
1103                        DEL_PTR(shadowTraverser);
1104                        shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
1105                }
1106
1107                break;
1108        case '+':
1109                if (maxBatchSize < 10)
1110                        maxBatchSize = 10;
1111                else
1112                        maxBatchSize += 10;
1113
1114                traverser->SetMaxBatchSize(maxBatchSize);
1115                break;
1116        case '-':
1117                maxBatchSize -= 10;
1118                if (maxBatchSize < 0) maxBatchSize = 1;
1119                traverser->SetMaxBatchSize(maxBatchSize);               
1120                break;
1121        case 'M':
1122        case 'm':
1123                useMultiQueries = !useMultiQueries;
1124                traverser->SetUseMultiQueries(useMultiQueries);
1125                break;
1126        case '1':
1127                descendKeyPressed = true;
1128                break;
1129        case '2':
1130                ascendKeyPressed = true;
1131                break;
1132        case '3':
1133                if (trianglesPerVirtualLeaf >= 100)
1134                        trianglesPerVirtualLeaf -= 100;
1135                bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
1136                break;
1137        case '4':
1138                trianglesPerVirtualLeaf += 100;
1139                bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
1140                break;
1141        case '5':
1142                assumedVisibleFrames -= 1;
1143                if (assumedVisibleFrames < 1) assumedVisibleFrames = 1;
1144                traverser->SetAssumedVisibleFrames(assumedVisibleFrames);
1145                break;
1146        case '6':
1147                assumedVisibleFrames += 1;
1148                traverser->SetAssumedVisibleFrames(assumedVisibleFrames);               
1149                break;
1150        case '7':
1151                ssaoTempCohFactor *= 0.5f;
1152                break;
1153        case '8':
1154                ssaoTempCohFactor *= 2.0f;
1155                //if (ssaoTempCohFactor > 1.0f) ssaoExpFactor = 1.0f;
1156                break;
1157        case '9':
1158                useLODs = !useLODs;
1159                SceneEntity::SetUseLODs(useLODs);
1160                break;
1161        case 'P':
1162        case 'p':
1163                samplingMethod = DeferredRenderer::SAMPLING_METHOD((samplingMethod + 1) % 3);
1164                cout << "ssao sampling method: " << samplingMethod << endl;
1165                break;
1166        case 'Y':
1167        case 'y':
1168                showShadowMap = !showShadowMap;
1169                break;
1170        case 'g':
1171        case 'G':
1172                useGlobIllum = !useGlobIllum;
1173                break;
1174        case 't':
1175        case 'T':
1176                useTemporalCoherence = !useTemporalCoherence;
1177                break;
1178        case 'o':
1179        case 'O':
1180                useOptimization = !useOptimization;
1181                traverser->SetUseOptimization(useOptimization);
1182                break;
1183        case 'a':
1184        case 'A':
1185                leftKeyPressed = true;
1186                break;
1187        case 'd':
1188        case 'D':
1189                rightKeyPressed = true;
1190                break;
1191        case 'w':
1192        case 'W':
1193                upKeyPressed = true;
1194                break;
1195        case 's':
1196        case 'S':
1197                downKeyPressed = true;
1198                break;
1199        case 'r':
1200        case 'R':
1201                useRenderQueue = !useRenderQueue;
1202                traverser->SetUseRenderQueue(useRenderQueue);
1203               
1204                break;
1205        case 'b':
1206        case 'B':
1207                useTightBounds = !useTightBounds;
1208                traverser->SetUseTightBounds(useTightBounds);
1209                break;
1210        case 'l':
1211        case 'L':
1212                renderLightView = !renderLightView;
1213                break;
1214        case 'h':
1215        case 'H':
1216                useHDR = !useHDR;
1217                break;
1218        default:
1219                return;
1220        }
1221
1222        glutPostRedisplay();
1223}
1224
1225
1226void SpecialKeyUp(int c, int x, int y)
1227{
1228        switch (c)
1229        {
1230        case GLUT_KEY_LEFT:
1231                leftKeyPressed = false;
1232                break;
1233        case GLUT_KEY_RIGHT:
1234                rightKeyPressed = false;
1235                break;
1236        case GLUT_KEY_UP:
1237                upKeyPressed = false;
1238                break;
1239        case GLUT_KEY_DOWN:
1240                downKeyPressed = false;
1241                break;
1242        case GLUT_ACTIVE_ALT:
1243                altKeyPressed = false;
1244                break;
1245        default:
1246                return;
1247        }
1248}
1249
1250
1251void KeyUp(unsigned char c, int x, int y)
1252{
1253        switch (c)
1254        {
1255
1256        case 'A':
1257        case 'a':
1258                leftKeyPressed = false;
1259                break;
1260        case 'D':
1261        case 'd':
1262                rightKeyPressed = false;
1263                break;
1264        case 'W':
1265        case 'w':
1266                upKeyPressed = false;
1267                break;
1268        case 'S':
1269        case 's':
1270                downKeyPressed = false;
1271                break;
1272        case '1':
1273                descendKeyPressed = false;
1274                break;
1275        case '2':
1276                ascendKeyPressed = false;
1277                break;
1278       
1279        default:
1280                return;
1281        }
1282        //glutPostRedisplay();
1283}
1284
1285
1286void Special(int c, int x, int y)
1287{
1288        switch(c)
1289        {
1290        case GLUT_KEY_F1:
1291                showHelp = !showHelp;
1292                break;
1293        case GLUT_KEY_F2:
1294                visMode = !visMode;
1295                break;
1296        case GLUT_KEY_F3:
1297                showBoundingVolumes = !showBoundingVolumes;
1298                traverser->SetShowBounds(showBoundingVolumes);
1299                break;
1300        case GLUT_KEY_F4:
1301                showOptions = !showOptions;
1302                break;
1303        case GLUT_KEY_F5:
1304                showStatistics = !showStatistics;
1305                break;
1306        case GLUT_KEY_F6:
1307                flyMode = !flyMode;
1308                break;
1309        case GLUT_KEY_F7:
1310
1311                renderMethod = (renderMethod + 1) % 4;
1312
1313                traverser->SetUseDepthPass(
1314                        (renderMethod == RENDER_DEPTH_PASS) ||
1315                        (renderMethod == RENDER_DEPTH_PASS_DEFERRED)
1316                        );
1317               
1318                break;
1319        case GLUT_KEY_F8:
1320                useAdvancedShading = !useAdvancedShading;
1321
1322                break;
1323        case GLUT_KEY_F9:
1324                showAlgorithmTime = !showAlgorithmTime;
1325                break;
1326        case GLUT_KEY_F10:
1327                moveLight = !moveLight;
1328                break;
1329        case GLUT_KEY_LEFT:
1330                {
1331                        leftKeyPressed = true;
1332                        camera->Pitch(KeyRotationAngle());
1333                }
1334                break;
1335        case GLUT_KEY_RIGHT:
1336                {
1337                        rightKeyPressed = true;
1338                        camera->Pitch(-KeyRotationAngle());
1339                }
1340                break;
1341        case GLUT_KEY_UP:
1342                {
1343                        upKeyPressed = true;
1344                        KeyHorizontalMotion(KeyShift());
1345                }
1346                break;
1347        case GLUT_KEY_DOWN:
1348                {
1349                        downKeyPressed = true;
1350                        KeyHorizontalMotion(-KeyShift());
1351                }
1352                break;
1353        default:
1354                return;
1355
1356        }
1357
1358        glutPostRedisplay();
1359}
1360
1361#pragma warning( default : 4100 )
1362
1363
1364void Reshape(int w, int h)
1365{
1366        winAspectRatio = 1.0f;
1367
1368        glViewport(0, 0, w, h);
1369       
1370        winWidth = w;
1371        winHeight = h;
1372
1373        if (w) winAspectRatio = (float) w / (float) h;
1374
1375        glMatrixMode(GL_PROJECTION);
1376        glLoadIdentity();
1377
1378        gluPerspective(fov, winAspectRatio, nearDist, farDist);
1379
1380        glMatrixMode(GL_MODELVIEW);
1381
1382        glutPostRedisplay();
1383}
1384
1385
1386void Mouse(int button, int state, int x, int y)
1387{
1388        if ((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN))
1389        {
1390                xEyeBegin = x;
1391                yMotionBegin = y;
1392
1393                glutMotionFunc(LeftMotion);
1394        }
1395        else if ((button == GLUT_RIGHT_BUTTON) && (state == GLUT_DOWN))
1396        {
1397                xEyeBegin = x;
1398                yEyeBegin = y;
1399                yMotionBegin = y;
1400
1401                if (!moveLight)
1402                        glutMotionFunc(RightMotion);
1403                else
1404                        glutMotionFunc(RightMotionLight);
1405        }
1406        else if ((button == GLUT_MIDDLE_BUTTON) && (state == GLUT_DOWN))
1407        {
1408                horizontalMotionBegin = x;
1409                verticalMotionBegin = y;
1410                glutMotionFunc(MiddleMotion);
1411        }
1412
1413        glutPostRedisplay();
1414}
1415
1416
1417/**     rotation for left/right mouse drag
1418        motion for up/down mouse drag
1419*/
1420void LeftMotion(int x, int y)
1421{
1422        Vector3 viewDir = camera->GetDirection();
1423        Vector3 pos = camera->GetPosition();
1424
1425        // don't move in the vertical direction
1426        Vector3 horView(viewDir[0], viewDir[1], 0);
1427       
1428        float eyeXAngle = 0.2f *  M_PI * (xEyeBegin - x) / 180.0;
1429
1430        camera->Pitch(eyeXAngle);
1431
1432        pos += horView * (yMotionBegin - y) * 0.2f;
1433       
1434        camera->SetPosition(pos);
1435       
1436        xEyeBegin = x;
1437        yMotionBegin = y;
1438
1439        glutPostRedisplay();
1440}
1441
1442
1443void RightMotionLight(int x, int y)
1444{
1445        float theta = 0.2f * M_PI * (xEyeBegin - x) / 180.0f;
1446        float phi = 0.2f * M_PI * (yMotionBegin - y) / 180.0f;
1447       
1448        Vector3 lightDir = light->GetDirection();
1449
1450        Matrix4x4 roty = RotationYMatrix(theta);
1451        Matrix4x4 rotx = RotationXMatrix(phi);
1452
1453        lightDir = roty * lightDir;
1454        lightDir = rotx * lightDir;
1455
1456        // normalize to avoid accumulating errors
1457        lightDir.Normalize();
1458
1459        light->SetDirection(lightDir);
1460
1461        xEyeBegin = x;
1462        yMotionBegin = y;
1463
1464        glutPostRedisplay();
1465}
1466
1467
1468/**     rotation for left / right mouse drag
1469        motion for up / down mouse drag
1470*/
1471void RightMotion(int x, int y)
1472{
1473        float eyeXAngle = 0.2f *  M_PI * (xEyeBegin - x) / 180.0;
1474        float eyeYAngle = -0.2f *  M_PI * (yEyeBegin - y) / 180.0;
1475
1476        camera->Yaw(eyeYAngle);
1477        camera->Pitch(eyeXAngle);
1478
1479        xEyeBegin = x;
1480        yEyeBegin = y;
1481
1482        glutPostRedisplay();
1483}
1484
1485
1486// strafe
1487void MiddleMotion(int x, int y)
1488{
1489        Vector3 viewDir = camera->GetDirection();
1490        Vector3 pos = camera->GetPosition();
1491
1492        // the 90 degree rotated view vector
1493        // y zero so we don't move in the vertical
1494        Vector3 rVec(viewDir[0], viewDir[1], 0);
1495       
1496        Matrix4x4 rot = RotationZMatrix(M_PI * 0.5f);
1497        rVec = rot * rVec;
1498       
1499        pos -= rVec * (x - horizontalMotionBegin) * 0.1f;
1500        pos[2] += (verticalMotionBegin - y) * 0.1f;
1501
1502        camera->SetPosition(pos);
1503
1504        horizontalMotionBegin = x;
1505        verticalMotionBegin = y;
1506
1507        glutPostRedisplay();
1508}
1509
1510
1511void InitExtensions(void)
1512{
1513        GLenum err = glewInit();
1514
1515        if (GLEW_OK != err)
1516        {
1517                // problem: glewInit failed, something is seriously wrong
1518                fprintf(stderr,"Error: %s\n", glewGetErrorString(err));
1519                exit(1);
1520        }
1521        if  (!GLEW_ARB_occlusion_query)
1522        {
1523                printf("I require the GL_ARB_occlusion_query to work.\n");
1524                exit(1);
1525        }
1526}
1527
1528
1529void Begin2D()
1530{
1531        glDisable(GL_LIGHTING);
1532        glDisable(GL_DEPTH_TEST);
1533
1534        glMatrixMode(GL_PROJECTION);
1535        glPushMatrix();
1536        glLoadIdentity();
1537
1538        gluOrtho2D(0, winWidth, 0, winHeight);
1539
1540        glMatrixMode(GL_MODELVIEW);
1541        glPushMatrix();
1542        glLoadIdentity();
1543}
1544
1545
1546void End2D()
1547{
1548        glMatrixMode(GL_PROJECTION);
1549        glPopMatrix();
1550
1551        glMatrixMode(GL_MODELVIEW);
1552        glPopMatrix();
1553
1554        glEnable(GL_LIGHTING);
1555        glEnable(GL_DEPTH_TEST);
1556}
1557
1558
1559// displays the visualisation of culling algorithm
1560void DisplayVisualization()
1561{
1562        visualization->SetFrameId(traverser->GetCurrentFrameId());
1563       
1564        Begin2D();
1565        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1566        glEnable(GL_BLEND);
1567        glColor4f(0.0f ,0.0f, 0.0f, 0.5f);
1568
1569        glRecti(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth, winHeight);
1570        glDisable(GL_BLEND);
1571        End2D();
1572       
1573       
1574        AxisAlignedBox3 box = bvh->GetBox();
1575
1576        const float offs = box.Size().x * 0.3f;
1577       
1578        Vector3 vizpos = Vector3(box.Min().x, box.Min().y  - box.Size().y * 0.35f, box.Min().z + box.Size().z * 50);
1579       
1580        visCamera->SetPosition(vizpos);
1581        visCamera->ResetPitchAndYaw();
1582       
1583        glPushAttrib(GL_VIEWPORT_BIT);
1584        glViewport(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth / 3, winHeight / 3);
1585
1586        glMatrixMode(GL_PROJECTION);
1587        glPushMatrix();
1588
1589        glLoadIdentity();
1590       
1591        glOrtho(-offs, offs, -offs, offs, 0.0f, box.Size().z * 100.0f);
1592
1593        glMatrixMode(GL_MODELVIEW);
1594        glPushMatrix();
1595
1596        visCamera->SetupCameraView();
1597
1598        Matrix4x4 rotZ = RotationZMatrix(-camera->GetPitch());
1599        glMultMatrixf((float *)rotZ.x);
1600
1601        // inverse translation in order to fix current position
1602        Vector3 pos = camera->GetPosition();
1603        glTranslatef(-pos.x, -pos.y, -pos.z);
1604
1605
1606        GLfloat position[] = {0.8f, 1.0f, 1.5f, 0.0f};
1607        glLightfv(GL_LIGHT0, GL_POSITION, position);
1608
1609        GLfloat position1[] = {bvh->GetBox().Center().x, bvh->GetBox().Max().y, bvh->GetBox().Center().z, 1.0f};
1610        glLightfv(GL_LIGHT1, GL_POSITION, position1);
1611
1612        glClear(GL_DEPTH_BUFFER_BIT);
1613
1614
1615        ////////////
1616        //-- visualization of the occlusion culling
1617
1618        visualization->Render();
1619
1620       
1621        // reset previous settings
1622        glPopAttrib();
1623
1624        glMatrixMode(GL_PROJECTION);
1625        glPopMatrix();
1626        glMatrixMode(GL_MODELVIEW);
1627        glPopMatrix();
1628}
1629
1630
1631// cleanup routine after the main loop
1632void CleanUp()
1633{
1634        DEL_PTR(traverser);
1635        DEL_PTR(sceneQuery);
1636        DEL_PTR(bvh);
1637        DEL_PTR(visualization);
1638        DEL_PTR(camera);
1639        DEL_PTR(renderQueue);
1640        DEL_PTR(perfGraph);
1641        DEL_PTR(fbo);
1642        DEL_PTR(ssaoShader);
1643        DEL_PTR(light);
1644        DEL_PTR(visCamera);
1645        DEL_PTR(preetham);
1646        DEL_PTR(shadowMap);
1647        DEL_PTR(shadowTraverser);
1648       
1649        ResourceManager::DelSingleton();
1650        loader = NULL;
1651}
1652
1653
1654// this function inserts a dezimal point after each 1000
1655void CalcDecimalPoint(string &str, int d, int len)
1656{
1657        static vector<int> numbers;
1658        numbers.clear();
1659
1660        static string shortStr;
1661        shortStr.clear();
1662
1663        static char hstr[100];
1664
1665        while (d != 0)
1666        {
1667                numbers.push_back(d % 1000);
1668                d /= 1000;
1669        }
1670
1671        // first element without leading zeros
1672        if (numbers.size() > 0)
1673        {
1674                sprintf(hstr, "%d", numbers.back());
1675                shortStr.append(hstr);
1676        }
1677       
1678        for (int i = (int)numbers.size() - 2; i >= 0; i--)
1679        {
1680                sprintf(hstr, ",%03d", numbers[i]);
1681                shortStr.append(hstr);
1682        }
1683
1684        int dif = len - (int)shortStr.size();
1685
1686        for (int i = 0; i < dif; ++ i)
1687        {
1688                str += " ";
1689        }
1690
1691        str.append(shortStr);
1692}
1693
1694
1695void DisplayStats()
1696{
1697        static char msg[9][300];
1698
1699        static double frameTime = elapsedTime;
1700        static double renderTime = algTime;
1701
1702        const float expFactor = 0.1f;
1703
1704        // if some strange render time spike happened in this frame => don't count
1705        if (elapsedTime < 500) frameTime = elapsedTime * expFactor + (1.0f - expFactor) * elapsedTime;
1706       
1707        static float rTime = 1000.0f;
1708
1709        if (showAlgorithmTime)
1710        {
1711                if (algTime < 500) renderTime = algTime * expFactor + (1.0f - expFactor) * renderTime;
1712        }
1713
1714        accumulatedTime += elapsedTime;
1715
1716        if (accumulatedTime > 500) // update every fraction of a second
1717        {       
1718                accumulatedTime = 0;
1719
1720                if (frameTime) fps = 1e3f / (float)frameTime;
1721
1722                rTime = renderTime;
1723
1724                if (renderLightView && shadowTraverser)
1725                {
1726                        renderedTriangles = shadowTraverser->GetStats().mNumRenderedTriangles;
1727                        renderedObjects = shadowTraverser->GetStats().mNumRenderedGeometry;
1728                        renderedNodes = shadowTraverser->GetStats().mNumRenderedNodes;
1729                }
1730                else if (showShadowMap && shadowTraverser)
1731                {
1732                        renderedNodes = traverser->GetStats().mNumRenderedNodes + shadowTraverser->GetStats().mNumRenderedNodes;
1733                        renderedObjects = traverser->GetStats().mNumRenderedGeometry + shadowTraverser->GetStats().mNumRenderedGeometry;
1734                        renderedTriangles = traverser->GetStats().mNumRenderedTriangles + shadowTraverser->GetStats().mNumRenderedTriangles;
1735                }
1736                else
1737                {
1738                        renderedTriangles = traverser->GetStats().mNumRenderedTriangles;
1739                        renderedObjects = traverser->GetStats().mNumRenderedGeometry;
1740                        renderedNodes = traverser->GetStats().mNumRenderedNodes;
1741                }
1742
1743                traversedNodes = traverser->GetStats().mNumTraversedNodes;
1744                frustumCulledNodes = traverser->GetStats().mNumFrustumCulledNodes;
1745                queryCulledNodes = traverser->GetStats().mNumQueryCulledNodes;
1746                issuedQueries = traverser->GetStats().mNumIssuedQueries;
1747                stateChanges = traverser->GetStats().mNumStateChanges;
1748                numBatches = traverser->GetStats().mNumBatches;
1749        }
1750
1751
1752        Begin2D();
1753
1754        glEnable(GL_BLEND);
1755        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1756
1757        if (showHelp)
1758        {       
1759                DrawHelpMessage();
1760        }
1761        else
1762        {
1763                if (showOptions)
1764                {
1765                        glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
1766                        glRecti(5, winHeight - 95, winWidth * 2 / 3 - 5, winHeight - 5);
1767                }
1768
1769                if (showStatistics)
1770                {
1771                        glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
1772                        glRecti(5, winHeight - 165, winWidth * 2 / 3 - 5, winHeight - 100);
1773                }
1774
1775                glEnable(GL_TEXTURE_2D);
1776
1777                myfont.Begin();
1778
1779                if (showOptions)
1780                {
1781                        glColor3f(0.0f, 1.0f, 0.0f);
1782
1783                        int i = 0;
1784
1785                        static char *renderMethodStr[] = {"forward", "depth pass + forward", "deferred shading", "depth pass + deferred"};
1786       
1787                        sprintf(msg[i ++], "multiqueries: %d, tight bounds: %d, render queue: %d",
1788                                                        useMultiQueries, useTightBounds, useRenderQueue);
1789
1790                        sprintf(msg[i ++], "render technique: %s, SSAO: %d", renderMethodStr[renderMethod], useAdvancedShading);
1791
1792                        sprintf(msg[i ++], "triangles per virtual leaf: %5d", trianglesPerVirtualLeaf);
1793
1794                        sprintf(msg[i ++], "assumed visible frames: %4d, max batch size: %4d",
1795                                assumedVisibleFrames, maxBatchSize);
1796
1797                        for (int j = 0; j < 4; ++ j)
1798                                myfont.DrawString(msg[j], 10.0f, winHeight - 5 - j * 20);
1799                }
1800
1801                if (showStatistics)
1802                {
1803                        glColor3f(1.0f, 1.0f, 0.0f);
1804
1805                        string objStr, totalObjStr;
1806                        string triStr, totalTriStr;
1807
1808                        int len = 10;
1809                        CalcDecimalPoint(objStr, renderedObjects, len);
1810                        CalcDecimalPoint(totalObjStr, (int)loader->GetNumEntities(), len);
1811
1812                        CalcDecimalPoint(triStr, renderedTriangles, len);
1813                        CalcDecimalPoint(totalTriStr, bvh->GetBvhStats().mTriangles, len);
1814
1815                        int i = 4;
1816
1817                        if (0)
1818                        {
1819                                sprintf(msg[i ++], "rendered: %s of %s objects, %s of %s triangles",
1820                                        objStr.c_str(), totalObjStr.c_str(), triStr.c_str(), totalTriStr.c_str());
1821                        }
1822                        else
1823                        {
1824                                sprintf(msg[i ++], "rendered: %6d of %6d nodes, %s of %s triangles",
1825                                        renderedNodes, bvh->GetNumVirtualNodes(), triStr.c_str(), totalTriStr.c_str());
1826                        }
1827
1828                        sprintf(msg[i ++], "traversed: %5d, frustum culled: %5d, query culled: %5d",
1829                                traversedNodes, frustumCulledNodes, queryCulledNodes);
1830
1831                        sprintf(msg[i ++], "issued queries: %5d, state changes: %5d, render batches: %5d",
1832                                issuedQueries, stateChanges, numBatches);
1833
1834                        for (int j = 4; j < 7; ++ j)
1835                                myfont.DrawString(msg[j], 10.0f, winHeight - (j + 1) * 20);
1836                }
1837
1838                glColor3f(1.0f, 1.0f, 1.0f);
1839                static char *alg_str[] = {"Frustum Cull", "Stop and Wait", "CHC", "CHC ++"};
1840               
1841                if (!showAlgorithmTime)
1842                                sprintf(msg[7], "%s:  %6.1f fps", alg_str[renderMode], fps);
1843                else
1844                        sprintf(msg[7], "%s:  %6.1f ms", alg_str[renderMode], rTime);
1845               
1846                myfont.DrawString(msg[7], 1.3f, 690.0f, 760.0f);//, top_color, bottom_color);
1847               
1848                //sprintf(msg[8], "algorithm time: %6.1f ms", rTime);
1849                //myfont.DrawString(msg[8], 720.0f, 730.0f);           
1850        }
1851
1852        glDisable(GL_BLEND);
1853        glDisable(GL_TEXTURE_2D);
1854
1855        End2D();
1856}       
1857
1858
1859void RenderSky()
1860{
1861        if ((renderMethod == RENDER_DEFERRED) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
1862                state.SetRenderPassType(RenderState::DEFERRED);
1863
1864        const bool useToneMapping =
1865                ((renderMethod == RENDER_DEPTH_PASS_DEFERRED) ||
1866                 (renderMethod == RENDER_DEFERRED)) && useHDR;
1867
1868        preetham->RenderSkyDome(-light->GetDirection(), camera, &state, !useToneMapping);
1869
1870        state.Reset();
1871}
1872
1873
1874// render visible object from depth pass
1875void RenderVisibleObjects()
1876{
1877        if (renderMethod == RENDER_DEPTH_PASS_DEFERRED)
1878        {
1879                if (showShadowMap && !renderLightView)
1880                {
1881                        state.Reset();
1882
1883                        float minVisibleDist = min(camera->GetFar(), traverser->GetMaxVisibleDistance());
1884                        RenderShadowMap(minVisibleDist);
1885                }
1886
1887                glDisable(GL_LIGHTING);
1888                glViewport(0, 0, texWidth, texHeight);
1889
1890                state.Reset();
1891                InitDeferredRendering();
1892        }
1893        else
1894        {
1895                glEnable(GL_LIGHTING);
1896                state.SetRenderPassType(RenderState::FORWARD);
1897                state.Reset();
1898        }
1899
1900        glShadeModel(GL_SMOOTH);
1901        glEnableClientState(GL_NORMAL_ARRAY);
1902
1903        // draw all objects that have exactly the same depth as the current sample
1904        glDepthFunc(GL_LEQUAL);
1905        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1906
1907        glClear(GL_COLOR_BUFFER_BIT);
1908
1909        state.SetUseAlphaToCoverage(true);
1910       
1911
1912        //cout << "visible: " << (int)traverser->GetVisibleObjects().size() << endl;
1913
1914        SceneEntityContainer::const_iterator sit,
1915                sit_end = traverser->GetVisibleObjects().end();
1916
1917        for (sit = traverser->GetVisibleObjects().begin(); sit != sit_end; ++ sit)
1918        {
1919                renderQueue->Enqueue(*sit);
1920        }
1921
1922        renderQueue->Apply();
1923
1924        glDepthFunc(GL_LESS);
1925        state.Reset();
1926
1927        PrintGLerror("visibleobjects");
1928}
1929
1930
1931void PlaceViewer(const Vector3 &oldPos)
1932{
1933        if (!sceneQuery)
1934                sceneQuery = new SceneQuery(bvh->GetBox(), traverser);
1935
1936        Vector3 playerPos = camera->GetPosition();
1937        bool validIntersect = sceneQuery->CalcIntersection(playerPos);
1938
1939        if (validIntersect)
1940                // && ((playerPos.z - oldPos.z) < bvh->GetBox().Size(2) * 1e-1f))
1941        {
1942                camera->SetPosition(playerPos);
1943        }
1944}
1945
1946
1947void RenderShadowMap(float newfar)
1948{
1949        loader->DisableVertexProfile();
1950        loader->DisableFragmentProfile();
1951
1952        glDisableClientState(GL_NORMAL_ARRAY);
1953
1954        state.SetRenderPassType(RenderState::DEPTH_PASS);
1955       
1956        // hack: disable cull face because of alpha textured balconies
1957        glDisable(GL_CULL_FACE);
1958        state.LockCullFaceEnabled(true);
1959
1960        state.SetUseAlphaToCoverage(false);
1961
1962        // change CHC++ set of state variables
1963        // this must be done for each change of camera because
1964        // otherwise the temporal coherency is broken
1965        BvhNode::SetCurrentState(1);
1966
1967        // hack: temporarily change camera far plane
1968        camera->SetFar(newfar);
1969
1970        // the scene is rendered withouth any shading   
1971        shadowMap->ComputeShadowMap(shadowTraverser, viewProjMat);
1972
1973        glEnable(GL_CULL_FACE);
1974        camera->SetFar(farDist);
1975
1976        state.SetUseAlphaToCoverage(true);
1977        state.LockCullFaceEnabled(false);
1978
1979        glEnableClientState(GL_NORMAL_ARRAY);
1980
1981        // change back state
1982        BvhNode::SetCurrentState(0);
1983}
Note: See TracBrowser for help on using the repository browser.