传统的OpenGL(Legacy OpenGL):我的阴影映射代码出了什么问题?

4
我正在尝试在旧版OpenGL中实现阴影映射(是的,我知道它已经被弃用了,但是无论如何),但是它并没有正常工作。几乎所有的东西都是黑色的(见图片,在左下角添加了一个来自光源的视图)。我检查了深度纹理和投影,对我来说一切都是正确的。

Wrong shadow mapping

我是一名有用的助手,可以为您进行文本翻译。以下是需要翻译的内容:

我在纹理单元0中有一个漫反射贴图,深度贴图在纹理单元1中。

我的初始化代码:


    void InitScene()
    {
        light1_projection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, 1.0f, 100.0f);
        light1_view = glm::lookAt(glm::vec3(30.0f, 35.0f, 30.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
    
        camera_projection = glm::perspective(glm::radians(45.0f), 1.333f, 1.0f, 300.0f);
        camera_view = glm::lookAt(glm::vec3(0.0f, 30.0f, 20.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
    
        bias = glm::mat4(
            0.5f, 0.0f, 0.0f, 0.0f,
            0.0f, 0.5f, 0.0f, 0.0f,
            0.0f, 0.0f, 5.0f, 0.0f,
            0.5f, 0.5f, 0.5f, 1.0f
        );
    
        glEnable(GL_CULL_FACE);
        glEnable(GL_DEPTH_TEST);
    
        glClearColor(0.2f, 0.2f, 1.0f, 1.0f);
    
        LoadTexture(); // Loads the diffuse texture in TMU 0
        InitShadowmapTexture();
    }
    
    void InitShadowmapTexture()
    {
        glActiveTexture(GL_TEXTURE1);
        
        glGenTextures(1, &shadowmap_texture);    
        glBindTexture(GL_TEXTURE_2D, shadowmap_texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
        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_MODE, GL_COMPARE_R_TO_TEXTURE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
        glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
            shadowmap_width, shadowmap_heigth, 0,
            GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
    
        glEnable(GL_TEXTURE_GEN_S);
        glEnable(GL_TEXTURE_GEN_T);
        glEnable(GL_TEXTURE_GEN_R);
        glEnable(GL_TEXTURE_GEN_Q);
    
        glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
        glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
        glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
        glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
    }

My render code:


    void Render()
    {
        RenderShadowMap();
        RenderNormalScene();
        RenderNormalSceneLightView();
    }
    
    void DrawScene(const glm::mat4 &view, const glm::mat4 &projection)
    {
        const auto plane = glm::translate(view, glm::vec3(0.0f, 0.0f, 0.0f));
        const auto cube1 = glm::translate(view, glm::vec3(0.0f, 3.0f, z)) *
            glm::rotate(glm::mat4(1.0f), glm::radians(rotx), glm::vec3(1.0f, 0.0f, 0.0f)) *
            glm::rotate(glm::mat4(1.0f), glm::radians(roty), glm::vec3(0.0f, 1.0f, 0.0f));
    
        glMatrixMode(GL_PROJECTION);
        glLoadMatrixf(glm::value_ptr(projection));
    
        glMatrixMode(GL_MODELVIEW);
        glLoadMatrixf(glm::value_ptr(view));
    
        glActiveTexture(GL_TEXTURE1);
        const auto planes = bias * light1_projection * light1_view;
        glTexGenfv(GL_S, GL_EYE_PLANE, glm::value_ptr(glm::row(planes, 0)));
        glTexGenfv(GL_T, GL_EYE_PLANE, glm::value_ptr(glm::row(planes, 1)));
        glTexGenfv(GL_R, GL_EYE_PLANE, glm::value_ptr(glm::row(planes, 2)));
        glTexGenfv(GL_Q, GL_EYE_PLANE, glm::value_ptr(glm::row(planes, 3)));
    
        glMatrixMode(GL_MODELVIEW);
        glLoadMatrixf(glm::value_ptr(plane));
        DrawPlane(20.0f, 20.0f);
    
        glMatrixMode(GL_MODELVIEW);
        glLoadMatrixf(glm::value_ptr(cube1));
        DrawCube(size, size, size);
    }
    
    void RenderNormalScene()
    {
        glActiveTexture(GL_TEXTURE1);
        glEnable(GL_TEXTURE_2D);
    
        glCullFace(GL_BACK);
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        glViewport(0, 0, screen_width, screen_heigth);
        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
        DrawScene(camera_view, camera_projection);
    }
    
    void RenderNormalSceneLightView()
    {
        glActiveTexture(GL_TEXTURE1);
        glEnable(GL_TEXTURE_2D);
    
        glEnable(GL_SCISSOR_TEST);
        glScissor(0, 0, screen_width / 6, screen_heigth / 6);
        glCullFace(GL_BACK);
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        glViewport(0, 0, screen_width / 6, screen_heigth / 6);
        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
        DrawScene(light1_view, light1_projection);
        glDisable(GL_SCISSOR_TEST);
    }
    
    void RenderShadowMap()
    {
        glActiveTexture(GL_TEXTURE1);
        glDisable(GL_TEXTURE_2D);
    
        glCullFace(GL_FRONT);
        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
        glViewport(0, 0, shadowmap_width, shadowmap_heigth);
        glClear(GL_DEPTH_BUFFER_BIT);
    
        DrawScene(light1_view, light1_projection);
    
        glActiveTexture(GL_TEXTURE1);
        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, shadowmap_width, shadowmap_heigth);
    }


你有没有想法来解决这个问题?

2
你的偏见是错误的。在第2行第2列中,你输入了“5.0f”而不是“0.5f”。 - new QOpenGLWidget
@newQOpenGLWidget 谢谢!这个小错误让我花了一整天的时间。现在它终于可以工作了。当我尝试使用普通纹理进行投影时,一切都是正确的,所以我没有考虑到偏移矩阵。 - Mario
1个回答

4
您将值设置为
bias = glm::mat4(
    0.5f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.5f, 0.0f, 0.0f,
    0.0f, 0.0f, 5.0f, 0.0f,
    0.5f, 0.5f, 0.5f, 1.0f
);

在第2行第2列,您将值设置为5.0f而不是0.5f。这会导致将z值放大5倍而不是0.5倍;因此出现了错误。
正确的偏置矩阵为:
bias = 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
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接