阴影贴图:整个网格在阴影中,根据深度贴图,应该没有光线

时间:2014-12-09 12:11:20

标签: c++ opengl glsl shadow shadow-mapping

第一次尝试使用openGL ang glsl着色器语言实现阴影贴图。 我认为我渲染到纹理的第一遍是正确的,但是当我比较深度值时,它似乎会影响所有内容。

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

我的透视投影矩阵如下所示:

FOV = 90
Aspect = According to the programs window size. (I also tried to put different values here)
Near = 2;
Far= 10000;

初始化帧缓冲区的功能

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);   
}

为每个网格绘制函数。模型矩阵作为参数从Transform类绘制函数

传递
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);
            }
        }
    }
}

我的渲染循环

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);

}

传递1个顶点着色器

#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);
}

传递1片段着色器

#version 330 core
//Render to texture

// Ouput data
layout(location = 0) out float depthValue;

void main(void)
{
    depthValue = gl_FragCoord.z;
}

传递2顶点着色器

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

}

传递2片段着色器

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

}

1 个答案:

答案 0 :(得分:0)

禁用一件事的纹理比较。这仅在与sampler2DShadow一起使用时才有效,并且您显然没有在代码中使用它,因为纹理坐标是2D。

这意味着替换以下代码:

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->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);

同样,对非GL_LINEAR纹理使用sampler2DShadow过滤是一个坏主意。这将平均4个最近的深度值,并给你一个深度返回。但这不是反别名阴影的正确方法;你实际上想要平均4次深度测试的结果而不是平均4次深度的单次测试。