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

Revision 3046, 45.6 KB checked in by mattausch, 16 years ago (diff)

added shader for forward shadin tree animation program

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