Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 3 of 3

Thread: OpenGL Shadow Mapping problem

  1. #1
    Newbie Newbie
    Join Date
    Apr 2014
    Posts
    2

    OpenGL Shadow Mapping problem

    Hi, I'm new to opengl and I'm trying to get shadow mapping work.
    I've followed the tutorial on shadow mapping from opengl-tutorial.org but now I'm having some problem:

    when I run my program this is what i get:
    Click image for larger version. 

Name:	Schermata da 2014-09-04 09:15:40.jpg 
Views:	31 
Size:	10.6 KB 
ID:	1418

    Now I've noticed that my shadow texture is not created correctly, using gDEBugger I get this shadow texture:
    Click image for larger version. 

Name:	shadow.jpg 
Views:	25 
Size:	3.6 KB 
ID:	1419

    Note that my light source corresponds with camera position.
    It can be seen that the shadow is not created correctly. The most evident problem is that the upper piece of shadow is not created at all and the rest of the shadow maps seems to be flat, the values seems to differ very little between them.

    Now I really don't have idea on what's going wrong. This is my source code:

    Code :
    #include "MeshViewer.h"
    #include <cmath>
    #include <iostream>
    #include <sstream>
    #include <GL/gl.h>
     
    #include <glm/gtc/matrix_transform.hpp>
    #include <glm/gtc/type_ptr.hpp>
     
    #include <glm/gtc/matrix_inverse.hpp>
    #include "utilities.hpp"
    #include "glm/ext.hpp"
     
    MeshViewer::MeshViewer(std::string pathMesh) {
      window_ = NULL;
      vertexArrayObj_ = 0;
      vertexBufferObj_ = 0;
      facetBufferObj_ = 0;
      normalBufferObj_ = 0;
      meshImporter_.setPathMesh(pathMesh);
      cameraTransformationController_ = NULL;
      textureManager_ = NULL;
      camParser_ = NULL;
      imageWidth_ = 640;
      imageHeight_ = 480;
      framebufferProj_ = 0;
      framebufferTexture_ = 0;
      depthTexture_ = 0;
      unwrappedTexture_ = 0;
    }
     
    MeshViewer::~MeshViewer() {
      // Cleanup VBO
      glDeleteBuffers(1, &vertexBufferObj_);
      glDeleteBuffers(1, &facetBufferObj_);
      glDeleteBuffers(1, &normalBufferObj_);
      glDeleteBuffers(1, &uvBufferObj_);
      glDeleteVertexArrays(1, &vertexArrayObj_);
     
      glfwTerminate();
    }
    //-------------------------------------------------------------------------------------
    //-------------------------------------------------------------------------------------
    //-------------------------------------------------------------------------------------
    //-------------------------------------------------------------------------------------
    void MeshViewer::run() {
      initGlfw();
      glfwMakeContextCurrent(window_);
      glewExperimental = GL_TRUE;
      glewInit();
      // Ensure we can capture the escape key being pressed below
      glfwSetInputMode(window_, GLFW_STICKY_KEYS, GL_TRUE);
     
      // Dark blue background
      glClearColor(0.0f, 0.0f, 0.20f, 0.0f);
     
      // Enable depth test
      glEnable(GL_DEPTH_TEST);
      //glEnable(GL_LIGHTING);
     
      // Accept fragment if it closer to the camera than the former one
      glDepthFunc(GL_LESS);
     
      // Cull triangles which normal is not towards the camera
      //glEnable(GL_CULL_FACE);
      //glCullFace(GL_BACK); // Cull back-facing triangles -> draw only front-facing triangles
     
      shaderManDepth_.init();
      shaderManDepth_.addShader(GL_VERTEX_SHADER, "/home/dan/workspace/opengl-mesh-shader-and-visualizer/shaders/depth_vertex_shader.glsl");
      shaderManDepth_.addShader(GL_FRAGMENT_SHADER, "/home/dan/workspace/opengl-mesh-shader-and-visualizer/shaders/depth_fragment_shader.glsl");
     
      shaderManDepth_.finalize();
     
      // Get a handle for our "MVP" uniform
      GLuint depthMatrixID = shaderManDepth_.getUniformLocation("MVP");
     
      meshImporter_.importMesh();
     
      glGenVertexArrays(1, &vertexArrayObj_);
      glBindVertexArray(vertexArrayObj_);
     
      createVertexBuffer();
      createNormalBuffer();
      createFacetBuffer();
      createUVBuffer();
     
      renderDepthTexture();
      renderSceneToTexture();
     
      /*GLint maxTextureUnits = 0;
      glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
      std::cout << maxTextureUnits << std::endl;*/
     
      // Create and compile our GLSL program from the shaders (second pass)
      initAndCompileShaders();
     
      // Get a handle for our fragment uniforms variables
      GLuint textureId  = shaderMan_.getUniformLocation("myTextureSampler");
      GLuint shadowMapId = shaderMan_.getUniformLocation("shadowMap");
      // Get a handle for our vertex uniforms variables
      GLuint mvpID = shaderMan_.getUniformLocation("MVP");
      GLuint depthBiasId = shaderMan_.getUniformLocation("depthBiasMVP");
     
      camParser_ = new CamParser("/home/dan/workspace/photometricsurfaceevolution/dino_flipped/dinoR_par.txt");
      textureManager_ = new TextureManager(GL_TEXTURE_2D);
      camParser_->parseFile();
     
      int i = 0;
      //Load all the cameras
      //for(int i = 0; i < camParser_->getNumCameras(); i++){
      cameraLoad(i);
      std::string fileName = "/home/dan/workspace/opengl-mesh-shader-and-visualizer/dino_flipped/dinoR"+utils::getFrameNumber(i+1, 4)+".png";
      //std::string  fileName = "/home/dan/workspace/opengl-mesh-shader-and-visualizer/kitti/kitti_image_02_seq_0095_resized_rotated/0000000000.png";
      //Load texture into textureObj_:
      textureManager_->load(fileName);
      //}
     
     
      do {
        // Render to our framebuffer
        glBindFramebuffer(GL_FRAMEBUFFER, framebufferProj_);
        glViewport(0, 0, imageWidth_, imageHeight_); // Render on the whole framebuffer, complete from the lower left corner to the upper right
     
        // Clear the screen
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
        // Use our shader
        shaderManDepth_.enable();
     
        // Get the MVP matrix from the light's point of view
        glm::mat4 depthMVP = cameraTransformationController_->getInitMvpMatrix();
        //std::cout << "depthMVP: " << glm::to_string(depthMVP) << std::endl;
        // Send our transformation to the currently bound shader,
        // in the "MVP" uniform
        glUniformMatrix4fv(depthMatrixID, 1, GL_FALSE, &depthMVP[0][0]);
     
        // 1rst attribute buffer : vertices
        GLint posAttribId = shaderManDepth_.getAttribLocation("position");
        glEnableVertexAttribArray(posAttribId);
        glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObj_);
        glVertexAttribPointer(posAttribId, 3, GL_FLOAT, GL_FALSE, 0, 0);
     
        // Index buffer
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, facetBufferObj_);
        // Draw the triangles on the depth texture!
        glDrawElements(GL_TRIANGLES, meshImporter_.getFacets().size() / 3, GL_UNSIGNED_INT, 0);
     
        glDisableVertexAttribArray(posAttribId);
     
        // Render to the screen
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        //glBindFramebuffer(GL_FRAMEBUFFER, framebufferTexture_);
     
        glViewport(0, 0, imageWidth_, imageHeight_); // Render on the whole framebuffer, complete from the lower left corner to the upper right
     
        // Clear the screen
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
        shaderMan_.enable();
     
        cameraTransformationController_->moveCamFromInputs();
        glm::mat4 MVP = cameraTransformationController_->getCurMatrix();
        //std::cout << "MVP: " << glm::to_string(MVP) << std::endl;
     
        /*glm::mat4 biasMatrix(
            0.5, 0.0, 0.0, 0.0,
            0.0, 0.5, 0.0, 0.0,
            0.0, 0.0, 0.5, 0.0,
            0.5, 0.5, 0.5, 1.0
        );*/
     
        glm::mat4 depthBiasMVP = depthMVP;
        //std::cout << "depthBiasMVP: " << glm::to_string(depthBiasMVP) << std::endl;
     
        // Send our transformation to the currently bound shader, in the "MVP" uniform
        glUniformMatrix4fv(mvpID, 1, GL_FALSE, &MVP[0][0]);
        glUniformMatrix4fv(depthBiasId, 1, GL_FALSE, &depthBiasMVP[0][0]);
     
        //Active Texture unit 0 and bind textureObj_ to it
        textureManager_->bind(GL_TEXTURE0);
        // Set our "myTextureSampler" sampler to use Texture unit 0:
        glUniform1i(textureId, 0);
     
        //Active Texture unit 0 and bind depthTexture_ to it
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, depthTexture_);
        // Set our "shadowMap" sampler to use texture unit 1
        glUniform1i(shadowMapId, 1);
     
        // 1rst attribute buffer : vertices
        posAttribId = shaderMan_.getAttribLocation("position");
        glEnableVertexAttribArray(posAttribId);
        glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObj_);
        glVertexAttribPointer(posAttribId, 3, GL_FLOAT, GL_FALSE, 0, 0);
     
        // 2nd attribute buffer : UVs
        GLint uvAttrId = shaderMan_.getAttribLocation("vertexUV");
        glEnableVertexAttribArray(uvAttrId);
        glBindBuffer(GL_ARRAY_BUFFER, uvBufferObj_);
        glVertexAttribPointer(uvAttrId, 2, GL_FLOAT, GL_FALSE, 0, 0);
     
        // 3rd attribute buffer : normals
        GLint normalAttrId = shaderMan_.getAttribLocation("normal");
        glEnableVertexAttribArray(normalAttrId);
        glBindBuffer(GL_ARRAY_BUFFER, normalBufferObj_);
        glVertexAttribPointer(normalAttrId, 3, GL_FLOAT, GL_FALSE, 0, 0);
     
        // Index buffer
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, facetBufferObj_);
     
        // Draw the triangles !
        glDrawElements(GL_TRIANGLES, meshImporter_.getFacets().size(), GL_UNSIGNED_INT, 0);
     
        //unbind FBO (bind it to screen):
        //glBindFramebuffer(GL_FRAMEBUFFER, 0);
     
        glDisableVertexAttribArray(posAttribId);
        glDisableVertexAttribArray(uvAttrId);
        glDisableVertexAttribArray(normalAttrId);
        // put the stuff we've been drawing onto the display
        glfwSwapBuffers(window_);
        // update other events like input handling
        glfwPollEvents();
     
      } while (glfwGetKey(window_, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window_) == 0);
    }
     
     
    bool MeshViewer::initAndCompileShaders() {
      return initAndCompileShaders("/home/dan/workspace/opengl-mesh-shader-and-visualizer/shaders/vertex_shader.glsl",
          "/home/dan/workspace/opengl-mesh-shader-and-visualizer/shaders/fragment_shader.glsl");
    }
     
    bool MeshViewer::initAndCompileShaders(std::string vertexShaderPath, std::string fragShaderPath) {
      shaderMan_.init();
      shaderMan_.addShader(GL_VERTEX_SHADER, vertexShaderPath.c_str());
      shaderMan_.addShader(GL_FRAGMENT_SHADER, fragShaderPath.c_str());
     
      shaderMan_.finalize();
      return true;
    }
     
    bool MeshViewer::initGlfw() {
      // Initialize GLFW
      if (!glfwInit()) {
        fprintf(stderr, "Failed to initialize GLFW\n");
        return false;
      }
     
      glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
      glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
      glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
      glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
      glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
     
      window_ = glfwCreateWindow(imageWidth_, imageHeight_, "mumble...mumble", NULL, NULL);
     
      cameraTransformationController_ = new TransformationController(window_, static_cast<float>(imageWidth_), static_cast<float>(imageHeight_));
     
      if (window_ == NULL) {
        fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible.\n");
        glfwTerminate();
        return false;
      }
      return true;
    }
     
    void MeshViewer::cameraLoad(int numCamera) {
      std::vector<CameraType> cameraList = camParser_->getCamerasList();
      glm::mat3 camIntrinsic = cameraList[numCamera].intrinsics;
      float fx = camIntrinsic[0][0];
      float fy = camIntrinsic[1][1];
      float cx = camIntrinsic[0][2];
      float cy = camIntrinsic[1][2];
      cameraTransformationController_->setIntrinsicParameters(fx, fy, cx, cy);
      glm::mat3 rot = cameraList[numCamera].rotation;
      glm::vec3 tras = cameraList[numCamera].translation;
      cameraTransformationController_->setExtrinsicParameters(rot, tras);
      cameraTransformationController_->computeMatricesFromCam();
    }
     
    void MeshViewer::createVertexBuffer() {
      glGenBuffers(1, &vertexBufferObj_);
      glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObj_);
      glBufferData(GL_ARRAY_BUFFER, meshImporter_.getVertices().size() * sizeof(glm::vec3), &meshImporter_.getVertices()[0], GL_STATIC_DRAW);
    }
     
    void MeshViewer::createNormalBuffer() {
      glGenBuffers(1, &normalBufferObj_);
      glBindBuffer(GL_ARRAY_BUFFER, normalBufferObj_);
      glBufferData(GL_ARRAY_BUFFER, meshImporter_.getNormals().size() * sizeof(glm::vec3), &meshImporter_.getNormals()[0], GL_STATIC_DRAW);
    }
     
    void MeshViewer::createFacetBuffer() {
      glGenBuffers(1, &facetBufferObj_);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, facetBufferObj_);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER, meshImporter_.getFacets().size() * sizeof(GLuint), &meshImporter_.getFacets()[0], GL_STATIC_DRAW);
    }
     
    void MeshViewer::createUVBuffer() {
      glGenBuffers(1, &uvBufferObj_);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, uvBufferObj_);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER, meshImporter_.getUVs().size() * sizeof(GLuint), &meshImporter_.getUVs()[0], GL_STATIC_DRAW);
    }
     
    void MeshViewer::renderDepthTexture() {
      // ---------------------------------------------
      // Render to Texture - specific code begins here
      // ---------------------------------------------
      // The framebuffer, which regroups 0, 1, or more textures, and 0 or 1 depth buffer.
      glGenFramebuffers(1, &framebufferProj_);
      glBindFramebuffer(GL_FRAMEBUFFER, framebufferProj_);
     
      // Depth texture. Slower than a depth buffer, but you can sample it later in your shader
      glGenTextures(1, &depthTexture_);
      //std::cout << "depthTexture_ id: " << depthTexture_ << std::endl;
      glBindTexture(GL_TEXTURE_2D, depthTexture_);
      glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT16, imageWidth_, imageHeight_, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_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);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
     
      //DEPTH_ATTACHMENT: the texture will receive the result of the depth test
      glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture_, 0);
     
      // No color output in the bound framebuffer, only depth.
      glDrawBuffer(GL_NONE);
     
      // Always check that our framebuffer is ok
      if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
        std::cerr << "depthTextureLoadAndBind failed to load" << std::endl;
        return;
      }
    }
     
    void MeshViewer::renderSceneToTexture(){
      glGenFramebuffers(1, &framebufferTexture_);
      glBindFramebuffer(GL_FRAMEBUFFER, framebufferTexture_);
     
      // The texture we're going to render to
      glGenTextures(1, &unwrappedTexture_);
      //std::cout << "unwrappedTexture_ id: " << unwrappedTexture_ << std::endl;
     
      // "Bind" the newly created texture : all future texture functions will modify this texture
      glBindTexture(GL_TEXTURE_2D, unwrappedTexture_);
     
      // Give an empty image to OpenGL ( the last "0" means "empty" )
      glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, imageWidth_, imageHeight_, 0,GL_RGB, GL_UNSIGNED_BYTE, 0);
     
      // Poor filtering
      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);
     
      // The depth buffer
      glGenRenderbuffers(1, &depthrenderbuffer_);
      glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer_);
      glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, imageWidth_, imageHeight_);
      glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer_);
     
      // Set "renderedTexture" as our colour attachement #0
      glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, unwrappedTexture_, 0);
     
      // Always check that our framebuffer is ok
      if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
        std::cerr << "failed to render for Texture" << std::endl;
        return;
      }
    }

    Thank you in advance.
    Last edited by Donnie; 09-04-2014 at 01:58 AM.

  2. #2
    Newbie Newbie
    Join Date
    Apr 2014
    Posts
    2
    I've solved the problem above but now I don't know how to remove the shadow ac.ne.
    Some idea?

  3. #3
    Junior Member Regular Contributor
    Join Date
    Dec 2010
    Location
    Oakville, ON, CA
    Posts
    107
    The glPolygonOffset serves that purpose. You may also manually increase the depth (z coordinate) slightly in your vertex or fragment shaders.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •