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

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