OpenGL如何使用多重采样2d纹理将深度缓冲区附加到帧缓冲区

时间:2015-11-07 20:56:07

标签: c++ opengl fbo depth-buffer msaa

当我使用GL_TEXTURE_2D_MULTISAMPLE时,如何将深度缓冲区附加到我的framebufferobject。来自下面代码的glCheckFramebufferStatus(msaa_fbo)返回0.从文档中,这似乎意味着msaa_fba不是帧缓冲区,而是从glGenFramebuffers(1, &msaa_fbo);创建的。

  

此外,如果发生错误,则返回零。   如果目标不是GL_DRAW_FRAMEBUFFER,GL_READ_FRAMEBUFFER或GL_FRAMEBUFFER,则会生成GL_INVALID_ENUM。

错误是1280,我认为这意味着GL_INVALID_ENUM。

如果我删除深度缓冲附件,程序将运行并渲染(尽管没有深度测试)。当它运行时,错误仍然存​​在。如果包含深度附件,则每帧后都会出现错误(1286),即INVALID_FRAMEBUFFER。我不知道怎么从这里继续。我看过的一些例子做的有点相同,但似乎有效。

glGenTextures(1, &render_target_texture);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, render_target_texture);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, NUM_SAMPLES, GL_RGBA8, width, height, false);

glGenFramebuffers(1, &msaa_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, msaa_fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, render_target_texture, 0);

glGenRenderbuffers(1, &depth_render_buffer);
glBindRenderbuffer(GL_RENDERBUFFER, depth_render_buffer);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, NUM_SAMPLES, GL_DEPTH_COMPONENT24, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_render_buffer);

GLenum status = glCheckFramebufferStatus(msaa_fbo);

大部分代码来自this

修改

状态检查错误,应该是GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);。现在,当我不包括深度时没有错误。当我包含深度时,我现在收到此错误:GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE

编辑2

文档声称当GL_TEXTURE_SAMPLES和GL_RENDERBUFFER:SAMPLES不匹配时会发生这种情况。

  

如果GL_RENDERBUFFER_SAMPLES的值对于所有附加的渲染缓冲区不相同,则返回GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;如果GL_TEXTURE_SAMPLES的值对于所有附加纹理都不相同;或者,如果附加的图像是渲染缓冲区和纹理的混合,则GL_RENDERBUFFER_SAMPLES的值与GL_TEXTURE_SAMPLES的值不匹配。

但是他们这样做了!

我已经像这样测试了它们:

std::cout << "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << std::endl;
GLsizei gts, grs;
glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_SAMPLES, &gts);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &grs);
std::cout << "GL_TEXTURE_SAMPLES: " << gts << std::endl;
std::cout << "GL_RENDERBUFFER_SAMPLES: " << grs << std::endl;

输出是:

GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
GL_TEXTURE_SAMPLES: 8
GL_RENDERBUFFER_SAMPLES: 8

编辑3

通过使用两个纹理而不是像这样的纹理和渲染缓冲区来解决这个问题:

glGenFramebuffers(1, &msaa_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, msaa_fbo);

glGenTextures(1, &render_texture);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, render_texture);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, NUM_SAMPLES, GL_RGBA8, width, height, false);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, render_texture, 0);

glGenTextures(1, &depth_texture);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, depth_texture);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, NUM_SAMPLES, GL_DEPTH_COMPONENT, width, height, false);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, depth_texture, 0);

我仍然对原始实施的问题感兴趣,所以问题仍然存在。

1 个答案:

答案 0 :(得分:1)

如果将纹理与渲染缓冲区混合,则需要使用固定的样本位置作为纹理。根据规范,“帧缓冲完整性”部分:

  

TEXTURE_FIXED_SAMPLE_LOCATIONS的值对于所有附加纹理都是相同的;并且,如果附加的图像是渲染缓冲区和纹理的混合,则所有附加纹理的TEXTURE_FIXED_SAMPLE_LOCATIONS值必须为TRUE。

     

{FRAMEBUFFER_INCOMPLETE_MULTISAMPLE}

为避免此错误情况,您需要将设置纹理存储的调用更改为:

glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,
    NUM_SAMPLES, GL_RGBA8, width, height, GL_TRUE);