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

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