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

Revision 3039, 45.8 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_FIXED,
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_FIXED;
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        //InitCg();
480
481        const float turbitiy = 5.0f;
482        preetham = new SkyPreetham(turbitiy, skyDome);
483
484        // initialize the render traverser
485        traverser = CreateTraverser(camera);
486
487        visualization = new Visualization(bvh, camera, NULL, &state);
488       
489        state.SetRenderPassType(RenderState::FIXED);
490
491        // frame time is restarted every frame
492        frameTimer.Start();
493
494        // the rendering loop
495        glutMainLoop();
496
497        // clean up
498        CleanUp();
499       
500        return 0;
501}
502
503
504void InitFBO()
505{
506        PrintGLerror("fbo start");
507
508        // this fbo basicly stores the scene information we get from standard rendering of a frame
509        // we store colors, normals, positions (for the ssao)
510        fbo = new FrameBufferObject(texWidth, texHeight, FrameBufferObject::DEPTH_32);
511        //fbo = new FrameBufferObject(texWidth, texHeight, FrameBufferObject::DEPTH_24);
512
513        // the diffuse color buffer
514        fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, ColorBufferObject::FILTER_NEAREST);
515        // the normals buffer
516        fbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
517        // the positions buffer
518        //fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
519        fbo->AddColorBuffer(ColorBufferObject::RGB_UBYTE, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
520        // another color buffer
521        fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, ColorBufferObject::FILTER_NEAREST);
522
523        PrintGLerror("fbo");
524}
525
526
527bool InitFont(void)
528{
529        glEnable(GL_TEXTURE_2D);
530
531        glGenTextures(1, &fontTex);
532        glBindTexture(GL_TEXTURE_2D, fontTex);
533
534        if (!myfont.Create("data/fonts/verdana.glf", fontTex))
535                return false;
536
537        glDisable(GL_TEXTURE_2D);
538       
539        return true;
540}
541
542
543void InitGLstate()
544{
545        glClearColor(0.4f, 0.4f, 0.4f, 1.0f);
546       
547        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
548        glPixelStorei(GL_PACK_ALIGNMENT,1);
549       
550        glDepthFunc(GL_LESS);
551        glEnable(GL_DEPTH_TEST);
552
553        glColor3f(1.0f, 1.0f, 1.0f);
554        glShadeModel(GL_SMOOTH);
555       
556        glMaterialf(GL_FRONT, GL_SHININESS, 64);
557        glEnable(GL_NORMALIZE);
558               
559        glDisable(GL_ALPHA_TEST);
560        glAlphaFunc(GL_GEQUAL, 0.5f);
561
562        glFrontFace(GL_CCW);
563        glCullFace(GL_BACK);
564        glEnable(GL_CULL_FACE);
565
566        glDisable(GL_TEXTURE_2D);
567
568        GLfloat ambientColor[] = {0.2, 0.2, 0.2, 1.0};
569        GLfloat diffuseColor[] = {1.0, 0.0, 0.0, 1.0};
570        GLfloat specularColor[] = {0.0, 0.0, 0.0, 1.0};
571
572        glMaterialfv(GL_FRONT, GL_AMBIENT, ambientColor);
573        glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseColor);
574        glMaterialfv(GL_FRONT, GL_SPECULAR, specularColor);
575
576        glDepthFunc(GL_LESS);
577
578        if (!InitFont())
579                cerr << "font creation failed" << endl;
580        else
581                cout << "successfully created font" << endl;
582
583
584        //////////////////////////////
585
586        //GLfloat lmodel_ambient[] = {1.0f, 1.0f, 1.0f, 1.0f};
587        GLfloat lmodel_ambient[] = {0.7f, 0.7f, 0.8f, 1.0f};
588
589        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
590        //glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
591        glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
592        glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SINGLE_COLOR_EXT);
593}
594
595
596void DrawHelpMessage()
597{
598        const char *message[] =
599        {
600                "Help information",
601                "",
602                "'F1'           - shows/dismisses this message",
603                "'F2'           - shows/hides bird eye view",
604                "'F3'           - shows/hides bounds (boxes or tight bounds)",
605                "'F4',          - shows/hides parameters",
606                "'F5'           - shows/hides statistics",
607                "'F6',          - toggles between fly/walkmode",
608                "'F7',          - cycles throw render modes",
609                "'F8',          - enables/disables ambient occlusion (only deferred)",
610                "'F9',          - shows pure algorithm render time (using glFinish)",
611                "'SPACE'        - cycles through occlusion culling algorithms",
612                "",
613                "'MOUSE LEFT'        - turn left/right, move forward/backward",
614                "'MOUSE RIGHT'       - turn left/right, move forward/backward",
615                "'MOUSE MIDDLE'      - move up/down, left/right",
616                "'CURSOR UP/DOWN'    - move forward/backward",
617                "'CURSOR LEFT/RIGHT' - turn left/right",
618                "",
619                "'-'/'+'        - decreases/increases max batch size",
620                "'1'/'2'        - downward/upward motion",
621                "'3'/'4'        - decreases/increases triangles per virtual bvh leaf (sets bvh depth)",
622                "'5'/'6'        - decreases/increases assumed visible frames",
623                "",
624                "'R'            - use render queue",
625                "'B'            - use tight bounds",
626                "'M'            - use multiqueries",
627                "'O'            - use CHC optimization (geometry queries for leaves)",
628                0,
629        };
630       
631       
632        glColor4f(0.0f, 1.0f , 0.0f, 0.2f); // 20% green.
633
634        glRecti(30, 30, winWidth - 30, winHeight - 30);
635
636        glEnd();
637
638        glColor3f(1.0f, 1.0f, 1.0f);
639       
640        glEnable(GL_TEXTURE_2D);
641        myfont.Begin();
642
643        int x = 40, y = 30;
644
645        for(int i = 0; message[i] != 0; ++ i)
646        {
647                if(message[i][0] == '\0')
648                {
649                        y += 15;
650                }
651                else
652                {
653                        myfont.DrawString(message[i], x, winHeight - y);
654                        y += 25;
655                }
656        }
657        glDisable(GL_TEXTURE_2D);
658}
659
660
661RenderTraverser *CreateTraverser(Camera *cam)
662{
663        RenderTraverser *tr;
664       
665        bvh->ResetNodeClassifications();
666
667        switch (renderMode)
668        {
669        case RenderTraverser::CULL_FRUSTUM:
670                tr = new FrustumCullingTraverser();
671                break;
672        case RenderTraverser::STOP_AND_WAIT:
673                tr = new StopAndWaitTraverser();
674                break;
675        case RenderTraverser::CHC:
676                tr = new CHCTraverser();
677                break;
678        case RenderTraverser::CHCPLUSPLUS:
679                tr = new CHCPlusPlusTraverser();
680                break;
681       
682        default:
683                tr = new FrustumCullingTraverser();
684        }
685
686        tr->SetCamera(cam);
687        tr->SetHierarchy(bvh);
688        tr->SetRenderQueue(renderQueue);
689        tr->SetRenderState(&state);
690        tr->SetUseOptimization(useOptimization);
691        tr->SetUseRenderQueue(useRenderQueue);
692        tr->SetVisibilityThreshold(threshold);
693        tr->SetAssumedVisibleFrames(assumedVisibleFrames);
694        tr->SetMaxBatchSize(maxBatchSize);
695        tr->SetUseMultiQueries(useMultiQueries);
696        tr->SetUseTightBounds(useTightBounds);
697        tr->SetUseDepthPass((renderMethod == RENDER_DEPTH_PASS) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED));
698        tr->SetRenderQueue(renderQueue);
699
700        return tr;
701}
702
703
704void SetupLighting()
705{
706        glEnable(GL_LIGHT0);
707        glDisable(GL_LIGHT1);
708       
709        Vector3 lightDir = -light->GetDirection();
710
711
712        ///////////
713        //-- first light: sunlight
714
715        GLfloat ambient[] = {0.25f, 0.25f, 0.3f, 1.0f};
716        GLfloat diffuse[] = {1.0f, 0.95f, 0.85f, 1.0f};
717        GLfloat specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
718       
719
720        const bool useToneMapping = ((renderMethod == RENDER_DEPTH_PASS_DEFERRED) || (renderMethod == RENDER_DEFERRED)) && useHDR;
721
722        Vector3 sunAmbient;
723        Vector3 sunDiffuse;
724
725        preetham->ComputeSunColor(lightDir, sunAmbient, sunDiffuse, !useToneMapping);
726
727        ambient[0] = sunAmbient.x;
728        ambient[1] = sunAmbient.y;
729        ambient[2] = sunAmbient.z;
730
731        // no tone mapping => scale
732        if (!useToneMapping)
733        {
734                const float maxComponent = sunDiffuse.MaxComponent();
735                sunDiffuse /= maxComponent;
736        }
737
738        diffuse[0] = sunDiffuse.x;
739        diffuse[1] = sunDiffuse.y;
740        diffuse[2] = sunDiffuse.z;
741
742        glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
743        glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
744        glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
745
746        GLfloat position[] = {lightDir.x, lightDir.y, lightDir.z, 0.0f};
747        glLightfv(GL_LIGHT0, GL_POSITION, position);
748}
749
750
751void SetupEyeView()
752{
753        // store matrix of last frame
754        oldViewProjMat = viewProjMat;
755
756        glMatrixMode(GL_PROJECTION);
757        glLoadIdentity();
758        gluPerspective(fov, winAspectRatio, nearDist, farDist);
759
760        glMatrixMode(GL_MODELVIEW);
761       
762        // set up the camera view
763        camera->SetupCameraView();
764
765               
766        /////////////////
767
768        Matrix4x4 matViewing, matProjection;
769
770        camera->GetModelViewMatrix(matViewing);
771        camera->GetProjectionMatrix(matProjection);
772
773        // store matrix for later use
774        viewProjMat = matViewing * matProjection;
775}
776
777
778void KeyHorizontalMotion(float shift)
779{
780        Vector3 hvec = -camera->GetDirection();
781        hvec.z = 0;
782
783        Vector3 pos = camera->GetPosition();
784        pos += hvec * shift;
785       
786        camera->SetPosition(pos);
787}
788
789
790void KeyVerticalMotion(float shift)
791{
792        Vector3 uvec = Vector3(0, 0, shift);
793
794        Vector3 pos = camera->GetPosition();
795        pos += uvec;
796       
797        camera->SetPosition(pos);
798}
799
800
801static void ComputeViewVectors(Vector3 &tl, Vector3 &tr, Vector3 &bl, Vector3 &br)
802{
803        Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr;
804
805        camera->ComputePoints(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr);
806
807        bl = Normalize(nbl - fbl);
808        br = Normalize(nbr - fbr);
809        tl = Normalize(ntl - ftl);
810        tr = Normalize(ntr - ftr);
811}
812
813
814void InitDeferredRendering()
815{
816        if (!fbo) InitFBO();
817        fbo->Bind();
818
819        // multisampling does not work with deferred shading
820        glDisable(GL_MULTISAMPLE_ARB);
821
822        state.SetRenderPassType(RenderState::DEFERRED);
823
824        loader->EnableVertexProfile();
825        loader->EnableFragmentProfile();
826
827        const Vector3 pos = camera->GetPosition();
828
829
830        // draw to 3 color buffers
831        // a color, normal, and positions buffer
832        if (sCurrentMrtSet == 0)
833        {
834                DeferredRenderer::colorBufferIdx = 0;
835                glDrawBuffers(2, mrt);
836        }
837        else
838        {
839                DeferredRenderer::colorBufferIdx = 3;
840                glDrawBuffers(2, mrt2);
841        }
842
843        sCurrentMrtSet = 1 - sCurrentMrtSet;
844}
845
846
847// the main rendering loop
848void Display()
849{       
850        Vector3 oldPos = camera->GetPosition();
851
852        if (leftKeyPressed)
853                camera->Pitch(KeyRotationAngle());
854        if (rightKeyPressed)
855                camera->Pitch(-KeyRotationAngle());
856        if (upKeyPressed)
857                KeyHorizontalMotion(-KeyShift());
858        if (downKeyPressed)
859                KeyHorizontalMotion(KeyShift());
860        if (ascendKeyPressed)
861                KeyVerticalMotion(KeyShift());
862        if (descendKeyPressed)
863                KeyVerticalMotion(-KeyShift());
864
865        // place view on ground
866        if (!flyMode) PlaceViewer(oldPos);
867
868        if (showAlgorithmTime)
869        {
870                glFinish();
871                algTimer.Start();
872        }
873       
874
875
876        if ((!shadowMap || !shadowTraverser) && (showShadowMap || renderLightView))
877        {
878                if (!shadowMap)
879                        shadowMap = new ShadowMap(light, shadowSize, bvh->GetBox(), camera);
880
881                if (!shadowTraverser)
882                        shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
883
884        }
885       
886        // bring eye modelview matrix up-to-date
887        SetupEyeView();
888
889        // hack
890        int oldRenderMethod = renderMethod;
891
892        if (renderLightView)
893                renderMethod = RenderState::FIXED;
894
895        glEnableClientState(GL_VERTEX_ARRAY);
896
897
898        // render with the specified method (forward rendering, forward + depth, deferred)
899        switch (renderMethod)
900        {
901        case RENDER_FIXED:
902       
903                glEnable(GL_MULTISAMPLE_ARB);
904               
905                state.SetRenderPassType(RenderState::FIXED);
906                glEnable(GL_LIGHTING);
907
908                loader->DisableFragmentProfile();
909                loader->DisableVertexProfile();
910
911                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
912
913                glEnableClientState(GL_NORMAL_ARRAY);
914
915                break;
916
917        case RENDER_DEPTH_PASS_DEFERRED:
918
919                glDisable(GL_MULTISAMPLE_ARB);
920                state.SetUseAlphaToCoverage(false);
921
922                state.SetRenderPassType(RenderState::DEPTH_PASS);
923
924                if (!fbo) InitFBO(); fbo->Bind();
925
926                glDrawBuffers(1, mrt);
927
928                loader->DisableFragmentProfile();
929                loader->DisableVertexProfile();
930
931                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
932
933                // the scene is rendered withouth any shading   
934                glShadeModel(GL_FLAT);
935                glDisable(GL_LIGHTING);
936                glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
937
938
939                break;
940
941        case RENDER_DEPTH_PASS:
942
943                glEnable(GL_MULTISAMPLE_ARB);
944               
945                loader->DisableFragmentProfile();
946                loader->DisableVertexProfile();
947
948                state.SetRenderPassType(RenderState::DEPTH_PASS);
949
950                // the scene is rendered withouth any shading   
951                glShadeModel(GL_FLAT);
952                glDisable(GL_LIGHTING);
953       
954                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
955                glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
956
957
958                break;
959       
960        case RenderState::DEFERRED:
961
962                if (showShadowMap && !renderLightView)
963                        RenderShadowMap(camera->GetFar());
964
965                //glPushAttrib(GL_VIEWPORT_BIT);
966                glViewport(0, 0, texWidth, texHeight);
967
968                InitDeferredRendering();
969               
970                glEnableClientState(GL_NORMAL_ARRAY);
971                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
972
973                break;
974        }
975
976        glDepthFunc(GL_LESS);
977
978        glDisable(GL_TEXTURE_2D);
979        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
980               
981
982        // reset lod levels for current frame
983        LODLevel::InitFrame(camera->GetPosition());
984
985        // set up lights
986        SetupLighting();
987
988
989        if (renderLightView)
990        {
991                // change CHC++ set of state variables (must be done for each change of camera because
992                // otherwise the temporal coherency is broken
993                BvhNode::SetCurrentState(1);
994                shadowMap->RenderShadowView(shadowTraverser, viewProjMat);
995                BvhNode::SetCurrentState(0);
996        }
997        else
998        {
999                // actually render the scene geometry using the specified algorithm
1000                traverser->RenderScene();
1001        }
1002
1003
1004        /////////
1005        //-- do the rest of the rendering
1006       
1007        // reset depth pass and render visible objects
1008        if ((renderMethod == RENDER_DEPTH_PASS) ||
1009                (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
1010        {
1011                RenderVisibleObjects();
1012        }
1013       
1014
1015        ///////////////
1016        //-- render sky
1017
1018        // q: should we render sky after deferred shading?
1019        // this would conveniently solves some issues (e.g, skys without shadows)
1020
1021        RenderSky();
1022
1023
1024        if ((renderMethod == RENDER_DEFERRED) ||
1025                (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
1026        {
1027                FrameBufferObject::Release();
1028
1029                loader->DisableVertexProfile();
1030                loader->DisableFragmentProfile();
1031
1032                if (!ssaoShader) ssaoShader =
1033                        new DeferredRenderer(texWidth, texHeight, camera, farDist / MAX_DEPTH_CONST);
1034               
1035                DeferredRenderer::SHADING_METHOD shadingMethod;
1036
1037                if (useAdvancedShading)
1038                {
1039                        if (useGlobIllum)
1040                                shadingMethod = DeferredRenderer::GI;
1041                        else
1042                                shadingMethod = DeferredRenderer::SSAO;
1043                }
1044                else
1045                        shadingMethod = DeferredRenderer::DEFAULT;
1046
1047
1048                ssaoShader->SetShadingMethod(shadingMethod);
1049                ssaoShader->SetSamplingMethod(samplingMethod);
1050                ssaoShader->SetUseTemporalCoherence(useTemporalCoherence);
1051
1052                ShadowMap *sm = showShadowMap ? shadowMap : NULL;
1053                ssaoShader->Render(fbo, oldViewProjMat, viewProjMat, ssaoTempCohFactor, light, useHDR, sm);
1054        }
1055
1056
1057        state.SetRenderPassType(RenderState::FIXED);
1058        state.Reset();
1059
1060
1061        glDisableClientState(GL_VERTEX_ARRAY);
1062        glDisableClientState(GL_NORMAL_ARRAY);
1063       
1064        renderMethod = oldRenderMethod;
1065
1066
1067        ///////////
1068
1069
1070        if (showAlgorithmTime)
1071        {
1072                glFinish();
1073
1074                algTime = algTimer.Elapsedms();
1075                perfGraph->AddData(algTime);
1076
1077                perfGraph->Draw();
1078        }
1079        else
1080        {
1081                if (visMode) DisplayVisualization();
1082        }
1083
1084        glFlush();
1085
1086        const bool restart = true;
1087        elapsedTime = frameTimer.Elapsedms(restart);
1088
1089        DisplayStats();
1090
1091        glutSwapBuffers();
1092}
1093
1094
1095#pragma warning( disable : 4100 )
1096void KeyBoard(unsigned char c, int x, int y)
1097{
1098        switch(c)
1099        {
1100        case 27:
1101                CleanUp();
1102                exit(0);
1103                break;
1104        case 32: // space
1105                renderMode = (renderMode + 1) % RenderTraverser::NUM_TRAVERSAL_TYPES;
1106
1107                DEL_PTR(traverser);
1108                traverser = CreateTraverser(camera);
1109
1110                if (shadowTraverser)
1111                {
1112                        // shadow traverser has to be recomputed
1113                        DEL_PTR(shadowTraverser);
1114                        shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
1115                }
1116
1117                break;
1118        case '+':
1119                if (maxBatchSize < 10)
1120                        maxBatchSize = 10;
1121                else
1122                        maxBatchSize += 10;
1123
1124                traverser->SetMaxBatchSize(maxBatchSize);
1125                break;
1126        case '-':
1127                maxBatchSize -= 10;
1128                if (maxBatchSize < 0) maxBatchSize = 1;
1129                traverser->SetMaxBatchSize(maxBatchSize);               
1130                break;
1131        case 'M':
1132        case 'm':
1133                useMultiQueries = !useMultiQueries;
1134                traverser->SetUseMultiQueries(useMultiQueries);
1135                break;
1136        case '1':
1137                descendKeyPressed = true;
1138                break;
1139        case '2':
1140                ascendKeyPressed = true;
1141                break;
1142        case '3':
1143                if (trianglesPerVirtualLeaf >= 100)
1144                        trianglesPerVirtualLeaf -= 100;
1145                bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
1146                break;
1147        case '4':
1148                trianglesPerVirtualLeaf += 100;
1149                bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
1150                break;
1151        case '5':
1152                assumedVisibleFrames -= 1;
1153                if (assumedVisibleFrames < 1) assumedVisibleFrames = 1;
1154                traverser->SetAssumedVisibleFrames(assumedVisibleFrames);
1155                break;
1156        case '6':
1157                assumedVisibleFrames += 1;
1158                traverser->SetAssumedVisibleFrames(assumedVisibleFrames);               
1159                break;
1160        case '7':
1161                ssaoTempCohFactor *= 0.5f;
1162                break;
1163        case '8':
1164                ssaoTempCohFactor *= 2.0f;
1165                //if (ssaoTempCohFactor > 1.0f) ssaoExpFactor = 1.0f;
1166                break;
1167        case '9':
1168                useLODs = !useLODs;
1169                SceneEntity::SetUseLODs(useLODs);
1170                break;
1171        case 'P':
1172        case 'p':
1173                samplingMethod = DeferredRenderer::SAMPLING_METHOD((samplingMethod + 1) % 3);
1174                cout << "ssao sampling method: " << samplingMethod << endl;
1175                break;
1176        case 'Y':
1177        case 'y':
1178                showShadowMap = !showShadowMap;
1179                break;
1180        case 'g':
1181        case 'G':
1182                useGlobIllum = !useGlobIllum;
1183                break;
1184        case 't':
1185        case 'T':
1186                useTemporalCoherence = !useTemporalCoherence;
1187                break;
1188        case 'o':
1189        case 'O':
1190                useOptimization = !useOptimization;
1191                traverser->SetUseOptimization(useOptimization);
1192                break;
1193        case 'a':
1194        case 'A':
1195                leftKeyPressed = true;
1196                break;
1197        case 'd':
1198        case 'D':
1199                rightKeyPressed = true;
1200                break;
1201        case 'w':
1202        case 'W':
1203                upKeyPressed = true;
1204                break;
1205        case 's':
1206        case 'S':
1207                downKeyPressed = true;
1208                break;
1209        case 'r':
1210        case 'R':
1211                useRenderQueue = !useRenderQueue;
1212                traverser->SetUseRenderQueue(useRenderQueue);
1213               
1214                break;
1215        case 'b':
1216        case 'B':
1217                useTightBounds = !useTightBounds;
1218                traverser->SetUseTightBounds(useTightBounds);
1219                break;
1220        case 'l':
1221        case 'L':
1222                renderLightView = !renderLightView;
1223                break;
1224        case 'h':
1225        case 'H':
1226                useHDR = !useHDR;
1227                break;
1228        default:
1229                return;
1230        }
1231
1232        glutPostRedisplay();
1233}
1234
1235
1236void SpecialKeyUp(int c, int x, int y)
1237{
1238        switch (c)
1239        {
1240        case GLUT_KEY_LEFT:
1241                leftKeyPressed = false;
1242                break;
1243        case GLUT_KEY_RIGHT:
1244                rightKeyPressed = false;
1245                break;
1246        case GLUT_KEY_UP:
1247                upKeyPressed = false;
1248                break;
1249        case GLUT_KEY_DOWN:
1250                downKeyPressed = false;
1251                break;
1252        case GLUT_ACTIVE_ALT:
1253                altKeyPressed = false;
1254                break;
1255        default:
1256                return;
1257        }
1258}
1259
1260
1261void KeyUp(unsigned char c, int x, int y)
1262{
1263        switch (c)
1264        {
1265
1266        case 'A':
1267        case 'a':
1268                leftKeyPressed = false;
1269                break;
1270        case 'D':
1271        case 'd':
1272                rightKeyPressed = false;
1273                break;
1274        case 'W':
1275        case 'w':
1276                upKeyPressed = false;
1277                break;
1278        case 'S':
1279        case 's':
1280                downKeyPressed = false;
1281                break;
1282        case '1':
1283                descendKeyPressed = false;
1284                break;
1285        case '2':
1286                ascendKeyPressed = false;
1287                break;
1288       
1289        default:
1290                return;
1291        }
1292        //glutPostRedisplay();
1293}
1294
1295
1296void Special(int c, int x, int y)
1297{
1298        switch(c)
1299        {
1300        case GLUT_KEY_F1:
1301                showHelp = !showHelp;
1302                break;
1303        case GLUT_KEY_F2:
1304                visMode = !visMode;
1305                break;
1306        case GLUT_KEY_F3:
1307                showBoundingVolumes = !showBoundingVolumes;
1308                traverser->SetShowBounds(showBoundingVolumes);
1309                break;
1310        case GLUT_KEY_F4:
1311                showOptions = !showOptions;
1312                break;
1313        case GLUT_KEY_F5:
1314                showStatistics = !showStatistics;
1315                break;
1316        case GLUT_KEY_F6:
1317                flyMode = !flyMode;
1318                break;
1319        case GLUT_KEY_F7:
1320
1321                renderMethod = (renderMethod + 1) % 4;
1322
1323                traverser->SetUseDepthPass(
1324                        (renderMethod == RENDER_DEPTH_PASS) ||
1325                        (renderMethod == RENDER_DEPTH_PASS_DEFERRED)
1326                        );
1327               
1328                break;
1329        case GLUT_KEY_F8:
1330                useAdvancedShading = !useAdvancedShading;
1331
1332                break;
1333        case GLUT_KEY_F9:
1334                showAlgorithmTime = !showAlgorithmTime;
1335                break;
1336        case GLUT_KEY_F10:
1337                moveLight = !moveLight;
1338                break;
1339        case GLUT_KEY_LEFT:
1340                {
1341                        leftKeyPressed = true;
1342                        camera->Pitch(KeyRotationAngle());
1343                }
1344                break;
1345        case GLUT_KEY_RIGHT:
1346                {
1347                        rightKeyPressed = true;
1348                        camera->Pitch(-KeyRotationAngle());
1349                }
1350                break;
1351        case GLUT_KEY_UP:
1352                {
1353                        upKeyPressed = true;
1354                        KeyHorizontalMotion(KeyShift());
1355                }
1356                break;
1357        case GLUT_KEY_DOWN:
1358                {
1359                        downKeyPressed = true;
1360                        KeyHorizontalMotion(-KeyShift());
1361                }
1362                break;
1363        default:
1364                return;
1365
1366        }
1367
1368        glutPostRedisplay();
1369}
1370
1371#pragma warning( default : 4100 )
1372
1373
1374void Reshape(int w, int h)
1375{
1376        winAspectRatio = 1.0f;
1377
1378        glViewport(0, 0, w, h);
1379       
1380        winWidth = w;
1381        winHeight = h;
1382
1383        if (w) winAspectRatio = (float) w / (float) h;
1384
1385        glMatrixMode(GL_PROJECTION);
1386        glLoadIdentity();
1387
1388        gluPerspective(fov, winAspectRatio, nearDist, farDist);
1389
1390        glMatrixMode(GL_MODELVIEW);
1391
1392        glutPostRedisplay();
1393}
1394
1395
1396void Mouse(int button, int state, int x, int y)
1397{
1398        if ((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN))
1399        {
1400                xEyeBegin = x;
1401                yMotionBegin = y;
1402
1403                glutMotionFunc(LeftMotion);
1404        }
1405        else if ((button == GLUT_RIGHT_BUTTON) && (state == GLUT_DOWN))
1406        {
1407                xEyeBegin = x;
1408                yEyeBegin = y;
1409                yMotionBegin = y;
1410
1411                if (!moveLight)
1412                        glutMotionFunc(RightMotion);
1413                else
1414                        glutMotionFunc(RightMotionLight);
1415        }
1416        else if ((button == GLUT_MIDDLE_BUTTON) && (state == GLUT_DOWN))
1417        {
1418                horizontalMotionBegin = x;
1419                verticalMotionBegin = y;
1420                glutMotionFunc(MiddleMotion);
1421        }
1422
1423        glutPostRedisplay();
1424}
1425
1426
1427/**     rotation for left/right mouse drag
1428        motion for up/down mouse drag
1429*/
1430void LeftMotion(int x, int y)
1431{
1432        Vector3 viewDir = camera->GetDirection();
1433        Vector3 pos = camera->GetPosition();
1434
1435        // don't move in the vertical direction
1436        Vector3 horView(viewDir[0], viewDir[1], 0);
1437       
1438        float eyeXAngle = 0.2f *  M_PI * (xEyeBegin - x) / 180.0;
1439
1440        camera->Pitch(eyeXAngle);
1441
1442        pos += horView * (yMotionBegin - y) * 0.2f;
1443       
1444        camera->SetPosition(pos);
1445       
1446        xEyeBegin = x;
1447        yMotionBegin = y;
1448
1449        glutPostRedisplay();
1450}
1451
1452
1453void RightMotionLight(int x, int y)
1454{
1455        float theta = 0.2f * M_PI * (xEyeBegin - x) / 180.0f;
1456        float phi = 0.2f * M_PI * (yMotionBegin - y) / 180.0f;
1457       
1458        Vector3 lightDir = light->GetDirection();
1459
1460        Matrix4x4 roty = RotationYMatrix(theta);
1461        Matrix4x4 rotx = RotationXMatrix(phi);
1462
1463        lightDir = roty * lightDir;
1464        lightDir = rotx * lightDir;
1465
1466        // normalize to avoid accumulating errors
1467        lightDir.Normalize();
1468
1469        light->SetDirection(lightDir);
1470
1471        xEyeBegin = x;
1472        yMotionBegin = y;
1473
1474        glutPostRedisplay();
1475}
1476
1477
1478/**     rotation for left / right mouse drag
1479        motion for up / down mouse drag
1480*/
1481void RightMotion(int x, int y)
1482{
1483        float eyeXAngle = 0.2f *  M_PI * (xEyeBegin - x) / 180.0;
1484        float eyeYAngle = -0.2f *  M_PI * (yEyeBegin - y) / 180.0;
1485
1486        camera->Yaw(eyeYAngle);
1487        camera->Pitch(eyeXAngle);
1488
1489        xEyeBegin = x;
1490        yEyeBegin = y;
1491
1492        glutPostRedisplay();
1493}
1494
1495
1496// strafe
1497void MiddleMotion(int x, int y)
1498{
1499        Vector3 viewDir = camera->GetDirection();
1500        Vector3 pos = camera->GetPosition();
1501
1502        // the 90 degree rotated view vector
1503        // y zero so we don't move in the vertical
1504        Vector3 rVec(viewDir[0], viewDir[1], 0);
1505       
1506        Matrix4x4 rot = RotationZMatrix(M_PI * 0.5f);
1507        rVec = rot * rVec;
1508       
1509        pos -= rVec * (x - horizontalMotionBegin) * 0.1f;
1510        pos[2] += (verticalMotionBegin - y) * 0.1f;
1511
1512        camera->SetPosition(pos);
1513
1514        horizontalMotionBegin = x;
1515        verticalMotionBegin = y;
1516
1517        glutPostRedisplay();
1518}
1519
1520
1521void InitExtensions(void)
1522{
1523        GLenum err = glewInit();
1524
1525        if (GLEW_OK != err)
1526        {
1527                // problem: glewInit failed, something is seriously wrong
1528                fprintf(stderr,"Error: %s\n", glewGetErrorString(err));
1529                exit(1);
1530        }
1531        if  (!GLEW_ARB_occlusion_query)
1532        {
1533                printf("I require the GL_ARB_occlusion_query to work.\n");
1534                exit(1);
1535        }
1536}
1537
1538
1539void Begin2D()
1540{
1541        glDisable(GL_LIGHTING);
1542        glDisable(GL_DEPTH_TEST);
1543
1544        glMatrixMode(GL_PROJECTION);
1545        glPushMatrix();
1546        glLoadIdentity();
1547
1548        gluOrtho2D(0, winWidth, 0, winHeight);
1549
1550        glMatrixMode(GL_MODELVIEW);
1551        glPushMatrix();
1552        glLoadIdentity();
1553}
1554
1555
1556void End2D()
1557{
1558        glMatrixMode(GL_PROJECTION);
1559        glPopMatrix();
1560
1561        glMatrixMode(GL_MODELVIEW);
1562        glPopMatrix();
1563
1564        glEnable(GL_LIGHTING);
1565        glEnable(GL_DEPTH_TEST);
1566}
1567
1568
1569// displays the visualisation of culling algorithm
1570void DisplayVisualization()
1571{
1572        visualization->SetFrameId(traverser->GetCurrentFrameId());
1573       
1574        Begin2D();
1575        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1576        glEnable(GL_BLEND);
1577        glColor4f(0.0f ,0.0f, 0.0f, 0.5f);
1578
1579        glRecti(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth, winHeight);
1580        glDisable(GL_BLEND);
1581        End2D();
1582       
1583       
1584        AxisAlignedBox3 box = bvh->GetBox();
1585
1586        const float offs = box.Size().x * 0.3f;
1587       
1588        Vector3 vizpos = Vector3(box.Min().x, box.Min().y  - box.Size().y * 0.35f, box.Min().z + box.Size().z * 50);
1589       
1590        visCamera->SetPosition(vizpos);
1591        visCamera->ResetPitchAndYaw();
1592       
1593        glPushAttrib(GL_VIEWPORT_BIT);
1594        glViewport(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth / 3, winHeight / 3);
1595
1596        glMatrixMode(GL_PROJECTION);
1597        glPushMatrix();
1598
1599        glLoadIdentity();
1600       
1601        glOrtho(-offs, offs, -offs, offs, 0.0f, box.Size().z * 100.0f);
1602
1603        glMatrixMode(GL_MODELVIEW);
1604        glPushMatrix();
1605
1606        visCamera->SetupCameraView();
1607
1608        Matrix4x4 rotZ = RotationZMatrix(-camera->GetPitch());
1609        glMultMatrixf((float *)rotZ.x);
1610
1611        // inverse translation in order to fix current position
1612        Vector3 pos = camera->GetPosition();
1613        glTranslatef(-pos.x, -pos.y, -pos.z);
1614
1615
1616        GLfloat position[] = {0.8f, 1.0f, 1.5f, 0.0f};
1617        glLightfv(GL_LIGHT0, GL_POSITION, position);
1618
1619        GLfloat position1[] = {bvh->GetBox().Center().x, bvh->GetBox().Max().y, bvh->GetBox().Center().z, 1.0f};
1620        glLightfv(GL_LIGHT1, GL_POSITION, position1);
1621
1622        glClear(GL_DEPTH_BUFFER_BIT);
1623
1624
1625        ////////////
1626        //-- visualization of the occlusion culling
1627
1628        visualization->Render();
1629
1630       
1631        // reset previous settings
1632        glPopAttrib();
1633
1634        glMatrixMode(GL_PROJECTION);
1635        glPopMatrix();
1636        glMatrixMode(GL_MODELVIEW);
1637        glPopMatrix();
1638}
1639
1640
1641// cleanup routine after the main loop
1642void CleanUp()
1643{
1644        DEL_PTR(traverser);
1645        DEL_PTR(sceneQuery);
1646        DEL_PTR(bvh);
1647        DEL_PTR(visualization);
1648        DEL_PTR(camera);
1649        DEL_PTR(renderQueue);
1650        DEL_PTR(perfGraph);
1651        DEL_PTR(fbo);
1652        DEL_PTR(ssaoShader);
1653        DEL_PTR(light);
1654        DEL_PTR(visCamera);
1655        DEL_PTR(preetham);
1656        DEL_PTR(shadowMap);
1657        DEL_PTR(shadowTraverser);
1658       
1659        ResourceManager::DelSingleton();
1660        loader = NULL;
1661}
1662
1663
1664// this function inserts a dezimal point after each 1000
1665void CalcDecimalPoint(string &str, int d, int len)
1666{
1667        static vector<int> numbers;
1668        numbers.clear();
1669
1670        static string shortStr;
1671        shortStr.clear();
1672
1673        static char hstr[100];
1674
1675        while (d != 0)
1676        {
1677                numbers.push_back(d % 1000);
1678                d /= 1000;
1679        }
1680
1681        // first element without leading zeros
1682        if (numbers.size() > 0)
1683        {
1684                sprintf(hstr, "%d", numbers.back());
1685                shortStr.append(hstr);
1686        }
1687       
1688        for (int i = (int)numbers.size() - 2; i >= 0; i--)
1689        {
1690                sprintf(hstr, ",%03d", numbers[i]);
1691                shortStr.append(hstr);
1692        }
1693
1694        int dif = len - (int)shortStr.size();
1695
1696        for (int i = 0; i < dif; ++ i)
1697        {
1698                str += " ";
1699        }
1700
1701        str.append(shortStr);
1702}
1703
1704
1705void DisplayStats()
1706{
1707        static char msg[9][300];
1708
1709        static double frameTime = elapsedTime;
1710        static double renderTime = algTime;
1711
1712        const float expFactor = 0.1f;
1713
1714        // if some strange render time spike happened in this frame => don't count
1715        if (elapsedTime < 500) frameTime = elapsedTime * expFactor + (1.0f - expFactor) * elapsedTime;
1716       
1717        static float rTime = 1000.0f;
1718
1719        if (showAlgorithmTime)
1720        {
1721                if (algTime < 500) renderTime = algTime * expFactor + (1.0f - expFactor) * renderTime;
1722        }
1723
1724        accumulatedTime += elapsedTime;
1725
1726        if (accumulatedTime > 500) // update every fraction of a second
1727        {       
1728                accumulatedTime = 0;
1729
1730                if (frameTime) fps = 1e3f / (float)frameTime;
1731
1732                rTime = renderTime;
1733
1734                if (renderLightView && shadowTraverser)
1735                {
1736                        renderedTriangles = shadowTraverser->GetStats().mNumRenderedTriangles;
1737                        renderedObjects = shadowTraverser->GetStats().mNumRenderedGeometry;
1738                        renderedNodes = shadowTraverser->GetStats().mNumRenderedNodes;
1739                }
1740                else if (showShadowMap && shadowTraverser)
1741                {
1742                        renderedNodes = traverser->GetStats().mNumRenderedNodes + shadowTraverser->GetStats().mNumRenderedNodes;
1743                        renderedObjects = traverser->GetStats().mNumRenderedGeometry + shadowTraverser->GetStats().mNumRenderedGeometry;
1744                        renderedTriangles = traverser->GetStats().mNumRenderedTriangles + shadowTraverser->GetStats().mNumRenderedTriangles;
1745                }
1746                else
1747                {
1748                        renderedTriangles = traverser->GetStats().mNumRenderedTriangles;
1749                        renderedObjects = traverser->GetStats().mNumRenderedGeometry;
1750                        renderedNodes = traverser->GetStats().mNumRenderedNodes;
1751                }
1752
1753                traversedNodes = traverser->GetStats().mNumTraversedNodes;
1754                frustumCulledNodes = traverser->GetStats().mNumFrustumCulledNodes;
1755                queryCulledNodes = traverser->GetStats().mNumQueryCulledNodes;
1756                issuedQueries = traverser->GetStats().mNumIssuedQueries;
1757                stateChanges = traverser->GetStats().mNumStateChanges;
1758                numBatches = traverser->GetStats().mNumBatches;
1759        }
1760
1761
1762        Begin2D();
1763
1764        glEnable(GL_BLEND);
1765        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1766
1767        if (showHelp)
1768        {       
1769                DrawHelpMessage();
1770        }
1771        else
1772        {
1773                if (showOptions)
1774                {
1775                        glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
1776                        glRecti(5, winHeight - 95, winWidth * 2 / 3 - 5, winHeight - 5);
1777                }
1778
1779                if (showStatistics)
1780                {
1781                        glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
1782                        glRecti(5, winHeight - 165, winWidth * 2 / 3 - 5, winHeight - 100);
1783                }
1784
1785                glEnable(GL_TEXTURE_2D);
1786
1787                myfont.Begin();
1788
1789                if (showOptions)
1790                {
1791                        glColor3f(0.0f, 1.0f, 0.0f);
1792
1793                        int i = 0;
1794
1795                        static char *renderMethodStr[] = {"forward", "depth pass + forward", "deferred shading", "depth pass + deferred"};
1796       
1797                        sprintf(msg[i ++], "multiqueries: %d, tight bounds: %d, render queue: %d",
1798                                                        useMultiQueries, useTightBounds, useRenderQueue);
1799
1800                        sprintf(msg[i ++], "render technique: %s, SSAO: %d", renderMethodStr[renderMethod], useAdvancedShading);
1801
1802                        sprintf(msg[i ++], "triangles per virtual leaf: %5d", trianglesPerVirtualLeaf);
1803
1804                        sprintf(msg[i ++], "assumed visible frames: %4d, max batch size: %4d",
1805                                assumedVisibleFrames, maxBatchSize);
1806
1807                        for (int j = 0; j < 4; ++ j)
1808                                myfont.DrawString(msg[j], 10.0f, winHeight - 5 - j * 20);
1809                }
1810
1811                if (showStatistics)
1812                {
1813                        glColor3f(1.0f, 1.0f, 0.0f);
1814
1815                        string objStr, totalObjStr;
1816                        string triStr, totalTriStr;
1817
1818                        int len = 10;
1819                        CalcDecimalPoint(objStr, renderedObjects, len);
1820                        CalcDecimalPoint(totalObjStr, (int)loader->GetNumEntities(), len);
1821
1822                        CalcDecimalPoint(triStr, renderedTriangles, len);
1823                        CalcDecimalPoint(totalTriStr, bvh->GetBvhStats().mTriangles, len);
1824
1825                        int i = 4;
1826
1827                        if (0)
1828                        {
1829                                sprintf(msg[i ++], "rendered: %s of %s objects, %s of %s triangles",
1830                                        objStr.c_str(), totalObjStr.c_str(), triStr.c_str(), totalTriStr.c_str());
1831                        }
1832                        else
1833                        {
1834                                sprintf(msg[i ++], "rendered: %6d of %6d nodes, %s of %s triangles",
1835                                        renderedNodes, bvh->GetNumVirtualNodes(), triStr.c_str(), totalTriStr.c_str());
1836                        }
1837
1838                        sprintf(msg[i ++], "traversed: %5d, frustum culled: %5d, query culled: %5d",
1839                                traversedNodes, frustumCulledNodes, queryCulledNodes);
1840
1841                        sprintf(msg[i ++], "issued queries: %5d, state changes: %5d, render batches: %5d",
1842                                issuedQueries, stateChanges, numBatches);
1843
1844                        for (int j = 4; j < 7; ++ j)
1845                                myfont.DrawString(msg[j], 10.0f, winHeight - (j + 1) * 20);
1846                }
1847
1848                glColor3f(1.0f, 1.0f, 1.0f);
1849                static char *alg_str[] = {"Frustum Cull", "Stop and Wait", "CHC", "CHC ++"};
1850               
1851                if (!showAlgorithmTime)
1852                                sprintf(msg[7], "%s:  %6.1f fps", alg_str[renderMode], fps);
1853                else
1854                        sprintf(msg[7], "%s:  %6.1f ms", alg_str[renderMode], rTime);
1855               
1856                myfont.DrawString(msg[7], 1.3f, 690.0f, 760.0f);//, top_color, bottom_color);
1857               
1858                //sprintf(msg[8], "algorithm time: %6.1f ms", rTime);
1859                //myfont.DrawString(msg[8], 720.0f, 730.0f);           
1860        }
1861
1862        glDisable(GL_BLEND);
1863        glDisable(GL_TEXTURE_2D);
1864
1865        End2D();
1866}       
1867
1868
1869void RenderSky()
1870{
1871        loader->EnableVertexProfile();
1872        loader->EnableFragmentProfile();
1873
1874        if ((renderMethod == RENDER_DEFERRED) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
1875                state.SetRenderPassType(RenderState::DEFERRED);
1876
1877        const bool useToneMapping =
1878                ((renderMethod == RENDER_DEPTH_PASS_DEFERRED) ||
1879                 (renderMethod == RENDER_DEFERRED)) && useHDR;
1880
1881        preetham->RenderSkyDome(-light->GetDirection(), camera, &state, !useToneMapping);
1882
1883        loader->DisableVertexProfile();
1884        loader->DisableFragmentProfile();
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                        float minVisibleDist = min(camera->GetFar(), traverser->GetMaxVisibleDistance());
1896                        RenderShadowMap(minVisibleDist);
1897                }
1898
1899                glDisable(GL_LIGHTING);
1900                glViewport(0, 0, texWidth, texHeight);
1901
1902                state.Reset();
1903                InitDeferredRendering();
1904        }
1905        else
1906        {
1907                glEnable(GL_LIGHTING);
1908                state.SetRenderPassType(RenderState::FIXED);
1909                state.Reset();
1910        }
1911
1912        glShadeModel(GL_SMOOTH);
1913        glEnableClientState(GL_NORMAL_ARRAY);
1914
1915        // draw all objects that have exactly the same depth as the current sample
1916        glDepthFunc(GL_LEQUAL);
1917        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1918
1919        glClear(GL_COLOR_BUFFER_BIT);
1920
1921        state.SetUseAlphaToCoverage(true);
1922       
1923
1924        //cout << "visible: " << (int)traverser->GetVisibleObjects().size() << endl;
1925
1926        SceneEntityContainer::const_iterator sit,
1927                sit_end = traverser->GetVisibleObjects().end();
1928
1929        for (sit = traverser->GetVisibleObjects().begin(); sit != sit_end; ++ sit)
1930        {
1931                renderQueue->Enqueue(*sit);
1932        }
1933
1934        renderQueue->Apply();
1935
1936        glDepthFunc(GL_LESS);
1937        state.Reset();
1938
1939        PrintGLerror("visibleobjects");
1940}
1941
1942
1943void PlaceViewer(const Vector3 &oldPos)
1944{
1945        if (!sceneQuery)
1946                sceneQuery = new SceneQuery(bvh->GetBox(), traverser);
1947
1948        Vector3 playerPos = camera->GetPosition();
1949        bool validIntersect = sceneQuery->CalcIntersection(playerPos);
1950
1951        if (validIntersect)
1952                // && ((playerPos.z - oldPos.z) < bvh->GetBox().Size(2) * 1e-1f))
1953        {
1954                camera->SetPosition(playerPos);
1955        }
1956}
1957
1958
1959void RenderShadowMap(float newfar)
1960{
1961        loader->DisableVertexProfile();
1962        loader->DisableFragmentProfile();
1963
1964        glDisableClientState(GL_NORMAL_ARRAY);
1965
1966        state.SetRenderPassType(RenderState::DEPTH_PASS);
1967       
1968        // hack: disable cull face because of alpha textured balconies
1969        glDisable(GL_CULL_FACE);
1970        state.LockCullFaceEnabled(true);
1971
1972        state.SetUseAlphaToCoverage(false);
1973
1974        // change CHC++ set of state variables
1975        // this must be done for each change of camera because
1976        // otherwise the temporal coherency is broken
1977        BvhNode::SetCurrentState(1);
1978
1979        // hack: temporarily change camera far plane
1980        camera->SetFar(newfar);
1981
1982        // the scene is rendered withouth any shading   
1983        shadowMap->ComputeShadowMap(shadowTraverser, viewProjMat);
1984
1985        glEnable(GL_CULL_FACE);
1986        camera->SetFar(farDist);
1987
1988        state.SetUseAlphaToCoverage(true);
1989        state.LockCullFaceEnabled(false);
1990
1991        glEnableClientState(GL_NORMAL_ARRAY);
1992
1993        // change back state
1994        BvhNode::SetCurrentState(0);
1995}
Note: See TracBrowser for help on using the repository browser.