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, ...);

スカイボックスが画面いっぱいになったときの黒い画面について説明します。もちろん、深度テストがなければ、スカイボックスは描画するだけです。深度テストでは、スカイボックスはまだ最初のフレームに描画されますが、2 番目のフレームの直後にカラー バッファーのみがクリアされます。深度バッファにはまだ古いスカイボックス値が含まれているため、このフレームでは再描画されず、黒が残ります...

ただし、ジオメトリ パスは深度テストを有効にせずに描画するため、スカイボックスが有効になっていない場合でも、これは表示されるはずです。また、これは と でのみ発生しGL_LESSますGL_LEQUALまた、falseがありglDepthMaskます。これは、コード内のデフォルトの深度バッファーに何も書き込まないことを意味します。これは、おそらく初期化されていない他の値を含む深度バッファーを指しますが、私の経験では、最初はゼロです。また、これはスカイボックスが画面いっぱいにならず、カメラから離れた立方体として描画された場合にも発生し、その議論を吹き飛ばします。さて、おそらくジオメトリが 2 番目のフレームで描画に失敗した場合、それがそれを説明するでしょう. さらに言えば、露骨なドライバーのバグもそうですが、指定されたコードに問題は見られません。

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 に答える