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

Revision 3057, 46.3 KB checked in by mattausch, 16 years ago (diff)

added a shader manager

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