PDA

View Full Version : OpenGL Shadow Mapping problem



Donnie
09-04-2014, 12:31 AM
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:
1418

Now I've noticed that my shadow texture is not created correctly, using gDEBugger I get this shadow texture:
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:



#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.

Donnie
09-05-2014, 07:05 AM
I've solved the problem above but now I don't know how to remove the shadow ac.ne.
Some idea? :)

Yandersen
09-05-2014, 07:28 AM
The glPolygonOffset serves that purpose. You may also manually increase the depth (z coordinate) slightly in your vertex or fragment shaders.