c++ - 附加深度纹理 (C++) 时 OpenGL FBO 纹理困惑

标签 c++ opengl fbo

我正在尝试将我的场景渲染到我的 FBO,然后在屏幕的一角以较小的尺寸渲染它。它工作正常,但前提是 FBO 只有颜色纹理。当我尝试将深度纹理或深度缓冲区附加到它时,它会绘制我屏幕的单个像素。以下是一些屏幕:

带颜色纹理的FBO
FBO with Color Texture

具有颜色和深度纹理的 FBO
FBO with Color and Depth Texture

这是我的 FBO 类代码:

FrameBuffer::FrameBuffer()
{
    GLcall( glGenFramebuffers(1, &m_id) );

    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, m_id) );
    GLcall( glDrawBuffer(GL_COLOR_ATTACHMENT0) );

    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, 0) );
}

void FrameBuffer::attachTexture(const unsigned int width, const unsigned int height)
{
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, m_id) );

    m_textureAttachmentsIDs.push_back(0);
    GLcall( glGenTextures(1, &m_textureAttachmentsIDs[ m_textureAttachmentsIDs.size() - 1 ]) );

    GLcall( glBindTexture(GL_TEXTURE_2D, m_textureAttachmentsIDs[ m_textureAttachmentsIDs.size() - 1 ]) );
    GLcall( glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) );

    GLcall( glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textureAttachmentsIDs[ m_textureAttachmentsIDs.size() - 1 ], 0) );

    GLcall( glBindTexture(GL_TEXTURE_2D, 0) );
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, 0) );
}

void FrameBuffer::attachDepthTexture(const unsigned int width, const unsigned int height)
{
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, m_id) );

    GLcall( glGenTextures(1, &m_depthTextureAttachmentID) );

    GLcall( glBindTexture(GL_TEXTURE_2D, m_depthTextureAttachmentID) );
    GLcall( glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_ALPHA) );

    GLcall( glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTextureAttachmentID, 0) );

    GLcall( glBindTexture(GL_TEXTURE_2D, 0) );
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, 0) );
}

void FrameBuffer::attachDepthBuffer(const unsigned int width, const unsigned int height)
{
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, m_id) );

    GLcall( glGenRenderbuffers(1, &m_depthBufferAttachmentID) );

    GLcall( glBindRenderbuffer(GL_RENDERBUFFER, m_depthBufferAttachmentID) );
    GLcall( glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height) );
    GLcall( glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBufferAttachmentID) );

    GLcall( glBindRenderbuffer(GL_RENDERBUFFER, 0) );
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, 0) );
}


void FrameBuffer::bind(const unsigned int width, const unsigned int height) const
{
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, m_id) );
    GLcall( glViewport(0, 0, width, height) );
}

void FrameBuffer::unbind(const Window& window) const
{
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, 0) );
    GLcall( glViewport(0, 0, window.getWidth(), window.getHeight()) );
}

这是设置我的 FBO 和 Sprite 以渲染纹理的代码:

FrameBuffer testFBO;
testFBO.attachTexture(320, 180);
testFBO.attachDepthTexture(320, 180);

Layer2D layer(window);
Sprite2D screenSprite(vector2(400.0f, 600.0f), vector2(640.0f, 360.0f));
layer.addSprite(&screenSprite);

Texture screenTexture(testFBO.getTextureAttachments()[0], 320, 180);

下面是处理渲染的代码:

testFBO.bind(320, 180);
rr.render(cam);
testFBO.unbind(window);

screenSprite.setTexture(&screenTexture);

rr.render(cam);
layer.render();

我不会发布渲染代码,因为如果我不附加深度纹理或深度缓冲区,它会渲染一切。

是的,我正在清除深度缓冲区:

GLcall( glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) );

GLcall() 函数检查是否有任何 OpenGL 错误,而当我执行这段代码时没有任何错误。

提前致谢。

最佳答案

解决方法是清除 FBO 的深度缓冲区。

testFBO.bind(320, 180);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
rr.render(cam);
testFBO.unbind(window);

我只清除了默认 FBO 的深度缓冲区。

关于c++ - 附加深度纹理 (C++) 时 OpenGL FBO 纹理困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50404023/

相关文章:

c++ - 这两种初始化成员变量的方法有区别吗?

c++ - 移动立方体、体素,需要一些建议

opengl - OpenGL 中的多个窗口?

c++ - GLSL/OpenGL FBO 不会解除绑定(bind)

c++ - 使用 GL_RGBA16F_ARB 纹理时,它只包含废话,但我没有收到任何错误消息

c++ - 单例和多线程

c++ - 我可以将我的 C++ 代码绑定(bind)到 lua 并将其开发到某个 lua 游戏引擎吗?

c++ - 如何底部对齐字体

opengl - 纹理可以绑定(bind)到多个 fbo 吗?

c++ - 矩阵处理程序大序列