shadowmapping和sampler2DShadow

时间:2018-01-31 21:17:16

标签: c++ opengl glfw glew shadow-mapping

我一直在尝试在我的地形LOD程序中实现阴影贴图。我花了很多时间研究不同的技术并玩弄我的代码,但是我找不到我的错误,所以是时候问一下堆栈溢出的opengl大师吧了。)

我使用的是c ++,opengl,GLFW3,GLM,GLEW,GLSL(430)

我用不同的方式搞砸了,但结果总是以下之一:

  1. 使用visibility = 0.0;
  2. 呈现整个场景
  3. 使用visibility = 1.0;
  4. 呈现整个场景

    //////项目摘要

    no shadows, diffuse lighting

    使用跨越< 0,0,0>的四边形构建地形。至< 2048,400,2048>,然后由tess控制和评估着色器根据charPos进行测试。

    我使用不同的* .cpp文件来存储场景不同部分的渲染函数,因此vp_matrix变量在“main.cpp”中计算并传递给每个渲染函数,例如: renderTerrain(vp_matrix)。然后,我根据具体情况使用mvp = vp_matrix * m。对于terrain,我使用m来翻译vp_matrix by< -charPos.x,0,-charPos.z>在将地图渲染为颜色之前将地图置于播放器中心。当我渲染到depthBuffer的阴影时,我不使用这个翻译。我使用地图的边界(< 0,0,0>到< 2048,400,2048>)从太阳的角度渲染整个场景作为正投影。

    我使用静态变量,因为我在某些文件中重用某些名称。例如ProgramID,我不希望它们重叠,因此任何未在“简化”代码中定义的变量都是该文件的静态全局。

    我应该补充一点,所有着色器都编译没有错误。

    //////代码

    我尽力将代码缩减为仅影响阴影贴图的部分。 相关的2个文件是“main.cpp”和“terrain.cpp”。

    “main.cpp”具有FBO初始化和主渲染循环。 “terrain.cpp”包含大部分肉类。

    我没有包含样板代码,例如生成VAO。

    *********** main.cpp ***********

    * init *

    ShadowFrameBufferID = 0;
    glGenFramebuffers(1, &ShadowFrameBufferID);
    glBindFramebuffer(GL_FRAMEBUFFER, ShadowFrameBufferID);
    
    glGenTextures(1, &depthTexture);
    glBindTexture(GL_TEXTURE_2D, depthTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
    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_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
    
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
    glDrawBuffer(GL_NONE);
    glReadBuffer(GL_NONE);
    
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    {
        printf("shadow framebuffer error\n");
    }
    

    *渲染循环*

    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ShadowFrameBufferID);
    
    glViewport(0, 0, 1024, 1024);
    glClear(GL_DEPTH_BUFFER_BIT);
    
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    
    glm::mat4 depthProjectionMatrix = glm::ortho<float>(0.0f, 2048.0f, 0.0f, 400.0f, 0.0f, 2048.0f);
    glm::mat4 depthViewMatrix = glm::lookAt(sunPos, glm::vec3(0), glm::vec3(0.0f, 1.0f, 0.0f));
    glm::mat4 depth_vp_matrix = depthProjectionMatrix * depthViewMatrix;
    
    renderTerrainShadows(depth_vp_matrix);
    
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    
    glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
    
    glClearColor(0.478f, 0.702f, 0.816f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    
    renderTerrain(vp_matrix, depth_vp_matrix, depthTexture);
    
    glfwSwapBuffers(window);
    glfwPollEvents();
    

    *********** terrain.cpp ***********

    *着色器来源*

    // shadow/main vertex shaders (passthrough)
    #version 430
    layout(location = 0) in vec2 position;
    out vec2 vposition;
    void main()
    {
        vposition = position;\n"
    }
    
    // shadow tess evaluation shader
    #version 430
    uniform mat4 shadowMVP;
    void main()
    {
        computeXYZ(); // world coordinates
    
        gl_Position = shadowMVP * vec4(x, y, z, 1.0f);
    }
    
    // shadow fragment shader
    #version 430
    layout(location=0) out float fragmentDepth;
    void main()
    {
        fragmentDepth = gl_FragCoord.z;
    }
    
    // main tess evaluation shader
    #version 430
    uniform mat4 mvp, shadowBiasMVP;
    out vec4 shadowPosition;
    void main()
    {
        computeXYZ(); // world coordinates
    
        gl_Position =    mvp * vec4(x, y, z, 1.0f);
        shadowPosition = shadowBiasMVP * vec4(x, y, z, 1.0f);
    }
    
    // main fragment shader
    #version 430
    out vec3 color;
    uniform sampler2DShadow shadowMap;
    in vec4 shadowPosition;
    void main()
    {
        color = doStuff(); // compute from diffuse / fog effect / etc
    
        float visibility = texture(shadowMap, vec3(shadowPosition.xy/shadowPosition.w, shadowPosition.z/shadowPosition.w));
        color = color * visibility;
    }
    

    * init *

    // shadow program
    ShadowProgramID = loadshaders4(shadow_vertex_shader_source, shadow_tessellation_control_shader_source, shadow_tessellation_evaluation_shader_source, shadow_fragment_shader_source);
    ShadowMatrixID = glGetUniformLocation(ShadowProgramID, "shadowMVP");
    
    // main program
    ProgramID = loadshaders4(vertex_shader_source, tessellation_control_shader_source, tessellation_evaluation_shader_source, fragment_shader_source);
    ShadowMapID = glGetUniformLocation(ProgramID, "shadowMap");
    MatrixID = glGetUniformLocation(ProgramID, "mvp");
    ShadowBiasMatrixID = glGetUniformLocation(ProgramID, "shadowBiasMVP");
    

    * renderTerrainShadows *

    void renderTerrainShadows(glm::mat4 depth_vp_matrix)
    {
        glUseProgram(ShadowProgramID);
    
        // uniforms
        glUniformMatrix4fv(ShadowMatrixID, 1, GL_FALSE, &depth_vp_matrix[0][0]);
    
        // buffers
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
    
        glPatchParameteri(GL_PATCH_VERTICES, 4);
    
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
        glDrawElements(GL_PATCHES, indices.size(), GL_UNSIGNED_INT, (void*)0);
    
        glDisableVertexAttribArray(0);
    }
    

    * renderTerrain *

    void renderTerrain(glm::mat4 vp_matrix, glm::mat4 depth_vp_matrix, GLuint depthTexture)
    {
        glUseProgram(ProgramID);
    
        // uniforms
        // mvp matrix for rendering the scene needs to be translated to be centered on player
        glm::mat4 mvp = glm::translate(vp_matrix, glm::vec3(-charPos.x, 0.0f, -charPos.z));
        glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);
    
        // depth_mvp needs to be biased to change from [-1,1] to [0,1]
        glm::mat4 biasMatrix = glm::mat4(0.5f, 0.0f, 0.0f, 0.0f,
                                         0.0f, 0.5f, 0.0f, 0.0f,
                                         0.0f, 0.0f, 0.5f, 0.0f,
                                         0.5f, 0.5f, 0.5f, 1.0f);
        glm::mat4 depth_mvp = biasMatrix * depth_vp_matrix;
        glUniformMatrix4fv(ShadowBiasMatrixID, 1, GL_FALSE, &depth_mvp[0][0]);
    
        // shadow texture (0)
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, depthTexture);
        glUniform1i(ShadowMapID, 0);
    
        // buffers
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
    
        glPatchParameteri(GL_PATCH_VERTICES, 4);
    
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
        glDrawElements(GL_PATCHES, indices.size(), GL_UNSIGNED_INT, (void*)0);
    
        glDisableVertexAttribArray(0);
    }
    

1 个答案:

答案 0 :(得分:0)

太阳位置离glm::ortho

给出的远平面太远了