2

我刚刚实现了延迟渲染,但无法让我的天空盒正常工作。我尝试在渲染循环的最后渲染我的天空盒,我得到的只是黑屏。这是渲染循环:

    //binds the fbo
    gBuffer.Bind();

    //the shader that writes info to gbuffer
    geometryPass.Bind();

    glDepthMask(GL_TRUE);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_BLEND);

    //draw geometry
    geometryPass.SetUniform("model", transform.GetModel());
    geometryPass.SetUniform("mvp", camera.GetViewProjection() * transform.GetModel());

    mesh3.Draw();

    geometryPass.SetUniform("model", transform2.GetModel());
    geometryPass.SetUniform("mvp", camera.GetViewProjection() * transform2.GetModel());
    sphere.Draw();

    glDepthMask(GL_FALSE);
    glDisable(GL_DEPTH_TEST);

    glEnable(GL_BLEND);
    glBlendEquation(GL_FUNC_ADD);
    glBlendFunc(GL_ONE, GL_ONE);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glClear(GL_COLOR_BUFFER_BIT);

    //shader that calculates lighting
    pointLightPass.Bind();
    pointLightPass.SetUniform("cameraPos", camera.GetTransform().GetPosition());

    for (int i = 0; i < 2; i++)
    {
        pointLightPass.SetUniformPointLight("light", pointLights[i]);
        pointLightPass.SetUniform("mvp", glm::mat4(1.0f));
        //skybox.GetCubeMap()->Bind(9);
        quad.Draw();
    }

    //draw skybox
    glEnable(GL_DEPTH_TEST);
    skybox.Render(camera);

    window.Update();
    window.SwapBuffers();

下面是天空盒的渲染函数

glCullFace(GL_FRONT);
glDepthFunc(GL_LEQUAL);

m_transform.SetPosition(camera.GetTransform().GetPosition());
m_shader->Bind();

m_shader->SetUniform("mvp", camera.GetViewProjection() * m_transform.GetModel());
m_shader->SetUniform("cubeMap", 0);

m_cubeMap->Bind(0);
m_cubeMesh->Draw();

glDepthFunc(GL_LESS);
glCullFace(GL_BACK);

这是天空盒的顶点着色器:

layout (location = 0) in vec3 position;

out vec3 TexCoord;

uniform mat4 mvp;

void main()
{
    vec4 pos = mvp * vec4(position, 1.0);
    gl_Position = pos.xyww;
    TexCoord = position;
}

天空盒的片段着色器只是将输出颜色设置为texture(cubeMap, TexCoord). 正如您从顶点着色器中看到的那样,我将位置的z组件设置为w使其深度始终为 1。我还将深度函数设置为GL_LEQUAL使其无法通过深度测试。这不仅应该在尚未绘制其他对象的地方绘制天空盒吗?为什么会导致黑屏?

我知道我已经正确设置了天空盒,因为如果我自己绘制天空盒,它会显示得很好。

4

1 回答 1

2

我可以在瞬间看到在天空盒被绘制在一切之上之前应该绘制的几何图形。

由于您使用的是双缓冲,因此看到不同的东西一定是由于绘制了不同的帧。默认帧缓冲区中的深度缓冲区没有被清除,我认为这至少是时间不稳定的原因。

在您的情况下,您希望在绘制天空盒时默认深度缓冲区与 GBuffer 相同。实现此目的的一种快速方法是使用glBlitFramebuffer,同时也无需清除它:

glBindFramebuffer(GL_READ_FRAMEBUFFER, gbuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(..., GL_DEPTH_BUFFER_BIT, ...);

现在来解释天空盒填满屏幕时的黑屏。如果没有深度测试,天空盒当然只是绘制。在深度测试中,天空盒仍然在第一帧上绘制,但在第二帧之后不久,只清除了颜色缓冲区。深度缓冲区仍然包含陈旧的天空盒值,因此它不会为这一帧重新绘制,你会留下黑色......

但是,您的几何通道在未启用深度测试的情况下绘制,因此即使天空盒未启用,它也应该仍然可见。这也只会发生在GL_LESS你有GL_LEQUAL. glDepthMask错误,这意味着什么都不应该写入代码中的默认深度缓冲区。这指向包含其他值的深度缓冲区,可能未初始化,但根据我的经验,它最初为零。此外,当天空盒没有填满屏幕时,这种情况仍然会发生,它被绘制为远离相机的立方体,从而消除了这个论点。现在,也许如果几何图形未能在第二帧中绘制,就可以解释它。就此而言,公然的驱动程序错误也会出现,但我在给定的代码中没有看到任何问题。

TLDR:许多无法解释的事情,所以**我自己尝试过,无法重现您的问题......

这是一个基于您的代码的快速示例,它对我来说很好......

(绿色球体是几何体,红色立方体是天空盒)

gl_Position = pos
在此处输入图像描述

即使天空盒被绘制在顶部,也要注意加法混合的黄色。我还以为你也会看到这个。

gl_Position = pos.xyww
在此处输入图像描述

现在的代码...

//I haven't enabled back face culling, but that shouldn't affect anything

//binds the fbo
fbo.bind();

//the shader that writes info to gbuffer
//geometryPass.Bind(); //fixed pipeline for now

glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);

glColor3f(0,1,0);
fly.uploadCamera(); //glLoadMatrixf
sphere.draw();

glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);

glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);

fbo.unbind(); //glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT);

//shader that calculates lighting
drawtex.use();
//pointLightPass.SetUniform("cameraPos", camera.GetTransform().GetPosition());
drawtex.set("tex", *(Texture2D*)fbo.colour[0]);

for (int i = 0; i < 2; i++)
{
    //pointLightPass.SetUniformPointLight("light", pointLights[i]);
    //pointLightPass.SetUniform("mvp", glm::mat4(1.0f));
    //skybox.GetCubeMap()->Bind(9);
    drawtex.set("modelviewMat", mat44::identity());
    quad.draw();
}

drawtex.unuse();

//draw skybox
glEnable(GL_DEPTH_TEST);

glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, fbo.size.x, fbo.size.y, 0, 0, fbo.size.x, fbo.size.y, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

//glCullFace(GL_FRONT);
glDepthFunc(GL_LEQUAL);

//m_transform.SetPosition(camera.GetTransform().GetPosition());
skybox.use();

skybox.set("mvp", fly.camera.getProjection() * fly.camera.getInverse() * mat44::translate(1,0,0));
//m_shader->SetUniform("mvp", camera.GetViewProjection() * m_transform.GetModel());
//m_shader->SetUniform("cubeMap", 0);

//m_cubeMap->Bind(0);
cube.draw();
skybox.unuse();

glDepthFunc(GL_LESS);
//glCullFace(GL_BACK);

//window.Update();
//window.SwapBuffers();
于 2015-04-01T05:09:22.983 回答