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!!!

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