【问题标题】:Shadow Map: whole mesh is in shadow, there is no light where it should be according to depth map阴影贴图:整个网格处于阴影中,根据深度图应该在哪里没有光
【发布时间】:2014-12-09 12:11:20
【问题描述】:

第一次尝试使用 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);

}

【问题讨论】:

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


    【解决方案1】:

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

    这意味着替换以下代码:

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

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

    【讨论】:

    • 更改为 GL_NONE。我在着色器中的“ShadowCoord”看起来还好吗?我认为当我尝试将其转换为深度纹理空间时,问题就出在此处。
    • 发现问题。启用纹理比较是问题之一,以及我如何对阴影贴图进行采样将 .z 更改为 .x。我相信我需要 .x 因为深度值只是一个分量而不是向量。 float Depth = texture(shadowMap, UVCoords).x;
    • 老实说,在核心 GL 3.3 中,即使深度纹理只有 1 个组件,它也应该有效地返回:(r,r,r,1)。这意味着texture(shadowMap, UVCoords).x 应该给出与texture(shadowMap, UVCoords).z 相同的值。 compatibility 配置文件中有一个深度纹理模式会影响此行为,但在核心中,它应该始终按照我描述的方式运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 1970-01-01
    相关资源
    最近更新 更多