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

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