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

Revision 3014, 50.0 KB checked in by mattausch, 16 years ago (diff)

removed eyepos from sssao shader, played around with maxdepth

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