延迟渲染Skybox OpenGL

时间:2015-03-28 19:46:09

标签: c++ opengl glsl deferred-rendering skybox

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

    //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;
}

skybox的片段着色器只是将输出颜色设置为texture(cubeMap, TexCoord)。 正如您从顶点着色器中看到的那样,我将位置z组件设置为w,以便它的深度始终为1.我也设置了深度函数为GL_LEQUAL,因此深度测试失败。这不仅应该在其他物体尚未绘制的地方绘制天空盒吗?为什么会出现黑屏?

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

1 个答案:

答案 0 :(得分:1)

  

我可以简要地看一下在天空盒被绘制到所有东西之前应该绘制的几何体。

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

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

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

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

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

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

以下是基于您的代码的简单示例,它对我来说很好......

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

gl_Position = pos
enter image description here

注意添加剂混合中的黄色,即使天空盒被绘制在顶部。我原本以为你也会看到这个。

gl_Position = pos.xyww
enter image description here

现在代码......

//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();
相关问题