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

Revision 3221, 58.5 KB checked in by mattausch, 16 years ago (diff)

added some statistics stuff, but ssao slower than before (probably because made ssao width and intensity variable and not hardcoded anymore) from >180 frames to < 130 frames!!!

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