// chcdemo.cpp : Defines the entry point for the console application. // #include "common.h" #ifdef _CRT_SET #define _CRTDBG_MAP_ALLOC #include #include // redefine new operator #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) #define new DEBUG_NEW #endif #include #include #include "glInterface.h" #include "RenderTraverser.h" #include "SceneEntity.h" #include "Vector3.h" #include "Matrix4x4.h" #include "ResourceManager.h" #include "Bvh.h" #include "Camera.h" #include "Geometry.h" #include "BvhLoader.h" #include "FrustumCullingTraverser.h" #include "StopAndWaitTraverser.h" #include "CHCTraverser.h" #include "CHCPlusPlusTraverser.h" #include "Visualization.h" #include "RenderState.h" #include "Timer/PerfTimer.h" #include "SceneQuery.h" #include "RenderQueue.h" #include "Material.h" #include "glfont2.h" #include "PerformanceGraph.h" #include "Environment.h" #include "Halton.h" #include "Transform3.h" #include "SampleGenerator.h" #include "FrameBufferObject.h" #include "DeferredRenderer.h" #include "ShadowMapping.h" #include "Light.h" #include "SceneEntityConverter.h" #include "SkyPreetham.h" #include "Texture.h" #include "ShaderManager.h" #include "MotionPath.h" #include "ShaderProgram.h" #include "Shape.h" #include "WalkThroughRecorder.h" #include "StatsWriter.h" #include "VisibilitySolutionLoader.h" #include "ViewCellsTree.h" #include "PvsCollectionRenderer.h" #include "ObjExporter.h" #include "BvhExporter.h" using namespace std; using namespace CHCDemoEngine; /// the environment for the program parameter static Environment env; GLuint fontTex; /// the fbo used for MRT FrameBufferObject *fbo = NULL; /// the renderable scene geometry SceneEntityContainer staticObjects; /// the dynamic objects in the scene SceneEntityContainer dynamicObjects; // traverses and renders the hierarchy RenderTraverser *traverser = NULL; /// the hierarchy Bvh *bvh = NULL; /// handles scene loading ResourceManager *resourceManager = NULL; /// handles scene loading ShaderManager *shaderManager = NULL; /// the scene camera PerspectiveCamera *camera = NULL; /// the scene camera PerspectiveCamera *visCamera = NULL; /// the visualization Visualization *visualization = NULL; /// the current render renderState RenderState renderState; /// the rendering algorithm int renderMode = RenderTraverser::CHCPLUSPLUS; /// eye near plane distance const float nearDist = 0.2f; //const float nearDist = 1.0f; /// eye far plane distance float farDist = 1e6f; /// the field of view const float fov = 50.0f; float skyDomeScaleFactor = 80.0f; SceneQuery *sceneQuery = NULL; RenderQueue *renderQueue = NULL; /// traverses and renders the hierarchy RenderTraverser *shadowTraverser = NULL; /// the skylight + skydome model SkyPreetham *preetham = NULL; MotionPath *motionPath = NULL; /// max depth where candidates for tighter bounds are searched int maxDepthForTestingChildren = 3; /// use full resolution for ssao or half bool ssaoUseFullResolution = false; /// store the frames as tga bool recordFrames = false; /// record the taken path bool recordPath = false; /// replays the recorded path bool replayPath = false; /// frame number for replay int currentReplayFrame = -1; string recordedFramesSuffix("frames"); string statsFilename("stats"); string filename("city"); string bvhname(""); string visibilitySolution(""); /// the walkThroughRecorder WalkThroughRecorder *walkThroughRecorder = NULL; WalkThroughPlayer *walkThroughPlayer = NULL; StatsWriter *statsWriter = NULL; bool makeSnapShot = false; ViewCellsTree *viewCellsTree = NULL; ViewCell *viewCell = NULL; bool useSkylightForIllum = true; bool showFPS = true; static int globalVisibleId = 0; PerfTimer applicationTimer; float shotRays = .0f; /// the visibility solution is initialized at this number of rays shot that int visibilitySolutionInitialState = 0; Vector3 defaultAmbient(0.2f); Vector3 defaultDiffuse(1.0f); /// the technique used for rendering enum RenderTechnique { FORWARD, DEFERRED, DEPTH_PASS }; /// the used render type for this render pass enum RenderMethod { RENDER_FORWARD, RENDER_DEPTH_PASS, RENDER_DEFERRED, RENDER_DEPTH_PASS_DEFERRED, RENDER_NUM_RENDER_TYPES }; /// one of four possible render methods int renderMethod = RENDER_FORWARD; static int winWidth = 1024; static int winHeight = 768; static float winAspectRatio = 1.0f; /// these values get scaled with the frame rate static float keyForwardMotion = 30.0f; static float keyRotation = 1.5f; /// elapsed time in milliseconds double elapsedTime = 1000.0; double algTime = 1000.0; double accumulatedTime = 1000.0; float fps = 1e3f; float turbitity = 5.0f; // ssao parameters float ssaoKernelRadius = 1e-8f; float ssaoSampleIntensity = 0.2f; float ssaoFilterRadius = 3.0f; float ssaoTempCohFactor = 255.0; bool sortSamples = true; int shadowSize = 2048; /// the hud font glfont::GLFont myfont; // rendertexture int texWidth = 1024; int texHeight = 768; int renderedObjects = 0; int renderedNodes = 0; int renderedTriangles = 0; int issuedQueries = 0; int traversedNodes = 0; int frustumCulledNodes = 0; int queryCulledNodes = 0; int stateChanges = 0; int numBatches = 0; // mouse navigation renderState int xEyeBegin = 0; int yEyeBegin = 0; int yMotionBegin = 0; int verticalMotionBegin = 0; int horizontalMotionBegin = 0; bool leftKeyPressed = false; bool rightKeyPressed = false; bool upKeyPressed = false; bool downKeyPressed = false; bool descendKeyPressed = false; bool ascendKeyPressed = false; bool leftStrafeKeyPressed = false; bool rightStrafeKeyPressed = false; bool altKeyPressed = false; bool showHelp = false; bool showStatistics = false; bool showOptions = true; bool showBoundingVolumes = false; bool visMode = false; bool useOptimization = false; bool useTightBounds = true; bool useRenderQueue = true; bool useMultiQueries = true; bool flyMode = true; bool useGlobIllum = false; bool useTemporalCoherence = true; bool showAlgorithmTime = false; bool useFullScreen = false; bool useLODs = true; bool moveLight = false; bool useAdvancedShading = false; bool showShadowMap = false; bool renderLightView = false; bool useHDR = true; bool useAntiAliasing = true; bool useLenseFlare = true; bool usePvs = false; PerfTimer frameTimer, algTimer; /// the performance graph window PerformanceGraph *perfGraph = NULL; int sCurrentMrtSet = 0; static Matrix4x4 invTrafo = IdentityMatrix(); float mouseMotion = 0.2f; float viewCellsScaleFactor = 1.0f; float maxConvergence = 2000.0f; ////////////// //-- chc++ algorithm parameters /// the pixel threshold where a node is still considered invisible /// (should be zero for conservative visibility) int threshold; int assumedVisibleFrames = 10; int maxBatchSize = 50; int trianglesPerVirtualLeaf = INITIAL_TRIANGLES_PER_VIRTUAL_LEAVES; ////////////// enum {CAMERA_PASS = 0, LIGHT_PASS = 1}; //DeferredRenderer::SAMPLING_METHOD samplingMethod = DeferredRenderer::SAMPLING_POISSON; DeferredRenderer::SAMPLING_METHOD samplingMethod = DeferredRenderer::SAMPLING_QUADRATIC; ShadowMap *shadowMap = NULL; DirectionalLight *light = NULL; DeferredRenderer *deferredShader = NULL; SceneEntity *buddha = NULL; SceneEntity *skyDome = NULL; SceneEntity *sunBox = NULL; GLuint sunQuery = 0; string walkThroughSuffix("frames"); //////////////////// //--- function forward declarations void InitExtensions(); void InitGLstate(); void DisplayVisualization(); /// destroys all allocated resources void CleanUp(); void SetupEyeView(); void SetupLighting(); void DisplayStats(); /// draw the help screen void DrawHelpMessage(); /// render the sky dome void RenderSky(); /// render the objects found visible in the depth pass void RenderVisibleObjects(); int TestSunVisible(); void Begin2D(); void End2D(); /// the main loop void MainLoop(); void KeyBoard(unsigned char c, int x, int y); void Special(int c, int x, int y); void KeyUp(unsigned char c, int x, int y); void SpecialKeyUp(int c, int x, int y); void Reshape(int w, int h); void Mouse(int button, int renderState, int x, int y); void LeftMotion(int x, int y); void RightMotion(int x, int y); void MiddleMotion(int x, int y); void KeyHorizontalMotion(float shift); void KeyVerticalMotion(float shift); /// returns the string representation of a number with the decimal points void CalcDecimalPoint(string &str, int d); /// Creates the traversal method (vfc, stopandwait, chc, chc++) RenderTraverser *CreateTraverser(PerspectiveCamera *cam); /// place the viewer on the floor plane void PlaceViewer(const Vector3 &oldPos); // initialise the frame buffer objects void InitFBO(); /// changes the sunlight direction void RightMotionLight(int x, int y); /// render the shader map void RenderShadowMap(float newfar); /// function that touches each material once in order to accelarate render queue void PrepareRenderQueue(); /// loads the specified model int LoadModel(const string &model, SceneEntityContainer &entities); inline float KeyRotationAngle() { return keyRotation * elapsedTime * 1e-3f; } inline float KeyShift() { return keyForwardMotion * elapsedTime * 1e-3f; } void CreateAnimation(const Vector3 &pos); SceneQuery *GetOrCreateSceneQuery(); void LoadPvs(); void LoadVisibilitySolution(); void RenderViewCell(); void LoadPompeiiFloor(); void LoadOrUpdatePVSs(const Vector3 &pos); void CreateNewInstance(SceneEntity *parent, const Vector3 &pos); ///////////// string envFileName = "default.env"; float pvsTotalSamples = .0f; float pvsTotalTime = .0f; // new view projection matrix of the camera static Matrix4x4 viewProjMat = IdentityMatrix(); // the old view projection matrix of the camera static Matrix4x4 oldViewProjMat = IdentityMatrix(); static void PrintGLerror(char *msg) { GLenum errCode; const GLubyte *errStr; if ((errCode = glGetError()) != GL_NO_ERROR) { errStr = gluErrorString(errCode); fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg); } } int main(int argc, char* argv[]) { #ifdef _CRT_SET //Now just call this function at the start of your program and if you're //compiling in debug mode (F5), any leaks will be displayed in the Output //window when the program shuts down. If you're not in debug mode this will //be ignored. Use it as you will! //note: from GDNet Direct [3.8.04 - 3.14.04] void detectMemoryLeaks() { _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF); _CrtSetReportMode(_CRT_ASSERT,_CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ASSERT,_CRTDBG_FILE_STDERR); #endif int returnCode = 0; Vector3 camPos(.0f, .0f, .0f); Vector3 camDir(.0f, 1.0f, .0f); Vector3 lightDir(-0.8f, 1.0f, -0.7f); if (argc > 1) envFileName = argv[1]; cout << "=== reading environment file " << envFileName << " ===" << endl << endl; if (!env.Read(envFileName)) { cerr << "loading environment " << envFileName << " failed!" << endl; } else { env.GetIntParam(string("assumedVisibleFrames"), assumedVisibleFrames); env.GetIntParam(string("maxBatchSize"), maxBatchSize); env.GetIntParam(string("trianglesPerVirtualLeaf"), trianglesPerVirtualLeaf); env.GetIntParam(string("winWidth"), winWidth); env.GetIntParam(string("winHeight"), winHeight); env.GetIntParam(string("shadowSize"), shadowSize); env.GetIntParam(string("maxDepthForTestingChildren"), maxDepthForTestingChildren); env.GetFloatParam(string("keyForwardMotion"), keyForwardMotion); env.GetFloatParam(string("keyRotation"), keyRotation); env.GetFloatParam(string("mouseMotion"), mouseMotion); env.GetFloatParam(string("tempCohFactor"), ssaoTempCohFactor); env.GetFloatParam(string("turbitity"), turbitity); env.GetVectorParam(string("camPosition"), camPos); env.GetVectorParam(string("camDirection"), camDir); env.GetVectorParam(string("lightDirection"), lightDir); env.GetVectorParam(string("defaultAmbient"), defaultAmbient); env.GetVectorParam(string("defaultDiffuse"), defaultDiffuse); env.GetBoolParam(string("useFullScreen"), useFullScreen); env.GetBoolParam(string("useLODs"), useLODs); env.GetBoolParam(string("useHDR"), useHDR); env.GetBoolParam(string("useAA"), useAntiAliasing); env.GetBoolParam(string("useLenseFlare"), useLenseFlare); env.GetBoolParam(string("useAdvancedShading"), useAdvancedShading); env.GetIntParam(string("renderMethod"), renderMethod); env.GetFloatParam(string("ssaoKernelRadius"), ssaoKernelRadius); env.GetFloatParam(string("ssaoSampleIntensity"), ssaoSampleIntensity); env.GetBoolParam(string("ssaoUseFullResolution"), ssaoUseFullResolution); env.GetStringParam(string("recordedFramesSuffix"), recordedFramesSuffix); env.GetStringParam(string("walkThroughSuffix"), walkThroughSuffix); env.GetStringParam(string("statsFilename"), statsFilename); env.GetStringParam(string("filename"), filename); env.GetStringParam(string("bvhname"), bvhname); env.GetStringParam(string("visibilitySolution"), visibilitySolution); env.GetBoolParam(string("usePvs"), usePvs); env.GetBoolParam(string("useSkylightForIllum"), useSkylightForIllum); env.GetFloatParam(string("viewCellsScaleFactor"), viewCellsScaleFactor); env.GetFloatParam(string("skyDomeScaleFactor"), skyDomeScaleFactor); env.GetIntParam(string("visibilitySolutionInitialState"), visibilitySolutionInitialState); env.GetIntParam(string("renderMode"), renderMode); //env.GetStringParam(string("modelPath"), model_path); //env.GetIntParam(string("numSssaoSamples"), numSsaoSamples); texWidth = winWidth; texHeight = winHeight; cout << "assumed visible frames: " << assumedVisibleFrames << endl; cout << "max batch size: " << maxBatchSize << endl; cout << "triangles per virtual leaf: " << trianglesPerVirtualLeaf << endl; cout << "static scene filename prefix: " << filename << endl; cout << "bvh filename prefix: " << bvhname << endl; cout << "key forward motion: " << keyForwardMotion << endl; cout << "key rotation: " << keyRotation << endl; cout << "win width: " << winWidth << endl; cout << "win height: " << winHeight << endl; cout << "use full screen: " << useFullScreen << endl; cout << "use LODs: " << useLODs << endl; cout << "camera position: " << camPos << endl; cout << "shadow size: " << shadowSize << endl; cout << "render method: " << renderMethod << endl; cout << "use antialiasing: " << useAntiAliasing << endl; cout << "use lense flare: " << useLenseFlare << endl; cout << "use advanced shading: " << useAdvancedShading << endl; cout << "turbitity: " << turbitity << endl; cout << "temporal coherence factor: " << ssaoTempCohFactor << endl; cout << "sample intensity: " << ssaoSampleIntensity << endl; cout << "kernel radius: " << ssaoKernelRadius << endl; cout << "use ssao full resolution: " << ssaoUseFullResolution << endl; cout << "recorded frames suffix: " << recordedFramesSuffix << endl; cout << "walkthrough suffix: " << walkThroughSuffix << endl; cout << "stats filename: " << statsFilename << endl; cout << "use PVSs: " << usePvs << endl; cout << "visibility solution: " << visibilitySolution << endl; cout << "view cells scale factor: " << viewCellsScaleFactor << endl; cout << "use skylight for illumination: " << useSkylightForIllum << endl; cout << "sky dome scale factor: " << skyDomeScaleFactor << endl; cout << "rendermode: " << renderMode << endl; //cout << "model path: " << model_path << endl; cout << "==== end parameters ====" << endl << endl; } /////////////////////////// camera = new PerspectiveCamera(winWidth / winHeight, fov); camera->SetNear(nearDist); camera->SetFar(1000); camera->SetDirection(camDir); camera->SetPosition(camPos); visCamera = new PerspectiveCamera(winWidth / winHeight, fov); visCamera->SetNear(0.0f); visCamera->Yaw(.5 * M_PI); // create a new light light = new DirectionalLight(lightDir, RgbaColor(1, 1, 1, 1), RgbaColor(1, 1, 1, 1)); // the render queue for material sorting renderQueue = new RenderQueue(&renderState); glutInitWindowSize(winWidth, winHeight); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE); //glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); //glutInitDisplayString("samples=2"); SceneEntity::SetUseLODs(useLODs); if (!useFullScreen) { glutCreateWindow("FriendlyCulling"); } else { glutGameModeString( "1024x768:32@75" ); glutEnterGameMode(); } glutDisplayFunc(MainLoop); glutKeyboardFunc(KeyBoard); glutSpecialFunc(Special); glutReshapeFunc(Reshape); glutMouseFunc(Mouse); glutIdleFunc(MainLoop); glutKeyboardUpFunc(KeyUp); glutSpecialUpFunc(SpecialKeyUp); glutIgnoreKeyRepeat(true); // initialise gl graphics InitExtensions(); InitGLstate(); glEnable(GL_MULTISAMPLE_ARB); glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); LeftMotion(0, 0); MiddleMotion(0, 0); perfGraph = new PerformanceGraph(1000); resourceManager = ResourceManager::GetSingleton(); shaderManager = ShaderManager::GetSingleton(); /////////// //-- load the static scene geometry LoadModel(filename + ".dem", staticObjects); ////////// //-- load some dynamic stuff //resourceManager->mUseNormalMapping = true; //resourceManager->mUseNormalMapping = false; resourceManager->mUseSpecialColors = true; //LoadModel("fisch.dem", dynamicObjects); //LoadModel("venusm.dem", dynamicObjects); //LoadModel("camel.dem", dynamicObjects); //LoadModel("toyplane2.dem", dynamicObjects); //LoadModel("elephal.dem", dynamicObjects); if (0) LoadPompeiiFloor(); #if 1 #if 0 VertexArray positions; positions.push_back(Vector3(478.398f, 268.0f, 181.3)); positions.push_back(Vector3(470.461, 268.543, 181.7)); positions.push_back(Vector3(499.648, 264.358, 181.7)); positions.push_back(Vector3(487.913, 285.162, 181.7)); #else VertexArray positions; //positions.push_back(Vector3(6.07307, 8.20723, 6.7)); positions.push_back(Vector3(6.07307, 8.20723, 6.62)); positions.push_back(Vector3(-17.1935, 11.1687, 8.8781)); //positions.push_back(Vector3(499.648, 264.358, 181.7)); //positions.push_back(Vector3(487.913, 285.162, 181.7)); #endif //const Vector3 sceneCenter(470.398f, 240.364f, 180.3); Matrix4x4 transl = TranslationMatrix(positions[0]); LoadModel("hbuddha.dem", dynamicObjects); buddha = dynamicObjects.back(); buddha->GetTransform()->SetMatrix(transl); for (size_t i = 1; i < positions.size(); ++ i) { CreateNewInstance(buddha, positions[i]); } #endif resourceManager->mUseNormalMapping = false; resourceManager->mUseSpecialColors = false; /////////// //-- load the associated static bvh BvhFactory bvhFactory; if (bvhname != "") { cout << "loading bvh from disc" << endl; const string bvh_fullpath = string(model_path + bvhname + ".bvh"); bvh = bvhFactory.Create(bvh_fullpath, staticObjects, dynamicObjects, maxDepthForTestingChildren); if (!bvh) { cerr << "loading bvh " << bvh_fullpath << " failed" << endl; CleanUp(); exit(0); } } else { cout << "creating new bvh" << endl; bvh = bvhFactory.Create(staticObjects, dynamicObjects, maxDepthForTestingChildren); } /// set the depth of the bvh depending on the triangles per leaf node bvh->SetVirtualLeaves(trianglesPerVirtualLeaf); // set far plane based on scene extent farDist = 10.0f * Magnitude(bvh->GetBox().Diagonal()); camera->SetFar(farDist); //ObjExporter().Export(model_path + "mytest.obj", bvh); //BvhExporter().Export(model_path + "mytest.bv", bvh); ////////////////// //-- setup the skydome model LoadModel("sky.dem", staticObjects); skyDome = staticObjects.back(); /// the turbitity of the sky (from clear to hazy, use <3 for clear sky) preetham = new SkyPreetham(turbitity, skyDome); CreateAnimation(positions[0]); ////////////////////////// //-- a bounding box representing the sun pos in order to test visibility Transform3 *trafo = resourceManager->CreateTransform(IdentityMatrix()); // make it slightly bigger to simulate sun diameter const float size = 25.0f; AxisAlignedBox3 sbox(Vector3(-size), Vector3(size)); SceneEntityConverter conv; ////////////////// //-- occlusion query for sun Material *mat = resourceManager->CreateMaterial(); mat->GetTechnique(0)->SetDepthWriteEnabled(false); mat->GetTechnique(0)->SetColorWriteEnabled(false); sunBox = conv.ConvertBox(sbox, mat, trafo); resourceManager->AddSceneEntity(sunBox); /// create single occlusion query that handles sun visibility glGenQueriesARB(1, &sunQuery); ////////// //-- initialize the traversal algorithm traverser = CreateTraverser(camera); // the bird-eye visualization visualization = new Visualization(bvh, camera, NULL, &renderState); // this function assign the render queue bucket ids of the materials in beforehand // => probably less overhead for new parts of the scene that are not yet assigned PrepareRenderQueue(); /// forward rendering is the default renderState.SetRenderTechnique(FORWARD); // frame time is restarted every frame frameTimer.Start(); //Halton::TestHalton(7, 2); //HaltonSequence::TestHalton(15, 2); //Halton::TestPrime(); // the rendering loop glutMainLoop(); // clean up CleanUp(); return 0; } void InitFBO() { PrintGLerror("fbo start"); // this fbo basicly stores the scene information we get from standard rendering of a frame // we store diffuse colors, eye space depth and normals fbo = new FrameBufferObject(texWidth, texHeight, FrameBufferObject::DEPTH_32); // the diffuse color buffer fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, ColorBufferObject::FILTER_NEAREST); // the normals buffer //fbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST); fbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR); // a rgb buffer which could hold material properties //fbo->AddColorBuffer(ColorBufferObject::RGB_UBYTE, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST); // buffer holding the difference vector to the old frame fbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR); // another color buffer fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, ColorBufferObject::FILTER_NEAREST); for (int i = 0; i < 4; ++ i) { FrameBufferObject::InitBuffer(fbo, i); } PrintGLerror("init fbo"); } bool InitFont(void) { glEnable(GL_TEXTURE_2D); glGenTextures(1, &fontTex); glBindTexture(GL_TEXTURE_2D, fontTex); if (!myfont.Create("data/fonts/verdana.glf", fontTex)) return false; glDisable(GL_TEXTURE_2D); return true; } void InitGLstate() { glClearColor(0.4f, 0.4f, 0.4f, 1e20f); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT,1); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); glColor3f(1.0f, 1.0f, 1.0f); glShadeModel(GL_SMOOTH); glMaterialf(GL_FRONT, GL_SHININESS, 64); glEnable(GL_NORMALIZE); glDisable(GL_ALPHA_TEST); glAlphaFunc(GL_GEQUAL, 0.5f); glFrontFace(GL_CCW); glCullFace(GL_BACK); glEnable(GL_CULL_FACE); glDisable(GL_TEXTURE_2D); GLfloat ambientColor[] = {0.2, 0.2, 0.2, 1.0}; GLfloat diffuseColor[] = {1.0, 0.0, 0.0, 1.0}; GLfloat specularColor[] = {0.0, 0.0, 0.0, 1.0}; glMaterialfv(GL_FRONT, GL_AMBIENT, ambientColor); glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseColor); glMaterialfv(GL_FRONT, GL_SPECULAR, specularColor); glDepthFunc(GL_LESS); if (!InitFont()) cerr << "font creation failed" << endl; else cout << "successfully created font" << endl; ////////////////////////////// //GLfloat lmodel_ambient[] = {1.0f, 1.0f, 1.0f, 1.0f}; GLfloat lmodel_ambient[] = {0.7f, 0.7f, 0.8f, 1.0f}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); //glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE); glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SINGLE_COLOR_EXT); } void DrawHelpMessage() { const char *message[] = { "Help information", "", "'F1' - shows/dismisses this message", "'F2' - shows/hides bird eye view", "'F3' - shows/hides bounds (boxes or tight bounds)", "'F4', - shows/hides parameters", "'F5' - shows/hides statistics", "'F6', - toggles between fly/walkmode", "'F7', - cycles throw render modes", "'F8', - enables/disables ambient occlusion (only deferred)", "'F9', - shows pure algorithm render time (using glFinish)", "'SPACE' - cycles through occlusion culling algorithms", "", "'MOUSE LEFT' - turn left/right, move forward/backward", "'MOUSE RIGHT' - turn left/right, move forward/backward", "'MOUSE MIDDLE' - move up/down, left/right", "'CURSOR UP/DOWN' - move forward/backward", "'CURSOR LEFT/RIGHT' - turn left/right", "", "'-'/'+' - decreases/increases max batch size", "'1'/'2' - downward/upward motion", "'3'/'4' - decreases/increases triangles per virtual bvh leaf (sets bvh depth)", "'5'/'6' - decreases/increases assumed visible frames", "", "'R' - use render queue", "'B' - use tight bounds", "'M' - use multiqueries", "'O' - use CHC optimization (geometry queries for leaves)", 0, }; glColor4f(0.0f, 1.0f , 0.0f, 0.2f); // 20% green. glRecti(30, 30, winWidth - 30, winHeight - 30); glEnd(); glColor3f(1.0f, 1.0f, 1.0f); glEnable(GL_TEXTURE_2D); myfont.Begin(); int x = 40, y = 30; for(int i = 0; message[i] != 0; ++ i) { if(message[i][0] == '\0') { y += 15; } else { myfont.DrawString(message[i], x, winHeight - y); y += 25; } } glDisable(GL_TEXTURE_2D); } RenderTraverser *CreateTraverser(PerspectiveCamera *cam) { RenderTraverser *tr; switch (renderMode) { case RenderTraverser::CULL_FRUSTUM: tr = new FrustumCullingTraverser(); break; case RenderTraverser::STOP_AND_WAIT: tr = new StopAndWaitTraverser(); break; case RenderTraverser::CHC: tr = new CHCTraverser(); break; case RenderTraverser::CHCPLUSPLUS: tr = new CHCPlusPlusTraverser(); break; //case RenderTraverser::CULL_COLLECTOR: // tr = new PvsCollectionRenderer(); // break; default: tr = new FrustumCullingTraverser(); } tr->SetCamera(cam); tr->SetHierarchy(bvh); tr->SetRenderQueue(renderQueue); tr->SetRenderState(&renderState); tr->SetUseOptimization(useOptimization); tr->SetUseRenderQueue(useRenderQueue); tr->SetVisibilityThreshold(threshold); tr->SetAssumedVisibleFrames(assumedVisibleFrames); tr->SetMaxBatchSize(maxBatchSize); tr->SetUseMultiQueries(useMultiQueries); tr->SetUseTightBounds((renderMode == RenderTraverser::CHCPLUSPLUS) && useTightBounds); tr->SetUseDepthPass((renderMethod == RENDER_DEPTH_PASS) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED)); tr->SetRenderQueue(renderQueue); tr->SetShowBounds(showBoundingVolumes); bvh->ResetNodeClassifications(); return tr; } /** Setup lighting conditions */ void SetupLighting() { glEnable(GL_LIGHT0); glDisable(GL_LIGHT1); Vector3 lightDir = -light->GetDirection(); /////////// //-- first light: sunlight GLfloat ambient[] = {0.25f, 0.25f, 0.3f, 1.0f}; GLfloat diffuse[] = {1.0f, 0.95f, 0.85f, 1.0f}; GLfloat specular[] = {1.0f, 1.0f, 1.0f, 1.0f}; const bool useHDRValues = ((renderMethod == RENDER_DEPTH_PASS_DEFERRED) || (renderMethod == RENDER_DEFERRED)) && useHDR; Vector3 sunAmbient; Vector3 sunDiffuse; if (useSkylightForIllum) { preetham->ComputeSunColor(lightDir, sunAmbient, sunDiffuse, !useHDRValues); ambient[0] = sunAmbient.x; ambient[1] = sunAmbient.y; ambient[2] = sunAmbient.z; diffuse[0] = sunDiffuse.x; diffuse[1] = sunDiffuse.y; diffuse[2] = sunDiffuse.z; } else { ambient[0] = defaultAmbient.x; ambient[1] = defaultAmbient.y; ambient[2] = defaultAmbient.z; diffuse[0] = defaultDiffuse.x; diffuse[1] = defaultDiffuse.y; diffuse[2] = defaultDiffuse.z; } glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, specular); GLfloat position[] = {lightDir.x, lightDir.y, lightDir.z, 0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, position); } void SetupEyeView() { // store matrix of last frame oldViewProjMat = viewProjMat; camera->SetupViewProjection(); ///////////////// //-- compute view projection matrix and store for later use Matrix4x4 matViewing, matProjection; camera->GetModelViewMatrix(matViewing); camera->GetProjectionMatrix(matProjection); viewProjMat = matViewing * matProjection; } void KeyHorizontalMotion(float shift) { Vector3 hvec = -camera->GetDirection(); hvec.z = 0; Vector3 pos = camera->GetPosition(); pos += hvec * shift; camera->SetPosition(pos); } void KeyVerticalMotion(float shift) { Vector3 uvec = Vector3(0, 0, shift); Vector3 pos = camera->GetPosition(); pos += uvec; camera->SetPosition(pos); } void KeyStrafe(float shift) { Vector3 viewDir = camera->GetDirection(); Vector3 pos = camera->GetPosition(); // the 90 degree rotated view vector // z zero so we don't move in the vertical Vector3 rVec(viewDir[0], viewDir[1], 0); Matrix4x4 rot = RotationZMatrix(M_PI * 0.5f); rVec = rot * rVec; pos += rVec * shift; camera->SetPosition(pos); } /** Initialize the deferred rendering pass. */ void InitDeferredRendering() { if (!fbo) InitFBO(); fbo->Bind(); // multisampling does not work with deferred shading glDisable(GL_MULTISAMPLE_ARB); renderState.SetRenderTechnique(DEFERRED); // draw to 3 render targets if (sCurrentMrtSet == 0) { DeferredRenderer::colorBufferIdx = 0; glDrawBuffers(3, mrt); } else { DeferredRenderer::colorBufferIdx = 3; glDrawBuffers(3, mrt2); } sCurrentMrtSet = 1 - sCurrentMrtSet; } /** the main rendering loop */ void MainLoop() { if (buddha) { Matrix4x4 oldTrafo = buddha->GetTransform()->GetMatrix(); Vector3 buddhaPos = motionPath->GetCurrentPosition(); Matrix4x4 trafo = TranslationMatrix(buddhaPos); buddha->GetTransform()->SetMatrix(trafo); #if TODO // drop objects on ground floor for (int i = 0; i < 10; ++ i) { SceneEntity *ent = dynamicObjects[i]; Vector3 newPos = ent->GetWorldCenter(); if (GetOrCreateSceneQuery()->CalcIntersection(newPos)) { Matrix4x4 mat = TranslationMatrix(newPos - ent->GetCenter()); ent->GetTransform()->SetMatrix(mat); } } #endif ///////////////////////// //-- update animations //const float rotAngle = M_PI * 1e-3f; //const float rotAngle = 0.3f * M_PI / 180.0f; const float rotAngle = 0.6f * M_PI / 180.0f; Matrix4x4 rotMatrix = RotationZMatrix(rotAngle); // hack: second buddha dynamicObjects[1]->GetTransform()->MultMatrix(rotMatrix); //const float moveSpeed = 5e-3f; const float moveSpeed = 1e-1f; motionPath->Move(moveSpeed); } ///////////// static Vector3 oldPos = camera->GetPosition(); static Vector3 oldDir = camera->GetDirection(); if (leftKeyPressed) camera->Pitch(KeyRotationAngle()); if (rightKeyPressed) camera->Pitch(-KeyRotationAngle()); if (upKeyPressed) KeyHorizontalMotion(-KeyShift()); if (downKeyPressed) KeyHorizontalMotion(KeyShift()); if (ascendKeyPressed) KeyVerticalMotion(KeyShift()); if (descendKeyPressed) KeyVerticalMotion(-KeyShift()); if (leftStrafeKeyPressed) KeyStrafe(KeyShift()); if (rightStrafeKeyPressed) KeyStrafe(-KeyShift()); // place view on ground if (!flyMode) PlaceViewer(oldPos); if (showAlgorithmTime) { glFinish(); algTimer.Start(); } // don't allow replay on record if (replayPath && !recordPath) { if (!walkThroughPlayer) walkThroughPlayer = new WalkThroughPlayer(walkThroughSuffix + ".log"); ++ currentReplayFrame; // reset if end of walkthrough is reached if (!walkThroughPlayer->ReadNextFrame(camera)) { cout << "reached end of walkthrough" << endl; currentReplayFrame = -1; replayPath = false; } } if ((!shadowMap || !shadowTraverser) && (showShadowMap || renderLightView)) { if (!shadowMap) shadowMap = new ShadowMap(light, shadowSize, bvh->GetBox(), camera); if (!shadowTraverser) shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera()); } // bring eye modelview matrix up-to-date SetupEyeView(); // set frame related parameters for GPU programs GPUProgramParameters::InitFrame(camera, light); if (recordPath) { if (!walkThroughRecorder) { walkThroughRecorder = new WalkThroughRecorder(walkThroughSuffix + ".log"); } // question: check if player has moved more than a minimum distance? if (0 || (Distance(oldPos, camera->GetPosition()) > 1e-6f) || (DotProd(oldDir, camera->GetDirection()) < 1.0f - 1e-6f)) { walkThroughRecorder->WriteFrame(camera); } } // hack: store current rendering method and restore later int oldRenderMethod = renderMethod; // for rendering the light view, we use forward rendering if (renderLightView) renderMethod = FORWARD; /// enable vbo vertex array glEnableClientState(GL_VERTEX_ARRAY); if (usePvs) LoadOrUpdatePVSs(camera->GetPosition()); // render with the specified method (forward rendering, forward + depth, deferred) switch (renderMethod) { case RENDER_FORWARD: glEnable(GL_MULTISAMPLE_ARB); renderState.SetRenderTechnique(FORWARD); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnableClientState(GL_NORMAL_ARRAY); break; case RENDER_DEPTH_PASS_DEFERRED: glDisable(GL_MULTISAMPLE_ARB); renderState.SetUseAlphaToCoverage(false); renderState.SetRenderTechnique(DEPTH_PASS); if (!fbo) InitFBO(); fbo->Bind(); // render to single depth texture glDrawBuffers(1, mrt); // clear buffer once glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // the scene is rendered withouth any shading // (should be handled by render renderState) glShadeModel(GL_FLAT); break; case RENDER_DEPTH_PASS: glEnable(GL_MULTISAMPLE_ARB); renderState.SetRenderTechnique(DEPTH_PASS); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // the scene is rendered withouth any shading // (should be handled by render renderState) glShadeModel(GL_FLAT); break; case RENDER_DEFERRED: if (showShadowMap && !renderLightView) { RenderShadowMap(camera->GetFar()); } //glPushAttrib(GL_VIEWPORT_BIT); glViewport(0, 0, texWidth, texHeight); InitDeferredRendering(); glEnableClientState(GL_NORMAL_ARRAY); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); break; } glDepthFunc(GL_LESS); glDisable(GL_TEXTURE_2D); glDisableClientState(GL_TEXTURE_COORD_ARRAY); // set proper lod levels for current frame using current eye point LODLevel::InitFrame(camera->GetPosition()); // set up sunlight SetupLighting(); if (renderLightView) { // change CHC++ set of renderState variables: // must be done for each change of camera because otherwise // the temporal coherency is broken BvhNode::SetCurrentState(LIGHT_PASS); shadowMap->RenderShadowView(shadowTraverser, viewProjMat); BvhNode::SetCurrentState(CAMERA_PASS); } else { //if (traverser->GetType() == RenderTraverser::CULL_COLLECTOR) // ((PvsCollectionRenderer *)traverser)->SetViewCell(usePvs ? viewCell : NULL); // actually render the scene geometry using the specified algorithm traverser->RenderScene(); } ///////// //-- do the rest of the rendering // return from depth pass and render visible objects if ((renderMethod == RENDER_DEPTH_PASS) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED)) { RenderVisibleObjects(); } const bool useDeferred = ((renderMethod == RENDER_DEFERRED) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED)); // if no lense flare => just set sun to invisible const int sunVisiblePixels = useLenseFlare && useDeferred ? TestSunVisible() : 0; /////////////// //-- render sky // q: should we render sky after deferred shading? // this would conveniently solves some issues (e.g, skys without shadows) RenderSky(); ////////////////////////////// if (useDeferred) { FrameBufferObject::Release(); if (!deferredShader) { deferredShader = new DeferredRenderer(texWidth, texHeight, camera, ssaoUseFullResolution); deferredShader->SetKernelRadius(ssaoKernelRadius); deferredShader->SetSampleIntensity(ssaoSampleIntensity); } DeferredRenderer::SHADING_METHOD shadingMethod; if (useAdvancedShading) { if (useGlobIllum) shadingMethod = DeferredRenderer::GI; else shadingMethod = DeferredRenderer::SSAO; } else { shadingMethod = DeferredRenderer::DEFAULT; } static int snapShotIdx = 0; deferredShader->SetSunVisiblePixels(sunVisiblePixels); deferredShader->SetShadingMethod(shadingMethod); deferredShader->SetSamplingMethod(samplingMethod); deferredShader->SetUseTemporalCoherence(useTemporalCoherence); //deferredShader->SetSortSamples(sortSamples); deferredShader->SetTemporalCoherenceFactorForSsao(ssaoTempCohFactor); deferredShader->SetUseToneMapping(useHDR); deferredShader->SetUseAntiAliasing(useAntiAliasing); deferredShader->SetMaxConvergence(maxConvergence); if (recordFrames && replayPath) { // record all frames of the walkthrough deferredShader->SetSaveFrame(recordedFramesSuffix, currentReplayFrame); } else if (makeSnapShot) { // make snap shot deferredShader->SetSaveFrame("snap", snapShotIdx ++); } else { // do nothing deferredShader->SetSaveFrame("", -1); } if (makeSnapShot) makeSnapShot = false; ShadowMap *sm = showShadowMap ? shadowMap : NULL; deferredShader->Render(fbo, light, sm); } renderState.SetRenderTechnique(FORWARD); renderState.Reset(); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); renderMethod = oldRenderMethod; /////////// if (showAlgorithmTime) { glFinish(); algTime = algTimer.Elapsedms(); perfGraph->AddData(algTime); perfGraph->Draw(); } else { if (visMode) DisplayVisualization(); } glFlush(); const bool restart = true; elapsedTime = frameTimer.Elapsedms(restart); // statistics DisplayStats(); glutSwapBuffers(); oldPos = camera->GetPosition(); oldDir = camera->GetDirection(); } #pragma warning(disable : 4100) void KeyBoard(unsigned char c, int x, int y) { switch(c) { case 27: // write out current position on exit Debug << "camPosition=" << camera->GetPosition().x << " " << camera->GetPosition().y << " " << camera->GetPosition().z << endl; Debug << "camDirection=" << camera->GetDirection().x << " " << camera->GetDirection().y << " " << camera->GetDirection().z << endl; Debug << "lightDirection=" << light->GetDirection().x << " " << light->GetDirection().y << " " << light->GetDirection().z << endl; CleanUp(); exit(0); case 32: // space renderMode = (renderMode + 1) % RenderTraverser::NUM_TRAVERSAL_TYPES; //renderMode = (renderMode + 1) % 4; DEL_PTR(traverser); traverser = CreateTraverser(camera); if (shadowTraverser) { // shadow traverser has to be recomputed DEL_PTR(shadowTraverser); shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera()); } break; case '+': if (maxBatchSize < 10) maxBatchSize = 10; else maxBatchSize += 10; traverser->SetMaxBatchSize(maxBatchSize); break; case '-': maxBatchSize -= 10; if (maxBatchSize < 0) maxBatchSize = 1; traverser->SetMaxBatchSize(maxBatchSize); break; case 'M': case 'm': useMultiQueries = !useMultiQueries; traverser->SetUseMultiQueries(useMultiQueries); break; case '1': descendKeyPressed = true; break; case '2': ascendKeyPressed = true; break; case '3': if (trianglesPerVirtualLeaf >= 100) trianglesPerVirtualLeaf -= 100; bvh->SetVirtualLeaves(trianglesPerVirtualLeaf); break; case '4': trianglesPerVirtualLeaf += 100; bvh->SetVirtualLeaves(trianglesPerVirtualLeaf); break; case '5': assumedVisibleFrames -= 1; if (assumedVisibleFrames < 1) assumedVisibleFrames = 1; traverser->SetAssumedVisibleFrames(assumedVisibleFrames); break; case '6': assumedVisibleFrames += 1; traverser->SetAssumedVisibleFrames(assumedVisibleFrames); break; case '7': ssaoTempCohFactor *= 1.0f / 1.2f; cout << "new temporal coherence factor: " << ssaoTempCohFactor << endl; break; case '8': ssaoTempCohFactor *= 1.2f; cout << "new temporal coherence factor: " << ssaoTempCohFactor << endl; break; case '9': ssaoKernelRadius *= 0.8f; cout << "new ssao kernel radius: " << ssaoKernelRadius << endl; if (deferredShader) deferredShader->SetKernelRadius(ssaoKernelRadius); break; case '0': ssaoKernelRadius *= 1.0f / 0.8f; if (deferredShader) deferredShader->SetKernelRadius(ssaoKernelRadius); cout << "new ssao kernel radius: " << ssaoKernelRadius << endl; break; case 'n': ssaoSampleIntensity *= 0.9f; if (deferredShader) deferredShader->SetSampleIntensity(ssaoSampleIntensity); cout << "new ssao sample intensity: " << ssaoSampleIntensity << endl; break; case 'N': ssaoSampleIntensity *= 1.0f / 0.9f; if (deferredShader) deferredShader->SetSampleIntensity(ssaoSampleIntensity); cout << "new ssao sample intensity: " << ssaoSampleIntensity << endl; break; /* case 'o': case 'O': useOptimization = !useOptimization; // chc optimization of using the objects instead of // the bounding boxes for querying previously visible nodes traverser->SetUseOptimization(useOptimization); break;*/ case 'o': case 'O': if (maxConvergence > 100.0f) maxConvergence = 1.0f; else maxConvergence = 5000.0f; cout << "max convergence: " << maxConvergence << endl; break; case 'l': case 'L': useLODs = !useLODs; SceneEntity::SetUseLODs(useLODs); cout << "using LODs: " << useLODs << endl; break; case 'P': case 'p': samplingMethod = DeferredRenderer::SAMPLING_METHOD((samplingMethod + 1) % 3); cout << "ssao sampling method: " << samplingMethod << endl; break; case 'Y': case 'y': showShadowMap = !showShadowMap; break; case 'g': case 'G': useGlobIllum = !useGlobIllum; break; case 't': case 'T': useTemporalCoherence = !useTemporalCoherence; break; case 'a': case 'A': leftKeyPressed = true; break; case 'd': case 'D': rightKeyPressed = true; break; case 'w': case 'W': upKeyPressed = true; break; case 's': case 'S': downKeyPressed = true; break; case 'j': case 'J': leftStrafeKeyPressed = true; break; case 'k': case 'K': rightStrafeKeyPressed = true; break; case 'r': case 'R': useRenderQueue = !useRenderQueue; traverser->SetUseRenderQueue(useRenderQueue); break; case 'b': case 'B': useTightBounds = !useTightBounds; traverser->SetUseTightBounds((renderMode == RenderTraverser::CHCPLUSPLUS) && useTightBounds); break; case 'v': case 'V': renderLightView = !renderLightView; break; case 'h': case 'H': useHDR = !useHDR; break; case 'i': case 'I': useAntiAliasing = !useAntiAliasing; break; case 'c': case 'C': useLenseFlare = !useLenseFlare; break; case 'u': case 'U': // move light source instead of camera tilt moveLight = !moveLight; break; case '#': // make a snapshot of the current frame makeSnapShot = true; break; case '.': // enable / disable view cells usePvs = !usePvs; if (!usePvs) SceneEntity::SetCurrentVisibleId(-1); break; case ',': // show / hide FPS showFPS = !showFPS; break; default: return; } glutPostRedisplay(); } void SpecialKeyUp(int c, int x, int y) { switch (c) { case GLUT_KEY_LEFT: leftKeyPressed = false; break; case GLUT_KEY_RIGHT: rightKeyPressed = false; break; case GLUT_KEY_UP: upKeyPressed = false; break; case GLUT_KEY_DOWN: downKeyPressed = false; break; case GLUT_ACTIVE_ALT: altKeyPressed = false; break; default: return; } } void KeyUp(unsigned char c, int x, int y) { switch (c) { case 'A': case 'a': leftKeyPressed = false; break; case 'D': case 'd': rightKeyPressed = false; break; case 'W': case 'w': upKeyPressed = false; break; case 'S': case 's': downKeyPressed = false; break; case '1': descendKeyPressed = false; break; case '2': ascendKeyPressed = false; break; case 'j': case 'J': leftStrafeKeyPressed = false; break; case 'k': case 'K': rightStrafeKeyPressed = false; break; default: return; } //glutPostRedisplay(); } void Special(int c, int x, int y) { switch(c) { case GLUT_KEY_F1: showHelp = !showHelp; break; case GLUT_KEY_F2: visMode = !visMode; break; case GLUT_KEY_F3: showBoundingVolumes = !showBoundingVolumes; traverser->SetShowBounds(showBoundingVolumes); break; case GLUT_KEY_F4: showOptions = !showOptions; break; case GLUT_KEY_F5: showStatistics = !showStatistics; break; case GLUT_KEY_F6: flyMode = !flyMode; break; case GLUT_KEY_F7: renderMethod = (renderMethod + 1) % 4; traverser->SetUseDepthPass( (renderMethod == RENDER_DEPTH_PASS) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED) ); break; case GLUT_KEY_F8: useAdvancedShading = !useAdvancedShading; break; case GLUT_KEY_F9: showAlgorithmTime = !showAlgorithmTime; break; case GLUT_KEY_F10: replayPath = !replayPath; if (replayPath) { cout << "replaying path" << endl; currentReplayFrame = -1; // hack: load pvs on replay (remove later!) //usePvs = true; } else { cout << "finished replaying path" << endl; } break; case GLUT_KEY_F11: recordPath = !recordPath; if (recordPath) { cout << "recording path" << endl; } else { cout << "finished recording path" << endl; // start over with new frame recording next time DEL_PTR(walkThroughRecorder); } break; case GLUT_KEY_F12: recordFrames = !recordFrames; if (recordFrames) cout << "recording frames on replaying" << endl; else cout << "not recording frames on replaying" << endl; break; case GLUT_KEY_LEFT: { leftKeyPressed = true; camera->Pitch(KeyRotationAngle()); } break; case GLUT_KEY_RIGHT: { rightKeyPressed = true; camera->Pitch(-KeyRotationAngle()); } break; case GLUT_KEY_UP: { upKeyPressed = true; KeyHorizontalMotion(KeyShift()); } break; case GLUT_KEY_DOWN: { downKeyPressed = true; KeyHorizontalMotion(-KeyShift()); } break; default: return; } glutPostRedisplay(); } #pragma warning( default : 4100 ) void Reshape(int w, int h) { winAspectRatio = 1.0f; glViewport(0, 0, w, h); winWidth = w; winHeight = h; if (w) winAspectRatio = (float) w / (float) h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(fov, winAspectRatio, nearDist, farDist); glMatrixMode(GL_MODELVIEW); glutPostRedisplay(); } void Mouse(int button, int renderState, int x, int y) { if ((button == GLUT_LEFT_BUTTON) && (renderState == GLUT_DOWN)) { xEyeBegin = x; yMotionBegin = y; glutMotionFunc(LeftMotion); } else if ((button == GLUT_RIGHT_BUTTON) && (renderState == GLUT_DOWN)) { xEyeBegin = x; yEyeBegin = y; yMotionBegin = y; if (!moveLight) glutMotionFunc(RightMotion); else glutMotionFunc(RightMotionLight); } else if ((button == GLUT_MIDDLE_BUTTON) && (renderState == GLUT_DOWN)) { horizontalMotionBegin = x; verticalMotionBegin = y; glutMotionFunc(MiddleMotion); } glutPostRedisplay(); } /** rotation for left/right mouse drag motion for up/down mouse drag */ void LeftMotion(int x, int y) { Vector3 viewDir = camera->GetDirection(); Vector3 pos = camera->GetPosition(); // don't move in the vertical direction Vector3 horView(viewDir[0], viewDir[1], 0); float eyeXAngle = 0.2f * M_PI * (xEyeBegin - x) / 180.0; camera->Pitch(eyeXAngle); pos += horView * (yMotionBegin - y) * mouseMotion; camera->SetPosition(pos); xEyeBegin = x; yMotionBegin = y; glutPostRedisplay(); } void RightMotionLight(int x, int y) { float theta = 0.2f * M_PI * (xEyeBegin - x) / 180.0f; float phi = 0.2f * M_PI * (yMotionBegin - y) / 180.0f; Vector3 lightDir = light->GetDirection(); Matrix4x4 roty = RotationYMatrix(theta); Matrix4x4 rotx = RotationXMatrix(phi); lightDir = roty * lightDir; lightDir = rotx * lightDir; // normalize to avoid accumulating errors lightDir.Normalize(); light->SetDirection(lightDir); xEyeBegin = x; yMotionBegin = y; glutPostRedisplay(); } /** rotation for left / right mouse drag motion for up / down mouse drag */ void RightMotion(int x, int y) { float eyeXAngle = 0.2f * M_PI * (xEyeBegin - x) / 180.0; float eyeYAngle = -0.2f * M_PI * (yEyeBegin - y) / 180.0; camera->Yaw(eyeYAngle); camera->Pitch(eyeXAngle); xEyeBegin = x; yEyeBegin = y; glutPostRedisplay(); } /** strafe */ void MiddleMotion(int x, int y) { Vector3 viewDir = camera->GetDirection(); Vector3 pos = camera->GetPosition(); // the 90 degree rotated view vector // y zero so we don't move in the vertical Vector3 rVec(viewDir[0], viewDir[1], 0); Matrix4x4 rot = RotationZMatrix(M_PI * 0.5f); rVec = rot * rVec; pos -= rVec * (x - horizontalMotionBegin) * mouseMotion; pos[2] += (verticalMotionBegin - y) * mouseMotion; camera->SetPosition(pos); horizontalMotionBegin = x; verticalMotionBegin = y; glutPostRedisplay(); } void InitExtensions(void) { GLenum err = glewInit(); if (GLEW_OK != err) { // problem: glewInit failed, something is seriously wrong fprintf(stderr,"Error: %s\n", glewGetErrorString(err)); exit(1); } if (!GLEW_ARB_occlusion_query) { printf("I require the GL_ARB_occlusion_query to work.\n"); exit(1); } } void Begin2D() { glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0, winWidth, 0, winHeight); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); } void End2D() { glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); } // displays the visualisation of culling algorithm void DisplayVisualization() { // render current view cell if (usePvs) RenderViewCell(); visualization->SetViewCell(usePvs ? viewCell : NULL); visualization->SetFrameId(traverser->GetCurrentFrameId()); Begin2D(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glColor4f(0.0f ,0.0f, 0.0f, 0.5f); glRecti(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth, winHeight); glDisable(GL_BLEND); End2D(); AxisAlignedBox3 box = bvh->GetBox(); const float offs = box.Size().x * 0.3f; Vector3 vizpos = Vector3(box.Min().x, box.Min().y - box.Size().y * 0.35f, box.Min().z + box.Size().z * 50); visCamera->SetPosition(vizpos); visCamera->ResetPitchAndYaw(); glPushAttrib(GL_VIEWPORT_BIT); glViewport(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth / 3, winHeight / 3); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(-offs, offs, -offs, offs, 0.0f, box.Size().z * 100.0f); glMatrixMode(GL_MODELVIEW); glPushMatrix(); visCamera->SetupCameraView(); Matrix4x4 rotZ = RotationZMatrix(-camera->GetPitch()); glMultMatrixf((float *)rotZ.x); // inverse translation in order to fix current position Vector3 pos = camera->GetPosition(); glTranslatef(-pos.x, -pos.y, -pos.z); GLfloat position[] = {0.8f, 1.0f, 1.5f, 0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, position); GLfloat position1[] = {bvh->GetBox().Center().x, bvh->GetBox().Max().y, bvh->GetBox().Center().z, 1.0f}; glLightfv(GL_LIGHT1, GL_POSITION, position1); glClear(GL_DEPTH_BUFFER_BIT); //////////// //-- visualization of the occlusion culling visualization->Render(showShadowMap); // reset previous settings glPopAttrib(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } // cleanup routine after the main loop void CleanUp() { DEL_PTR(traverser); DEL_PTR(sceneQuery); DEL_PTR(bvh); DEL_PTR(visualization); DEL_PTR(camera); DEL_PTR(renderQueue); DEL_PTR(perfGraph); DEL_PTR(fbo); DEL_PTR(deferredShader); DEL_PTR(light); DEL_PTR(visCamera); DEL_PTR(preetham); DEL_PTR(shadowMap); DEL_PTR(shadowTraverser); DEL_PTR(motionPath); DEL_PTR(walkThroughRecorder); DEL_PTR(walkThroughPlayer); DEL_PTR(statsWriter); DEL_PTR(viewCellsTree); ResourceManager::DelSingleton(); ShaderManager::DelSingleton(); resourceManager = NULL; shaderManager = NULL; } // this function inserts a dezimal point after each 1000 void CalcDecimalPoint(string &str, int d, int len) { static vector numbers; numbers.clear(); static string shortStr; shortStr.clear(); static char hstr[100]; while (d != 0) { numbers.push_back(d % 1000); d /= 1000; } // first element without leading zeros if (numbers.size() > 0) { sprintf(hstr, "%d", numbers.back()); shortStr.append(hstr); } for (int i = (int)numbers.size() - 2; i >= 0; i--) { sprintf(hstr, ",%03d", numbers[i]); shortStr.append(hstr); } int dif = len - (int)shortStr.size(); for (int i = 0; i < dif; ++ i) { str += " "; } str.append(shortStr); } void DisplayStats() { static char msg[9][300]; static double frameTime = elapsedTime; static double renderTime = algTime; const float expFactor = 0.1f; // if some strange render time spike happened in this frame => don't count if (elapsedTime < 500) frameTime = elapsedTime * expFactor + (1.0f - expFactor) * elapsedTime; static float rTime = 1000.0f; // the render time is used only for the traversal algorithm using glfinish if (algTime < 500) renderTime = algTime * expFactor + (1.0f - expFactor) * renderTime; accumulatedTime += elapsedTime; if (accumulatedTime > 500) // update every fraction of a second { accumulatedTime = 0; if (frameTime) fps = 1e3f / (float)frameTime; rTime = renderTime; if (renderLightView && shadowTraverser) { renderedTriangles = shadowTraverser->GetStats().mNumRenderedTriangles; renderedObjects = shadowTraverser->GetStats().mNumRenderedGeometry; renderedNodes = shadowTraverser->GetStats().mNumRenderedNodes; } else if (showShadowMap && shadowTraverser) { renderedNodes = traverser->GetStats().mNumRenderedNodes + shadowTraverser->GetStats().mNumRenderedNodes; renderedObjects = traverser->GetStats().mNumRenderedGeometry + shadowTraverser->GetStats().mNumRenderedGeometry; renderedTriangles = traverser->GetStats().mNumRenderedTriangles + shadowTraverser->GetStats().mNumRenderedTriangles; } else { renderedTriangles = traverser->GetStats().mNumRenderedTriangles; renderedObjects = traverser->GetStats().mNumRenderedGeometry; renderedNodes = traverser->GetStats().mNumRenderedNodes; } traversedNodes = traverser->GetStats().mNumTraversedNodes; frustumCulledNodes = traverser->GetStats().mNumFrustumCulledNodes; queryCulledNodes = traverser->GetStats().mNumQueryCulledNodes; issuedQueries = traverser->GetStats().mNumIssuedQueries; stateChanges = traverser->GetStats().mNumStateChanges; numBatches = traverser->GetStats().mNumBatches; } //////////////// //-- record stats on walkthrough static float accTime = .0f; static float averageTime = .0f; if (currentReplayFrame > -1) { accTime += frameTime; averageTime = accTime / (currentReplayFrame + 1); if (!statsWriter) statsWriter = new StatsWriter(statsFilename + ".log"); FrameStats frameStats; frameStats.mFrame = currentReplayFrame; frameStats.mFPS = 1e3f / (float)frameTime; frameStats.mTime = frameTime; frameStats.mNodes = renderedNodes; frameStats.mObjects = renderedObjects; frameStats.mTriangles = renderedTriangles; statsWriter->WriteFrameStats(frameStats); } else if (statsWriter) { Debug << "average frame time " << averageTime << " for traversal algorithm " << renderMode << endl; // reset average frame time averageTime = accTime = .0f; DEL_PTR(statsWriter); } Begin2D(); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); if (showHelp) { DrawHelpMessage(); } else { if (showOptions) { glColor4f(0.0f, 0.0f, 0.0f, 0.5f); glRecti(5, winHeight - 95, winWidth * 2 / 3 - 5, winHeight - 5); } if (showStatistics) { glColor4f(0.0f, 0.0f, 0.0f, 0.5f); glRecti(5, winHeight - 165, winWidth * 2 / 3 - 5, winHeight - 100); } glEnable(GL_TEXTURE_2D); myfont.Begin(); if (showOptions) { glColor3f(0.0f, 1.0f, 0.0f); int i = 0; static char *renderMethodStr[] = {"forward", "depth pass + forward", "deferred shading", "depth pass + deferred"}; sprintf(msg[i ++], "multiqueries: %d, tight bounds: %d, render queue: %d", useMultiQueries, (renderMode == RenderTraverser::CHCPLUSPLUS) && useTightBounds, useRenderQueue); sprintf(msg[i ++], "render technique: %s, use pvss: %d", renderMethodStr[renderMethod], usePvs); sprintf(msg[i ++], "triangles per virtual leaf: %5d", trianglesPerVirtualLeaf); sprintf(msg[i ++], "assumed visible frames: %4d, max batch size: %4d", assumedVisibleFrames, maxBatchSize); for (int j = 0; j < 4; ++ j) myfont.DrawString(msg[j], 10.0f, winHeight - 5 - j * 20); } if (showStatistics) { glColor3f(1.0f, 1.0f, 0.0f); string objStr, totalObjStr; string triStr, totalTriStr; int len = 10; CalcDecimalPoint(objStr, renderedObjects, len); CalcDecimalPoint(totalObjStr, (int)resourceManager->GetNumEntities(), len); CalcDecimalPoint(triStr, renderedTriangles, len); CalcDecimalPoint(totalTriStr, bvh->GetBvhStats().mTriangles, len); int i = 4; if (0) // q: show rendered objects or nodes (no space for both) { sprintf(msg[i ++], "rendered: %s of %s objects, %s of %s triangles", objStr.c_str(), totalObjStr.c_str(), triStr.c_str(), totalTriStr.c_str()); } else { sprintf(msg[i ++], "rendered: %6d of %6d nodes, %s of %s triangles", renderedNodes, bvh->GetNumVirtualNodes(), triStr.c_str(), totalTriStr.c_str()); } sprintf(msg[i ++], "traversed: %5d, frustum culled: %5d, query culled: %5d nodes", traversedNodes, frustumCulledNodes, queryCulledNodes); sprintf(msg[i ++], "issued queries: %5d, state changes: %5d, render batches: %5d", issuedQueries, stateChanges, numBatches); for (int j = 4; j < 7; ++ j) myfont.DrawString(msg[j], 10.0f, winHeight - (j + 1) * 20); } glColor3f(0.0f, 1.0f, 0.0f); static char *alg_str[] = { "Frustum Cull" , "Stop and Wait" , "CHC" , "CHC ++" //, "Collector" }; if (!showAlgorithmTime) { if (showFPS) { sprintf(msg[7], "%s: %6.1f fps", alg_str[renderMode], fps); myfont.DrawString(msg[7], 1.3f, winWidth - 330, winHeight - 10.0f); //int mrays = (int)shotRays / 1000000; //sprintf(msg[7], "%s: %04d M rays", alg_str[renderMode], mrays); //myfont.DrawString(msg[7], 1.3f, winWidth - 330, winHeight - 60.0f); } } else { sprintf(msg[7], "%s: %6.1f ms", alg_str[renderMode], rTime); myfont.DrawString(msg[7], 1.3f, winWidth - 330, winHeight - 10.0f); } glColor3f(1.0f, 1.0f, 1.0f); } glColor3f(1, 1, 1); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); End2D(); } void RenderSky() { if ((renderMethod == RENDER_DEFERRED) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED)) renderState.SetRenderTechnique(DEFERRED); const bool useToneMapping = ((renderMethod == RENDER_DEPTH_PASS_DEFERRED) || (renderMethod == RENDER_DEFERRED)) && useHDR; preetham->RenderSkyDome(-light->GetDirection(), camera, &renderState, !useToneMapping, skyDomeScaleFactor); /// once again reset the renderState just to make sure renderState.Reset(); } // render visible object from depth pass void RenderVisibleObjects() { if (renderMethod == RENDER_DEPTH_PASS_DEFERRED) { if (showShadowMap && !renderLightView) { // usethe maximal visible distance to focus shadow map const float newFar = min(camera->GetFar(), traverser->GetMaxVisibleDistance()); RenderShadowMap(newFar); } // initialize deferred rendering InitDeferredRendering(); } else { renderState.SetRenderTechnique(FORWARD); } ///////////////// //-- reset gl renderState before the final visible objects pass renderState.Reset(); glEnableClientState(GL_NORMAL_ARRAY); /// switch back to smooth shading glShadeModel(GL_SMOOTH); /// reset alpha to coverage flag renderState.SetUseAlphaToCoverage(true); // clear color glClear(GL_COLOR_BUFFER_BIT); // draw only objects having exactly the same depth as the current sample glDepthFunc(GL_EQUAL); //cout << "visible: " << (int)traverser->GetVisibleObjects().size() << endl; SceneEntityContainer::const_iterator sit, sit_end = traverser->GetVisibleObjects().end(); for (sit = traverser->GetVisibleObjects().begin(); sit != sit_end; ++ sit) { renderQueue->Enqueue(*sit); } /// now render out everything in one giant pass renderQueue->Apply(); // switch back to standard depth func glDepthFunc(GL_LESS); renderState.Reset(); PrintGLerror("visible objects"); } SceneQuery *GetOrCreateSceneQuery() { if (!sceneQuery) { sceneQuery = new SceneQuery(bvh->GetBox(), traverser, &renderState); } return sceneQuery; } void PlaceViewer(const Vector3 &oldPos) { Vector3 playerPos = camera->GetPosition(); bool validIntersect = GetOrCreateSceneQuery()->CalcIntersection(playerPos); if (validIntersect) //&& ((playerPos.z - oldPos.z) < bvh->GetBox().Size(2) * 1e-1f)) { camera->SetPosition(playerPos); } } void RenderShadowMap(float newfar) { glDisableClientState(GL_NORMAL_ARRAY); renderState.SetRenderTechnique(DEPTH_PASS); // hack: disable cull face because of alpha textured balconies glDisable(GL_CULL_FACE); renderState.LockCullFaceEnabled(true); /// don't use alpha to coverage for the depth map (problems with fbo rendering) renderState.SetUseAlphaToCoverage(false); const Vector3 lightPos = light->GetDirection() * -1e3f; if (usePvs) LoadOrUpdatePVSs(lightPos); // change CHC++ set of renderState variables // this must be done for each change of camera because // otherwise the temporal coherency is broken BvhNode::SetCurrentState(LIGHT_PASS); // hack: temporarily change camera far plane camera->SetFar(newfar); // the scene is rendered withouth any shading shadowMap->ComputeShadowMap(shadowTraverser, viewProjMat); camera->SetFar(farDist); renderState.SetUseAlphaToCoverage(true); renderState.LockCullFaceEnabled(false); glEnable(GL_CULL_FACE); glEnableClientState(GL_NORMAL_ARRAY); // change back renderState BvhNode::SetCurrentState(CAMERA_PASS); } /** Touch each material once in order to preload the render queue bucket id of each material */ void PrepareRenderQueue() { for (int i = 0; i < 3; ++ i) { renderState.SetRenderTechnique(i); // fill all shapes into the render queue once so we can establish the buckets ShapeContainer::const_iterator sit, sit_end = (*resourceManager->GetShapes()).end(); for (sit = (*resourceManager->GetShapes()).begin(); sit != sit_end; ++ sit) { static Transform3 dummy(IdentityMatrix()); renderQueue->Enqueue(*sit, NULL); } // just clear queue again renderQueue->Clear(); } } int LoadModel(const string &model, SceneEntityContainer &entities) { const string filename = string(model_path + model); int numEntities = 0; cout << "\nloading model " << filename << endl; if (numEntities = resourceManager->Load(filename, entities)) { cout << "model " << filename << " successfully loaded" << endl; } else { cerr << "loading model " << filename << " failed" << endl; CleanUp(); exit(0); } return numEntities; } void CreateAnimation(const Vector3 &pos) { //const float b = 5.0f; const float a = 1.5f; const float a = 5.0f; const float b = 1.5f; VertexArray vertices; for (int i = 0; i < 360; ++ i) { const float angle = (float)i * M_PI / 180.0f; Vector3 offs = Vector3(cos(angle) * a, sin(angle) * b, 0); vertices.push_back(pos + offs); } /*for (int i = 0; i < 5; ++ i) { Vector3 offs = Vector3(i, 0, 0); vertices.push_back(center + offs); } for (int i = 0; i < 5; ++ i) { Vector3 offs = Vector3(4 - i, 0, 0); vertices.push_back(center + offs); }*/ motionPath = new MotionPath(vertices); } /** This function returns the number of visible pixels of a bounding box representing the sun. */ int TestSunVisible() { // assume sun is at a far away point along the light vector Vector3 sunPos = light->GetDirection() * -1e3f; sunPos += camera->GetPosition(); sunBox->GetTransform()->SetMatrix(TranslationMatrix(sunPos)); glBeginQueryARB(GL_SAMPLES_PASSED_ARB, sunQuery); sunBox->Render(&renderState); glEndQueryARB(GL_SAMPLES_PASSED_ARB); GLuint sampleCount; glGetQueryObjectuivARB(sunQuery, GL_QUERY_RESULT_ARB, &sampleCount); return sampleCount; } static Technique GetVizTechnique() { Technique tech; tech.Init(); tech.SetEmmisive(RgbaColor(1.0f, 1.0f, 1.0f, 1.0f)); tech.SetDiffuse(RgbaColor(1.0f, 1.0f, 1.0f, 1.0f)); tech.SetAmbient(RgbaColor(1.0f, 1.0f, 1.0f, 1.0f)); return tech; } void UpdatePvs(const Vector3 &pos) { viewCell = viewCellsTree->GetViewCell(camera->GetPosition()); const float elapsedAlgorithmTime = applicationTimer.Elapsedms(false); // assume 60 FPS, total time is in secs const float raysPerMs = 2.0f * pvsTotalSamples / (pvsTotalTime * 1000.0f); //shotRays = visibilitySolutionInitialState + elapsedAlgorithmTime * raysPerMs; //shotRays += 1000 * raysPerMs / 60.0f; //cout << "totalt: " << pvsTotalTime << endl; //cout << "rays per ms: " << raysPerMs << endl; SceneEntity::SetCurrentVisibleId(globalVisibleId); for (int i = 0; i < viewCell->mPvs.GetSize(); ++ i) { PvsEntry entry = viewCell->mPvs.GetEntry(i); #ifdef USE_TIMESTAMPS if (!((entry.mTimeStamp < 0.0f) || (entry.mTimeStamp <= shotRays))) continue; #endif entry.mEntity->SetVisibleId(globalVisibleId); //numTriangles += entry.mEntity->CountNumTriangles(); } ++ globalVisibleId; } void LoadVisibilitySolution() { /////////// //-- load the visibility solution const string vis_filename = string(model_path + visibilitySolution + ".vis"); VisibilitySolutionLoader visLoader; viewCellsTree = visLoader.Load(vis_filename, bvh, pvsTotalSamples, pvsTotalTime, viewCellsScaleFactor); if (!viewCellsTree) { cerr << "loading pvs failed" << endl; CleanUp(); exit(0); } } void RenderViewCell() { // render current view cell static Technique vcTechnique = GetVizTechnique(); vcTechnique.Render(&renderState); Visualization::RenderBoxForViz(viewCell->GetBox()); } void LoadPompeiiFloor() { AxisAlignedBox3 pompeiiBox = SceneEntity::ComputeBoundingBox(staticObjects); // todo: dispose texture Texture *floorTex = new Texture(model_path + "stairs.c.01.tif"); floorTex->SetBoundaryModeS(Texture::REPEAT); floorTex->SetBoundaryModeT(Texture::REPEAT); floorTex->Create(); Material *mymat = resourceManager->CreateMaterial(); Technique *tech = mymat->GetDefaultTechnique(); tech->SetDiffuse(RgbaColor(1, 1, 1, 1)); tech->SetTexture(floorTex); Technique *depthPass = new Technique(*tech); Technique *deferred = new Technique(*tech); depthPass->SetColorWriteEnabled(false); depthPass->SetLightingEnabled(false); ShaderProgram *defaultFragmentTexProgramMrt = ShaderManager::GetSingleton()->GetShaderProgram("defaultFragmentTexMrt"); ShaderProgram *defaultVertexProgramMrt = ShaderManager::GetSingleton()->GetShaderProgram("defaultVertexMrt"); deferred->SetFragmentProgram(defaultFragmentTexProgramMrt); deferred->SetVertexProgram(defaultVertexProgramMrt); deferred->GetFragmentProgramParameters()->SetViewMatrixParam(0); deferred->GetVertexProgramParameters()->SetModelMatrixParam(1); deferred->GetVertexProgramParameters()->SetOldModelMatrixParam(2); deferred->SetTexture(floorTex); mymat->AddTechnique(deferred); mymat->AddTechnique(depthPass); //const Vector3 offs(1300.0f, -2500.0f, .0f); const Vector3 offs(pompeiiBox.Center(0), pompeiiBox.Center(1), 0); Matrix4x4 moffs = TranslationMatrix(offs); Plane3 plane; Transform3 *mytrafo = resourceManager->CreateTransform(moffs); SceneEntity *myplane = SceneEntityConverter().ConvertPlane(plane, pompeiiBox.Size(0), pompeiiBox.Size(1), 5, 5, mymat, mytrafo); resourceManager->AddSceneEntity(myplane); staticObjects.push_back(myplane); } void LoadOrUpdatePVSs(const Vector3 &pos) { if (!viewCellsTree) { LoadVisibilitySolution(); applicationTimer.Start(); shotRays = visibilitySolutionInitialState; } if (viewCellsTree) UpdatePvs(pos); } void CreateNewInstance(SceneEntity *parent, const Vector3 &pos) { SceneEntity *ent = new SceneEntity(*parent); resourceManager->AddSceneEntity(ent); Matrix4x4 transl = TranslationMatrix(pos); Transform3 *transform = resourceManager->CreateTransform(transl); ent->SetTransform(transform); dynamicObjects.push_back(ent); //Debug << "positions: " << newPos << endl; }