当前位置: 动力学知识库 > 问答 > 编程问答 >

c++ - Shadow Map: whole mesh is in shadow, there is no light where it should be according to depth map

问题描述:

First time trying to implement shadow map using openGL ang glsl shader language.

I think the first pass where I render to a texture is correct but when I compare the depth values it seems to shadow everything.

https://www.dropbox.com/s/myxenx9y41yz2fc/Screenshot%202014-12-09%2012.18.53.png?dl=0

My perspective projection matrix looks like this:

FOV = 90

Aspect = According to the programs window size. (I also tried to put different values here)

Near = 2;

Far= 10000;

Function to initialize the frame buffer

void OpenGLWin::initDepthMap()

{

//Framebuffer

m_glFunctions->glGenFramebuffers(1, &m_frameBuffer);

m_glFunctions->glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer);

//////////////////////////////////////////////////////////////////////////

//Texture to render scene to

m_glFunctions->glGenTextures(1, &m_renderToTexture);

//Bind created texture to make it current

m_glFunctions->glBindTexture(GL_TEXTURE_2D, m_renderToTexture);

//Creates an empty texture of specified size.

//m_glFunctions->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024, 768, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);

m_glFunctions->glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);

m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);

m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);

m_glFunctions->glDrawBuffer(GL_NONE);

m_glFunctions->glReadBuffer(GL_NONE);

// Always check that our framebuffer is ok

if (m_glFunctions->glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){

qDebug() << "FrameBuffer not OK";

return;

}

m_glFunctions->glBindFramebuffer(GL_FRAMEBUFFER, 0);

}

Draw function for each mesh. Model matrix is passed as argument from a Transform class draw function

void Mesh::draw(const Matrix4x4& projection, const Matrix4x4& view, const Matrix4x4& model)

{

//Shadow map pass 1

if (m_shadowMapFirstpass){

//Pass 1 Shaders

m_glFunctions->glUseProgram(m_depthRTTShaderProgram);

//Light view matrix

m_depthMVP = projection*view*model;

//Get the location of the uniform name mvp

GLuint depthMVPLocation = m_glFunctions->glGetUniformLocation(m_depthRTTShaderProgram, "depthMVP");

m_glFunctions->glUniformMatrix4fv(depthMVPLocation, 1, GL_TRUE, &m_depthMVP[0][0]);

m_shadowMapFirstpass = false;

}

//Shadow map pass 2

else if(m_shadowMapFirstpass == false){

//Pass 2 Shader

m_glFunctions->glUseProgram(m_shaderProgram);

//Gets the model matrix which is then multiplied with view and projection to form the mvp matrix

Matrix4x4 mvp = projection * view * model;

//Get the location of the uniform name mvp

GLuint mvpLocation = m_glFunctions->glGetUniformLocation(m_shaderProgram, "mvp");

//Send the mvp matrix to the vertex shader

m_glFunctions->glUniformMatrix4fv(mvpLocation, 1, GL_TRUE, &mvp[0][0]);

Matrix4x4 depthBiasMVP = m_depthMVP;// biasMatrix*m_depthMVP;

GLuint depthBiasMVPLocation = m_glFunctions->glGetUniformLocation(m_shaderProgram, "depthBiasMVP");

m_glFunctions->glUniformMatrix4fv(depthBiasMVPLocation, 1, GL_TRUE, &depthBiasMVP[0][0]);

m_shadowMapFirstpass = true;

}

//Bind this mesh VAO

m_glFunctions->glBindVertexArray(m_vao);

//Draw the triangles using the index buffer(EBO)

glDrawElements(GL_TRIANGLES, m_indices.size(), GL_UNSIGNED_INT, 0);

//Unbind the VAO

m_glFunctions->glBindVertexArray(0);

/////////////////////////////////////////////////////////////////////////////////////////////////////

//Calls the childrens' update

if (!m_children.empty())

{

for (int i = 0; i < m_children.size(); i++)

{

if (m_children[i] != NULL)

{

m_children[i]->draw(frustumCheck, projection, view, bvScaleFactor, model);

}

}

}

}

My render loop

void OpenGLWin::paintGL()

{

// m_glFunctions->glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer);

m_glFunctions->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_frameBuffer);

glViewport(0, 0, 1024, 1024);

// Clear the buffer with the current clearing color

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//Light View Matrix

Matrix4x4 lightView;

lightView.lookAt(Vector3(0, 0, 0), Vector3(0, 0, -1), Vector3(0, 1, 0));

//Draw scene to Texture

m_root->draw(m_projection, lightView);

///////////////////////////////////////////////////////////////////

//Draw to real scene

m_glFunctions->glBindFramebuffer(GL_FRAMEBUFFER, 0);

// m_glFunctions->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

// Clear the screen

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//Bind Pass 2 shader

m_glFunctions->glUseProgram(m_shadowMapShaderProgram->getShaderProgramID());

GLuint shadowMapLocation = m_glFunctions->glGetUniformLocation(m_shadowMapShaderProgram->getShaderProgramID(), "shadowMap");

//Shadow Texture

m_glFunctions->glActiveTexture(GL_TEXTURE0);

m_glFunctions->glBindTexture(GL_TEXTURE_2D, m_renderToTexture);

m_glFunctions->glUniform1i(shadowMapLocation, 0);

//Updates matrices and view matrix for player camera

m_root->update(m_view);

//Render scene to main frame buffer

m_root->draw(m_projection, m_view);

}

Pass 1 Vertex Shader

#version 330 core

//Passthrough vertex shader

uniform mat4 depthMVP;

//Vertex received from the program

layout(location = 0) in vec3 vertexPosition_modelspace;

void main(void)

{

//Output position of vertex in clip space

gl_Position = depthMVP * vec4(vertexPosition_modelspace, 1);

}

Pass 1 Fragment Shader

#version 330 core

//Render to texture

// Ouput data

layout(location = 0) out float depthValue;

void main(void)

{

depthValue = gl_FragCoord.z;

}

Pass 2 Vertex Shader

#version 330 core

layout(location = 0) in vec3 vertexPosition_modelspace;

out vec4 ShadowCoord;

// Values that stay constant for the whole mesh.

uniform mat4 mvp;

uniform mat4 depthBiasMVP;

void main(){

// Output position of the vertex, in clip space : MVP * position

gl_Position = mvp * vec4(vertexPosition_modelspace,1);

ShadowCoord = depthBiasMVP * vec4(vertexPosition_modelspace,1);

}

Pass 2 Fragment Shader

#version 330 core

in vec4 ShadowCoord;

// Ouput data

layout(location = 0) out vec3 color;

// Values that stay constant for the whole mesh.

uniform sampler2D shadowMap;

void main(){

float visibility=1.0;

vec3 ProjCoords = ShadowCoord.xyz / ShadowCoord.w;

vec2 UVCoords;

UVCoords.x = 0.5 * ProjCoords.x + 0.5;

UVCoords.y = 0.5 * ProjCoords.y + 0.5;

float z = 0.5 * ProjCoords.z + 0.5;

float Depth = texture(shadowMap, UVCoords).z;//or x

if (Depth < (z + 0.00001)){

visibility = 0.1;

}

color = visibility*vec3(1,0,0);

}

网友答案:

Disable texture comparison for one thing. That's only valid when used with sampler2DShadow and you clearly are not using that in your code because your texture coordinates are 2D.

This means replacing the following code:

m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);

With this instead:

m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);

Likewise, using GL_LINEAR filtering on a non-sampler2DShadow texture is a bad idea. That is going to average the 4 nearest depth values and give you a single depth back. But that's not the proper way to anti-alias shadows; you actually want to average the result of 4 depth tests instead of doing a single test on the average of 4 depths.

分享给朋友:
您可能感兴趣的文章:
随机阅读: