【问题标题】:OpenGL Shadow GlitchOpenGL 阴影故障
【发布时间】:2014-08-24 23:50:58
【问题描述】:

问题

一段时间以来,我一直在尝试在 OpenGL 中实现阴影。我终于让它进入半工作状态,阴影出现但在奇怪的地方覆盖了场景[即 - 它与光无关]

为了进一步解释上面的 gif:当我将光源从场景(向左)移动到更远的 远离 - 阴影延伸得更远。为什么?如果有的话,它应该显示更多的场景。

更新 - 我弄乱了灯的位置,现在得到了这个结果(令人困惑):

深度图

这里是:

代码

因为这是一个难以确定的问题 - 我将发布我在此应用程序中使用的大量代码。

帧缓冲区和深度纹理 - 我需要的第一件事是一个帧缓冲区来记录所有绘制对象的深度值,然后我需要将这些值转储到深度纹理中(阴影-地图):

// Create Framebuffer
FramebufferName = 0;
glGenFramebuffers(1, &FramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);

// Create and Load Depth Texture
glGenTextures(1, &depthTexture);
glBindTexture(GL_TEXTURE_2D, depthTexture);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_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_REF_TO_TEXTURE);
glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT24, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);

//Attach Texture To Framebuffer
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);

//Check for errors
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    Falcon::Debug::error("ShadowBuffer [Framebuffer] could not be initialized.");

渲染场景 - 首先我做阴影通道,它只通过一些基本的着色器并输出到帧缓冲区,然后我做第二个常规通道,实际绘制场景并执行 GLSL阴影贴图采样:

//Clear
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//Select Main Shader
normalShader->useShader();

//Bind + Update + Draw
    /* Render Shadows */
    shadowShader->useShader();
    glBindFramebuffer(GL_FRAMEBUFFER, Shadows::framebuffer());
        //Viewport
        glViewport(0,0,640,480);

        //GLM Matrix Definitions
        glm::mat4 shadow_matrix_view;
        glm::mat4 shadow_matrix_projection;

        //View And Projection Calculations
        shadow_matrix_view       =  glm::lookAt(glm::vec3(light.x,light.y,light.z), glm::vec3(0,0,0), glm::vec3(0,1,0));
        shadow_matrix_projection =  glm::perspective(45.0f, 1.0f, 0.1f, 1000.0f);

        //Calculate MVP(s)
        glm::mat4 shadow_depth_mvp = shadow_matrix_projection * shadow_matrix_view * glm::mat4(1.0);
        glm::mat4 shadow_depth_bias = glm::mat4(0.5,0,0,0,0,0.5,0,0,0,0,0.5,0,0.5,0.5,0.5,1) * shadow_depth_mvp;

        //Send Data To The GPU
        glUniformMatrix4fv(glGetUniformLocation(shadowShader->getShader(),"depth_matrix"), 1, GL_FALSE, &shadow_depth_mvp[0][0]);
        glUniformMatrix4fv(glGetUniformLocation(normalShader->getShader(),"depth_matrix_bias"), 1, GL_FALSE, &shadow_depth_bias[0][0]);

        renderScene();
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    /* Clear */
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    /* Shader */
    normalShader->useShader();

    /* Shadow-map */
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, Shadows::shadowmap());
    glUniform1f(glGetUniformLocation(normalShader->getShader(),"shadowMap"),0);

    /* Render Scene */
    glViewport(0,0,640,480);
    renderScene();

片段着色器 - 这是我计算要输出的最终颜色并进行深度纹理/阴影贴图采样的地方。这可能是我出错的根源:

//Shadows
uniform sampler2DShadow shadowMap;
in vec4 shadowCoord;

void main()
{
    //Lighting Calculations...
    //Shadow Sampling:
    float visibility = 1.0;
    if (texture(shadowMap, shadowCoord.xyz) < shadowCoord.z){
        visibility = 0.1;
    }

    //Final Output
    outColor = finalColor * visibility;
}

编辑

AMD 硬件问题 - 也有人认为这可能是 GPU 的问题,但我觉得这很难相信,因为它是 Radeon HD 6670。是否值得放入 Nvidia 卡来测试这个理论?

建议更改 - 我根据 cmets 和答案做了一些建议更改:

首先,我将灯光的透视投影更改为正交投影,这为我提供了阴影贴图中所需的精度,因此现在我可以清楚地看到深度(即 -> 它不是全白的)。此外,它消除了对透视分割的需要,因此我使用 3 维坐标进行测试。下面是截图:

其次,我将纹理采样更改为:visibility = texture(shadowMap,shadowCoord.xyz); 现在总是返回 0,因此我看不到场景,因为它被认为是完全阴影的。

第三也是最后,我按照建议从GL_LEQUAL 交换到GL_LESS,没有发生任何变化。

【问题讨论】:

  • 1.我没有看到小长方体投射到地平面上的阴影——也许相机视角没有让我看到它,但你没有提到它仍然很奇怪。
  • 2.我们看到的阴影是什么?
  • 3.如果您的目标是 1024 平方像素,为什么要在 RTT 部分设置如此小的视口 640x480?
  • 4.你的阴影贴图看起来还好吗?
  • Yeezus - 请避免这样的多个 cmet。

标签: c++ opengl c++11 glsl shadow


【解决方案1】:

您的着色器存在根本性问题:

uniform sampler2DShadow shadowMap; // NOTE: Shadow samplers perform comparison !!

...

if (texture(shadowMap, shadowCoord.xyz) < shadowCoord.z)

您已启用纹理比较与参考。这意味着 3rd 纹理坐标将由 texture (...) 函数进行比较,返回值将是测试函数的结果(在本例中为 GL_LEQUAL)。

换句话说,texture (...) 将通过将在 shadowCoord.xy 的查找深度与shadowCoord.z。您要进行两次此测试。

考虑改用这个修改后的代码:

float visibility = texture(shadowMap, shadowCoord.xyz);

这不会产生您想要的结果,因为您的比较函数是GL_LEQUAL,但这是一个开始。考虑将比较函数更改为GL_LESS 以获得精确的功能匹配。

【讨论】:

  • 在修改着色器以支持失败或通过采样后 - 我得到了与第二张图片的问题相同的结果。
  • 您能否更新您的问题以显示您尝试过的内容?这当然是一个问题,尽管我认为这不是您唯一的问题,但在评论中解释起来太复杂了。立即想到的另一件事是,由于某种原因,您使用的是 4 维纹理坐标,但我没有看到同质划分。
猜你喜欢
  • 1970-01-01
  • 2014-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多