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:
[ATTACH=CONFIG]728[/ATTACH]

Now I’ve noticed that my shadow texture is not created correctly, using gDEBugger I get this shadow texture:
[ATTACH=CONFIG]729[/ATTACH]

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:


#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
");
    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.
");
    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.

I’ve solved the problem above but now I don’t know how to remove the shadow ac.ne.
Some idea? :slight_smile:

The glPolygonOffset serves that purpose. You may also manually increase the depth (z coordinate) slightly in your vertex or fragment shaders.