// occquery.cpp : Defines the entry point for the console application. // #include #include #include "common.h" #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 #include using namespace std; using namespace CHCDemoEngine; GLuint fbo; GLuint depthBuffer; GLuint positionsBuffer; GLuint colorsBuffer; GLuint normalsBuffer; GLuint positionsTex; GLuint colorsTex; GLuint normalsTex; GLuint noiseTex; /// the renderable scene geometry SceneEntityContainer sceneEntities; // traverses and renders the hierarchy RenderTraverser *traverser = NULL; /// the hierarchy Bvh *bvh = NULL; /// handles scene loading ResourceManager *loader = NULL; /// the scene camera Camera *camera = NULL; /// the scene camera Camera *visCamera = NULL; /// the visualization Visualization *visualization = NULL; /// the current render state RenderState state; /// the rendering algorithm int renderMode = RenderTraverser::CHCPLUSPLUS; // eye near plane distance float nearDist = 1.0f; /// the pixel threshold where a node is still considered invisible int threshold; float fov = 50.0f; int assumedVisibleFrames = 10; int maxBatchSize = 50; int trianglesPerVirtualLeaf = INITIAL_TRIANGLES_PER_VIRTUAL_LEAVES; SceneQuery *sceneQuery = NULL; RenderQueue *renderQueue = NULL; /// these values get scaled with the frame rate const static float keyForwardMotion = 50.0f; const static float keyRotation = 2.0f; /// elapsed time in seconds double elapsedTime = 1.0f; double algTime = 1.0f; static int winWidth = 1024; static int winHeight = 768; static float winAspectRatio = 1.0f; double accumulatedTime = 1000; float fps = 1e3f; float myfar = 0; // rendertexture const static int texWidth = 1024; const static int texHeight = 768; //const static int texWidth = 2048; //const static int texHeight = 2048; 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; bool showHelp = false; bool showStatistics = true; bool showOptions = true; bool showBoundingVolumes = false; bool visMode = false; // mouse navigation state int xEyeBegin = 0; int yEyeBegin = 0; int yMotionBegin = 0; int verticalMotionBegin = 0; int horizontalMotionBegin = 0; bool useOptimization = false; bool useTightBounds = true; bool useRenderQueue = true; bool useMultiQueries = true; bool flyMode = true; bool depthPass = false; bool useGlFinish = false; SceneEntityContainer skyGeometry; bool leftKeyPressed = false; bool rightKeyPressed = false; bool upKeyPressed = false; bool downKeyPressed = false; bool nineKeyPressed = false; bool eightKeyPressed = false; static Vector3 samples[32]; GLubyte *randomNormals; // function forward declarations void InitExtensions(); void DisplayVisualization(); void InitGLstate(); void InitRenderTexture(); void InitCg(); void CleanUp(); void SetupEyeView(); void UpdateEyeMtx(); void SetupLighting(); void DisplayStats(); void Output(int x, int y, const char *string); void DrawHelpMessage(); void RenderSky(); void RenderVisibleObjects(); void Begin2D(); void End2D(); void KeyBoard(unsigned char c, int x, int y); void DrawStatistics(); void Display(); 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 state, int x, int y); void LeftMotion(int x, int y); void RightMotion(int x, int y); void MiddleMotion(int x, int y); void CalcDecimalPoint(string &str, int d); void ResetTraverser(); void KeyHorizontalMotion(float shift); void KeyVerticalMotion(float shift); void PlaceViewer(const Vector3 &oldPos); void DisplayRenderTexture(); inline float KeyRotationAngle() { return keyRotation * elapsedTime; } inline float KeyShift() { return keyForwardMotion * elapsedTime; } void InitFBO(); void GenerateSamples(); void CreateNoiseTex2D(); void ComputeViewVectors(Vector3 &tl, Vector3 &tr, Vector3 &bl, Vector3 &br); GLenum mrt[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT}; ///////// //-- cg stuff static CGcontext sCgContext = NULL; static CGprogram sCgMrtVertexProgram = NULL; static CGprogram sCgSSAOProgram = NULL; static CGprogram sCgMrtFragmentProgram = NULL; static CGprofile sCgFragmentProfile; static CGprofile sCgVertexProfile; static CGparameter sColorsTexParam; static CGparameter sPositionsTexParam; static CGparameter sNormalsTexParam; static CGparameter sNoiseTexParam; /*static CGparameter sTexSizeParam; static CGparameter sSamplesParam; static CGparameter sEyeVecParam; static CGparameter sRadiusParam; */ static CGparameter sProjectionMatrixParam; static CGparameter sModelViewMatrixParam; static CGparameter sMaxDepthParam; const static float radius = 1e-3f; static void cgErrorCallback() { CGerror lastError = cgGetError(); if(lastError) { printf("%s\n\n", cgGetErrorString(lastError)); printf("%s\n", cgGetLastListing(sCgContext)); printf("Cg error, exiting...\n"); exit(0); } } 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[]) { int returnCode = 0; camera = new Camera(winWidth, winHeight, fov); camera->SetNear(nearDist); visCamera = new Camera(winWidth, winHeight, fov); visCamera->SetNear(0.0f); visCamera->Yaw(.5 * M_PI); renderQueue = new RenderQueue(&state, camera); glutInitWindowSize(winWidth, winHeight); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); glutCreateWindow("FriendlyCulling"); glutDisplayFunc(Display); glutKeyboardFunc(KeyBoard); glutSpecialFunc(Special); glutReshapeFunc(Reshape); glutMouseFunc(Mouse); glutIdleFunc(Display); glutKeyboardUpFunc(KeyUp); glutSpecialUpFunc(SpecialKeyUp); glutIgnoreKeyRepeat(true); InitExtensions(); InitGLstate(); //InitRenderTexture(); InitFBO(); LeftMotion(0, 0); MiddleMotion(0, 0); loader = new ResourceManager(); //const string filename("data/city/model/city.dem"); const string filename = string(model_path + "city.dem"); if (loader->Load(filename, sceneEntities)) cout << "scene " << filename << " loaded" << endl; else { cerr << "loading scene " << filename << " failed" << endl; CleanUp(); exit(0); } SceneEntityContainer dummy; const string envname = string(model_path + "env.dem"); if (loader->Load(envname, skyGeometry)) cout << "sky box " << filename << " loaded" << endl; else { cerr << "loading sky box " << filename << " failed" << endl; CleanUp(); exit(0); } // create noise texture for ssao CreateNoiseTex2D(); const string bvh_filename = string(model_path + "city.bvh"); BvhLoader bvhLoader; bvh = bvhLoader.Load(bvh_filename, sceneEntities); //bvh = bvhLoader.Load("data/city/model/city.bvh", sceneEntities); myfar = 1.0f * Magnitude(bvh->GetBox().Diagonal()); if (!bvh) { cerr << "loading bvh " << bvh_filename << " failed" << endl; CleanUp(); exit(0); } InitCg(); bvh->SetCamera(camera); ResetTraverser(); camera->Pitch(-M_PI * 0.5); camera->SetPosition(Vector3(483.398f, 242.364f, 186.078f)); visualization = new Visualization(bvh, camera, NULL, &state); sceneQuery = new SceneQuery(bvh->GetBox(), traverser); glutMainLoop(); // clean up CleanUp(); return 0; } void InitCg(void) { GenerateSamples(); // Setup Cg cgSetErrorCallback(cgErrorCallback); // Create cgContext. sCgContext = cgCreateContext(); // get the best profile for this hardware sCgFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); //assert(sCgFragmentProfile != CG_PROFILE_UNKNOWN); cgGLSetOptimalOptions(sCgFragmentProfile); sCgVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); cgGLSetOptimalOptions(sCgVertexProfile); sCgMrtVertexProgram = cgCreateProgramFromFile(sCgContext, CG_SOURCE, "src/shaders/mrt.cg", sCgVertexProfile, "vtx", NULL); if(sCgMrtVertexProgram != NULL) { cgGLLoadProgram(sCgMrtVertexProgram); sModelViewMatrixParam = cgGetNamedParameter(sCgMrtVertexProgram, "ModelViewProj"); } sCgMrtFragmentProgram = cgCreateProgramFromFile(sCgContext, CG_SOURCE, "src/shaders/mrt.cg", sCgFragmentProfile, "frag", NULL); if(sCgMrtFragmentProgram != NULL) { cgGLLoadProgram(sCgMrtFragmentProgram); sMaxDepthParam = cgGetNamedParameter(sCgMrtFragmentProgram, "maxDepth"); cgGLSetParameter1f(sMaxDepthParam, 1.0f / myfar); } else cerr << "test program failed to load" << endl; PrintGLerror("test"); /////////////// sCgSSAOProgram = cgCreateProgramFromFile(sCgContext, CG_SOURCE, "src/shaders/deferred.cg", //"src/test.cg", sCgFragmentProfile, NULL, NULL); if(sCgSSAOProgram != NULL) { cgGLLoadProgram(sCgSSAOProgram); // we need size of texture for scaling sPositionsTexParam = cgGetNamedParameter(sCgSSAOProgram, "positions"); sColorsTexParam = cgGetNamedParameter(sCgSSAOProgram, "colors"); sNormalsTexParam = cgGetNamedParameter(sCgSSAOProgram, "normals"); sNoiseTexParam = cgGetNamedParameter(sCgSSAOProgram, "noiseTexture"); sProjectionMatrixParam = cgGetNamedParameter(sCgSSAOProgram, "ProjTrafo"); /*sTexSizeParam = cgGetNamedParameter(sCgSSAOProgram, "invTexSize"); sRadiusParam = cgGetNamedParameter(sCgSSAOProgram, "radius"); sEyeVecParam = cgGetNamedParameter(sCgSSAOProgram, "eyevec"); sSamplesParam = cgGetNamedParameter(sCgSSAOProgram, "samples"); cgGLSetParameter1f(sTexSizeParam, 1.0f / (float)texWidth); cgGLSetParameter1f(sRadiusParam, radius); cgGLSetParameterArray3f(sSamplesParam, 0, 32, (const float *)samples);*/ } else cerr << "ssao program failed to load" << endl; PrintGLerror("init"); } void PrintFBOStatus(GLenum status) { switch(status) { case GL_FRAMEBUFFER_COMPLETE_EXT: cout << "frame buffer object created successfully" << endl; break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: cerr << "incomplete attachment" << endl; break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: cerr << "missing attachment" << endl; break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: cerr << "incomplete dimensions" << endl; break; case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: cerr << "incomplete formats" << endl; break; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: cerr << "incomplete draw buffer" << endl; break; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: cerr << "incomplete read buffer" << endl; break; case GL_FRAMEBUFFER_UNSUPPORTED_EXT: cerr << "framebuffer unsupported" << endl; break; default: cerr << "unknown status code " << status << endl; } } void InitFBO() { glGenFramebuffersEXT(1, &fbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); ////////// //-- positions buffer int samples = 8; //////////// //-- colors buffer glGenRenderbuffersEXT(1, &colorsBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, colorsBuffer); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA32F_ARB, texWidth, texHeight); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, colorsBuffer); glGenTextures(1, &colorsTex); glBindTexture(GL_TEXTURE_2D, colorsTex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, texWidth, texHeight, 0, GL_RGBA, GL_FLOAT, NULL); glGenerateMipmapEXT(GL_TEXTURE_2D); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, colorsTex, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); PrintFBOStatus(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); glGenRenderbuffersEXT(1, &positionsBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, positionsBuffer); //glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA32F_ARB, texWidth, texHeight); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_RGBA32F_ARB, texWidth, texHeight); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, positionsBuffer); glGenTextures(1, &positionsTex); glBindTexture(GL_TEXTURE_2D, positionsTex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, texWidth, texHeight, 0, GL_RGBA, GL_FLOAT, NULL); //glGenerateMipmapEXT(GL_TEXTURE_2D); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, positionsTex, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); PrintFBOStatus(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); //////// //-- normals buffer glGenRenderbuffersEXT(1, &normalsBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, normalsBuffer); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA32F_ARB, texWidth, texHeight); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_RENDERBUFFER_EXT, normalsBuffer); glGenTextures(1, &normalsTex); glBindTexture(GL_TEXTURE_2D, normalsTex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, texWidth, texHeight, 0, GL_RGBA, GL_FLOAT, NULL); //glGenerateMipmapEXT(GL_TEXTURE_2D); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, normalsTex, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); PrintFBOStatus(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); /////////// //-- create depth buffer glGenRenderbuffersEXT(1, &depthBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, texWidth, texHeight); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer); PrintFBOStatus(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); //////////////// //-- second fbo /*glGenFramebuffersEXT(1, &fbo2); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo2); // create color buffer glGenRenderbuffersEXT(1, &occlusionbuffer); //glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA32F_ARB, texWidth, texHeight); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_FLOAT_RGBA_NV, texWidth2, texHeight2); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, occlusionbuffer); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, occlusionbuffer); glGenTextures(1, &occlusionTex); glBindTexture(GL_TEXTURE_2D, occlusionTex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, texWidth2, texHeight2, 0, GL_RGBA, GL_FLOAT, NULL); glGenerateMipmapEXT(GL_TEXTURE_2D); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, colorTex, 0); PrintFBOStatus(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);*/ PrintGLerror("fbo"); } void InitGLstate(void) { glClearColor(0.5f, 0.5f, 0.8f, 0.0f); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT,1); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); SetupLighting(); glColor3f(1.0f, 1.0f, 1.0f); glShadeModel(GL_SMOOTH); glMaterialf(GL_FRONT, GL_SHININESS, 64); glEnable(GL_NORMALIZE); //glEnable(GL_ALPHA_TEST); glDisable(GL_ALPHA_TEST); glAlphaFunc(GL_GEQUAL, 0.5f); glFrontFace(GL_CCW); glCullFace(GL_BACK); glEnable(GL_CULL_FACE); //glDisable(GL_CULL_FACE); glDisable(GL_TEXTURE_2D); GLfloat ambientColor[] = {0.5, 0.5, 0.5, 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); } void DrawHelpMessage(void) { 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 statistics", "'F5', - shows/hides parameters", "'F6', - toggles between fly / walkmode", "'F7', - depth pass", "'F8', - enable/disable glFinish for more accurate timings", "'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' - move forward", "'CURSOR BACK' - move backward", "'CURSOR RIGHT' - turn right", "'CURSOR LEFT' - turn left", "", "'-' - decreases max batch size", "'+' - increases max batch size", "'4' - decrease triangles per virtual leaf (sets depth of bvh)", "'5' - increase triangles per virtual leaf (sets depth of bvh)", "'6' - decrease assumed visible frames", "'7' - increase assumed visible frames", "'8' - downward motion", "'9' - upward motion", "", "'R' - use render queue", "'B' - use tight bounds", "'M' - use multiqueries", "'O' - use CHC optimization (geometry queries for leaves)", 0, }; int x = 40, y = 60; glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glColor4f(0.0f, 1.0f , 0.0f, 0.2f); // 20% green. // Drawn clockwise because the flipped Y axis flips CCW and CW. glRecti(winWidth - 30, 30, 30, winHeight - 30); glDisable(GL_BLEND); glColor3f(1.0f, 1.0f, 1.0f); for(int i = 0; message[i] != 0; i++) { if(message[i][0] == '\0') { y += 15; } else { Output(x, y, message[i]); y += 20; } } } void ResetTraverser() { DEL_PTR(traverser); bvh->ResetNodeClassifications(); switch (renderMode) { case RenderTraverser::CULL_FRUSTUM: traverser = new FrustumCullingTraverser(); break; case RenderTraverser::STOP_AND_WAIT: traverser = new StopAndWaitTraverser(); break; case RenderTraverser::CHC: traverser = new CHCTraverser(); break; case RenderTraverser::CHCPLUSPLUS: traverser = new CHCPlusPlusTraverser(); break; default: traverser = new FrustumCullingTraverser(); } traverser->SetCamera(camera); traverser->SetHierarchy(bvh); traverser->SetRenderQueue(renderQueue); traverser->SetRenderState(&state); traverser->SetUseOptimization(useOptimization); traverser->SetUseRenderQueue(useRenderQueue); traverser->SetVisibilityThreshold(threshold); traverser->SetAssumedVisibleFrames(assumedVisibleFrames); traverser->SetMaxBatchSize(maxBatchSize); traverser->SetUseMultiQueries(useMultiQueries); traverser->SetUseTightBounds(useTightBounds); traverser->SetUseDepthPass(depthPass); traverser->SetRenderQueue(renderQueue); } void SetupLighting() { glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); //glEnable(GL_LIGHT1); glDisable(GL_LIGHT1); //GLfloat ambient[] = {0.5, 0.5, 0.5, 1.0}; GLfloat ambient[] = {0.2, 0.2, 0.2, 1.0}; GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0}; GLfloat specular[] = {1.0, 1.0, 1.0, 1.0}; GLfloat lmodel_ambient[] = {0.5f, 0.5f, 0.5f, 1.0f}; //GLfloat lmodel_ambient[] = {0.2f, 0.2f, 0.2f, 1.0f}; glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, specular); GLfloat position[] = {1.0, 1.0, 1.0, 0.0}; glLightfv(GL_LIGHT0, GL_POSITION, position); //////////// //-- second light GLfloat ambient1[] = {0.5, 0.5, 0.5, 1.0}; //GLfloat diffuse1[] = {1.0, 1.0, 1.0, 1.0}; GLfloat diffuse1[] = {0.5, 0.5, 0.5, 1.0}; GLfloat specular1[] = {0.5, 0.5, 0.5, 1.0}; glLightfv(GL_LIGHT1, GL_AMBIENT, ambient1); glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse1); glLightfv(GL_LIGHT1, GL_SPECULAR, specular1); GLfloat position1[] = {0.0, 1.0, 0.0, 1.0}; glLightfv(GL_LIGHT1, GL_POSITION, position1); 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_SEPARATE_SPECULAR_COLOR_EXT); glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SINGLE_COLOR_EXT); } void SetupEyeView() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(fov, 1.0f / winAspectRatio, nearDist, myfar); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); camera->SetupCameraView(); GLfloat position[] = {0.8f, 1.0f, 1.5f, 0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, position); GLfloat position1[] = {bvh->GetBox().Center().x, bvh->GetBox().Center().y, bvh->GetBox().Max().z, 1.0f}; glLightfv(GL_LIGHT1, GL_POSITION, position1); } 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 Display() { PerfTimer frameTimer, algTimer; frameTimer.Start(); Vector3 oldPos = camera->GetPosition(); if (leftKeyPressed) camera->Pitch(KeyRotationAngle()); if (rightKeyPressed) camera->Pitch(-KeyRotationAngle()); if (upKeyPressed) KeyHorizontalMotion(KeyShift()); if (downKeyPressed) KeyHorizontalMotion(-KeyShift()); if (eightKeyPressed) KeyVerticalMotion(-KeyShift()); if (nineKeyPressed) KeyVerticalMotion(KeyShift()); // place view on ground if (!flyMode) PlaceViewer(oldPos); if (useGlFinish) glFinish(); algTimer.Start(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); glPushAttrib(GL_VIEWPORT_BIT); glViewport(0, 0, texWidth, texHeight); cgGLEnableProfile(sCgFragmentProfile); cgGLBindProgram(sCgMrtFragmentProgram); cgGLEnableProfile(sCgVertexProfile); cgGLBindProgram(sCgMrtVertexProgram); glDrawBuffers(3, mrt); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDepthFunc(GL_LESS); glDisable(GL_TEXTURE_2D); glDisableClientState(GL_TEXTURE_COORD_ARRAY); // render without shading if (depthPass) { state.SetDepthPass(true); glDisable(GL_LIGHTING); } else { state.SetDepthPass(false); glEnable(GL_LIGHTING); } // bring eye modelview matrix up-to-date SetupEyeView(); Vector3 dir = camera->GetDirection(); //cgGLSetParameter3f(sEyeVecParam, dir.x, dir.y, dir.z); // set modelview matrix for shaders cgGLSetStateMatrixParameter(sModelViewMatrixParam, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); cgGLEnableProfile(sCgVertexProfile); // actually render the scene geometry using one of the specified algorithms traverser->RenderScene(); ////// //-- do the rest of the rendering glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); // reset depth pass and render visible objects if (depthPass) { RenderVisibleObjects(); } /////////////// //-- render sky RenderSky(); state.Reset(); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); cgGLDisableProfile(sCgVertexProfile); cgGLDisableProfile(sCgFragmentProfile); glPopAttrib(); cgGLSetStateMatrixParameter(sProjectionMatrixParam, CG_GL_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); DisplayRenderTexture(); if (useGlFinish) glFinish(); algTime = algTimer.Elapsedms(); /////////// if (visMode) DisplayVisualization(); DisplayStats(); glutSwapBuffers(); elapsedTime = frameTimer.Elapsed(); } #pragma warning( disable : 4100 ) void KeyBoard(unsigned char c, int x, int y) { switch(c) { case 27: CleanUp(); exit(0); break; case 32: //space renderMode = (renderMode + 1) % RenderTraverser::NUM_TRAVERSAL_TYPES; ResetTraverser(); break; case 'h': case 'H': showHelp = !showHelp; break; case '+': maxBatchSize += 10; traverser->SetMaxBatchSize(maxBatchSize); break; case '-': maxBatchSize -= 10; if (maxBatchSize < 0) maxBatchSize = 1; traverser->SetMaxBatchSize(maxBatchSize); break; case '6': assumedVisibleFrames -= 1; if (assumedVisibleFrames < 1) assumedVisibleFrames = 1; traverser->SetAssumedVisibleFrames(assumedVisibleFrames); break; case '7': assumedVisibleFrames += 1; traverser->SetAssumedVisibleFrames(assumedVisibleFrames); break; case 'M': case 'm': useMultiQueries = !useMultiQueries; traverser->SetUseMultiQueries(useMultiQueries); break; case '8': eightKeyPressed = true; break; case '9': nineKeyPressed = true; break; case 'o': case 'O': useOptimization = !useOptimization; traverser->SetUseOptimization(useOptimization); break; case 'a': case 'A': leftKeyPressed = true; break; case 'd': case 'D': rightKeyPressed = true; break; case 'w': case 'W': upKeyPressed = true; break; case 'x': case 'X': downKeyPressed = true; break; case 'r': case 'R': { useRenderQueue = !useRenderQueue; traverser->SetUseRenderQueue(useRenderQueue); } break; case 'b': case 'B': { useTightBounds = !useTightBounds; traverser->SetUseTightBounds(useTightBounds); } break; case '4': if (trianglesPerVirtualLeaf >= 100) trianglesPerVirtualLeaf -= 100; bvh->SetVirtualLeaves(trianglesPerVirtualLeaf); break; case '5': trianglesPerVirtualLeaf += 100; bvh->SetVirtualLeaves(trianglesPerVirtualLeaf); 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; default: return; } //glutPostRedisplay(); } 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 'X': case 'x': downKeyPressed = false; break; case '8': eightKeyPressed = false; break; case '9': nineKeyPressed = 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: showStatistics = !showStatistics; break; case GLUT_KEY_F5: showOptions = !showOptions; break; case GLUT_KEY_F6: flyMode = !flyMode; break; case GLUT_KEY_F7: depthPass = !depthPass; traverser->SetUseDepthPass(depthPass); break; case GLUT_KEY_F8: useGlFinish = !useGlFinish; 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) h / (float) w; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(fov, 1.0f / winAspectRatio, nearDist, myfar); glMatrixMode(GL_MODELVIEW); glutPostRedisplay(); } void Mouse(int button, int state, int x, int y) { if ((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN)) { xEyeBegin = x; yMotionBegin = y; glutMotionFunc(LeftMotion); } else if ((button == GLUT_RIGHT_BUTTON) && (state == GLUT_DOWN)) { yEyeBegin = y; yMotionBegin = y; glutMotionFunc(RightMotion); } else if ((button == GLUT_MIDDLE_BUTTON) && (state == 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) * 0.2f; camera->SetPosition(pos); xEyeBegin = x; yMotionBegin = y; glutPostRedisplay(); } /** rotation for left / right mouse drag motion for up / down mouse drag */ void RightMotion(int x, int y) { float eyeYAngle = -0.2f * M_PI * (yEyeBegin - y) / 180.0; camera->Yaw(eyeYAngle); 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) * 0.1f; pos[2] += (verticalMotionBegin - y) * 0.1f; 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(void) { glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0, winWidth, winHeight, 0); } void End2D(void) { glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); } void Output(int x, int y, const char *string) { if (string != 0) { size_t len, i; glRasterPos2f(x, y); len = strlen(string); for (i = 0; i < len; ++ i) { glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, string[i]); } } } // displays the visualisation of culling algorithm void DisplayVisualization() { visualization->SetFrameId(traverser->GetCurrentFrameId()); Begin2D(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glColor4f(0.0,0.0,0.0,0.5); glRecti(winWidth, 0, winWidth - winWidth / 3, winHeight / 3); glDisable(GL_BLEND); End2D(); AxisAlignedBox3 box = bvh->GetBox(); // set far for viz camera->SetFar(0.35f * Magnitude(box.Diagonal())); const float offs = box.Size().x * 0.3f; //const float yoffs = box.Size().y * 0.5f; Vector3 pos = camera->GetPosition(); Vector3 vizpos = Vector3(box.Min().x + 20, box.Min().y + 500, box.Min().z + box.Size().z * 50); visCamera->SetPosition(vizpos); glViewport(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth / 3, winHeight / 3); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-offs, offs, -offs, offs, 0.0f, box.Size().z * 100.0f); glMatrixMode(GL_MODELVIEW); visCamera->SetupCameraView(); Matrix4x4 rotZ = RotationZMatrix(-camera->GetPitch()); glMultMatrixf((float *)rotZ.x); 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(); // reset vp glViewport(0, 0, winWidth, winHeight); } // 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(loader); DEL_PTR(renderQueue); if (sCgMrtVertexProgram) cgDestroyProgram(sCgMrtVertexProgram); if (sCgSSAOProgram) cgDestroyProgram(sCgSSAOProgram); if (sCgContext) cgDestroyContext(sCgContext); glDeleteFramebuffersEXT(1, &fbo); glDeleteRenderbuffersEXT(1, &depthBuffer); glDeleteRenderbuffersEXT(1, &colorsBuffer); glDeleteRenderbuffersEXT(1, &normalsBuffer); glDeleteRenderbuffersEXT(1, &positionsBuffer); glDeleteTextures(1, &colorsTex); glDeleteTextures(1, &normalsTex); glDeleteTextures(1, &positionsTex); glDeleteTextures(1, &noiseTex); } // this function inserts a dezimal point after each 1000 void CalcDecimalPoint(string &str, int d) { vector numbers; 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()); str.append(hstr); } for (int i = (int)numbers.size() - 2; i >= 0; i--) { sprintf(hstr, ",%03d", numbers[i]); str.append(hstr); } } void DisplayStats() { static char msg[7][300]; static double renderTime = algTime; const float expFactor = 0.5f; // if some strange render time spike happened in this frame => don't count if (algTime < 500) renderTime = algTime * expFactor + (1.0f - expFactor) * algTime; accumulatedTime += elapsedTime * 1e3f; if (accumulatedTime > 500) // update every fraction of a second { accumulatedTime = 0; if (renderTime) fps = 1e3f / (float)renderTime; renderedObjects = traverser->GetStats().mNumRenderedGeometry; renderedNodes = traverser->GetStats().mNumRenderedNodes; renderedTriangles = traverser->GetStats().mNumRenderedTriangles; traversedNodes = traverser->GetStats().mNumTraversedNodes; frustumCulledNodes = traverser->GetStats().mNumFrustumCulledNodes; queryCulledNodes = traverser->GetStats().mNumQueryCulledNodes; issuedQueries = traverser->GetStats().mNumIssuedQueries; stateChanges = traverser->GetStats().mNumStateChanges; numBatches = traverser->GetStats().mNumBatches; } string str; string str2; int i = 0; CalcDecimalPoint(str, renderedTriangles); CalcDecimalPoint(str2, bvh->GetBvhStats().mTriangles); sprintf(msg[i ++], "rendered nodes: %6d (of %6d), rendered triangles: %s (of %s)", renderedNodes, bvh->GetNumVirtualNodes(), str.c_str(), str2.c_str()); sprintf(msg[i ++], "traversed: %5d, frustum culled: %5d, query culled: %5d", traversedNodes, frustumCulledNodes, queryCulledNodes); sprintf(msg[i ++], "issued queries: %5d, state changes: %5d, render batches: %5d", issuedQueries, stateChanges, numBatches); sprintf(msg[i ++], "fps: %6.1f", fps); sprintf(msg[i ++], "assumed visible frames: %4d, max batch size: %4d", assumedVisibleFrames, maxBatchSize); sprintf(msg[i ++], "multiqueries: %d, tight bounds: %d, render queue: %d, depth pass: %d, glFinish: %d", useMultiQueries, useTightBounds, useRenderQueue, depthPass, useGlFinish); sprintf(msg[i ++], "triangles per virtual leaf: %5d", trianglesPerVirtualLeaf); Begin2D(); if(showHelp) { DrawHelpMessage(); } else { static char *alg_str[] = {"Frustum Culling", "Stop and Wait", "CHC", "CHC ++"}; glColor3f(1.0f, 1.0f, 1.0f); Output(850, 30, alg_str[renderMode]); if (showStatistics) { for (int i = 0; i < 4; ++ i) Output(20, (i + 1) * 30, msg[i]); } if (showOptions) { for (int i = 4; i < 8; ++ i) Output(20, (i + 1) * 30, msg[i]); } } End2D(); } void RenderSky() { SceneEntityContainer::const_iterator sit, sit_end = skyGeometry.end(); for (sit = skyGeometry.begin(); sit != sit_end; ++ sit) (*sit)->Render(&state); } void RenderVisibleObjects() { state.SetDepthPass(false); state.Reset(); glEnable(GL_LIGHTING); glDepthFunc(GL_LEQUAL); //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); renderQueue->Apply(); glDepthFunc(GL_LESS); } void PlaceViewer(const Vector3 &oldPos) { Vector3 playerPos = camera->GetPosition(); bool validIntersect = sceneQuery->CalcIntersection(playerPos); if (validIntersect && (( playerPos.z - oldPos.z) < bvh->GetBox().Size(2) * 1e-1f)) { camera->SetPosition(playerPos); } } void DisplayRenderTexture() { glDisable(GL_TEXTURE_2D); //glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); //glBindTexture(GL_TEXTURE_2D, noiseTex); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); const float offs = 0.5f; //glPushAttrib(GL_VIEWPORT_BIT); //glViewport(-offs, texHeight); glOrtho(-offs, offs, -offs, offs, 0, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); cgGLEnableProfile(sCgFragmentProfile); cgGLBindProgram(sCgSSAOProgram); cgGLEnableTextureParameter(sPositionsTexParam); cgGLSetTextureParameter(sPositionsTexParam, positionsTex); cgGLEnableTextureParameter(sColorsTexParam); cgGLSetTextureParameter(sColorsTexParam, colorsTex); cgGLEnableTextureParameter(sNormalsTexParam); cgGLSetTextureParameter(sNormalsTexParam, normalsTex); cgGLEnableTextureParameter(sNoiseTexParam); cgGLSetTextureParameter(sNoiseTexParam, noiseTex); Vector3 tl, tr, bl, br; ComputeViewVectors(tl, tr, bl, br); glColor3f(1.0f, 1.0f, 1.0f); glBegin(GL_QUADS); #if 1 // slightly larger than screen size in order to hide ambient occlusion errors float offs2 = 0.55f; //float offs2 = 0.5f; glColor3f(bl.x, bl.y, bl.z); glTexCoord2f(0, 0); glVertex3f(-offs2, -offs2, -0.5f); glColor3f(br.x, br.y, br.z); glTexCoord2f(1, 0); glVertex3f( offs2, -offs2, -0.5f); glColor3f(tr.x, tr.y, tr.z); glTexCoord2f(1, 1); glVertex3f( offs2, offs2, -0.5f); glColor3f(tl.x, tl.y, tl.z); glTexCoord2f(0, 1); glVertex3f(-offs2, offs2, -0.5f); #else glTexCoord2f(0, 0); glVertex3f(-1, -1, -0.5f); glTexCoord2f(1, 0); glVertex3f( 1, -1, -0.5f); glTexCoord2f(1, 1); glVertex3f( 1, 1, -0.5f); glTexCoord2f(0, 1); glVertex3f(-1, 1, -0.5f); #endif glEnd(); cgGLDisableTextureParameter(sColorsTexParam); cgGLDisableTextureParameter(sPositionsTexParam); cgGLDisableTextureParameter(sNormalsTexParam); cgGLDisableTextureParameter(sNoiseTexParam); cgGLDisableProfile(sCgFragmentProfile); glEnable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); PrintGLerror("displaytexture"); } void GenerateSamples() { // fill an n * n * 2 array with uniformly distributed spherical samples for (int i = 0; i < 32; ++ i) { // create stratified samples over sphere const float rx = RandomValue(0, 1); const float ry = RandomValue(0, 1); //const float l = RandomValue(0, 1); const float theta = 2.0f * acos(sqrt(1.0f - rx)); const float phi = 2.0f * M_PI * ry; samples[i] = Vector3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); cout << samples[i] << endl; } } void ComputeViewVectors(Vector3 &tl, Vector3 &tr, Vector3 &bl, Vector3 &br) { float myfov = fov * M_PI / 180.0f; const float h_far = 2.0f * tan(myfov / 2.0f); const float w_far = h_far * texWidth / texHeight; float t1 = h_far * 0.5f; float t2 = w_far * 0.5f; bl = Normalize(Vector3(-t1, -t2, 1.0f)); br = Normalize(Vector3( t1, -t2, 1.0f)); tl = Normalize(Vector3(-t1, t2, 1.0f)); tr = Normalize(Vector3( t1, t2, 1.0f)); // normalize to 0 .. 1 bl = bl * 0.5f + 0.5f; br = br * 0.5f + 0.5f; tl = tl * 0.5f + 0.5f; tr = tr * 0.5f + 0.5f; } void CreateNoiseTex2D() { randomNormals = new GLubyte[texWidth * texHeight * 4]; for (int i = 0; i < texWidth * texHeight * 4; i += 4) { // create random samples over sphere const float rx = RandomValue(0, 1); const float theta = 2.0f * acos(sqrt(1.0f - rx)); randomNormals[i + 0] = (GLubyte)((cos(theta) * 0.5f + 0.5f) * 255.0f); randomNormals[i + 1] = (GLubyte)((sin(theta) * 0.5f + 0.5f) * 255.0f); randomNormals[i + 2] = 0; randomNormals[i + 3] = 255; } glEnable(GL_TEXTURE_2D); glGenTextures(1, &noiseTex); glBindTexture(GL_TEXTURE_2D, noiseTex); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_BYTE, randomNormals); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); cout << "created noise texture" << endl; PrintGLerror("noisetexture"); }