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

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