附加到framebuffer的OpenGL多重采样整数纹理无法正确解析

时间:2013-09-16 10:38:51

标签: opengl integer framebuffer render-to-texture multisampling

所以,我使用多重渲染目标帧缓冲,其中第一个颜色附件是颜色纹理(RGBA8),而第二个颜色附件(颜色附件1)是索引纹理(R32UI)。

gl::BindTexture(gl::TEXTURE_2D_MULTISAMPLE, m_Textures[eTEXTURE_COLORBUFFER]);
gl::TexParameteri(gl::TEXTURE_2D_MULTISAMPLE, gl::TEXTURE_BASE_LEVEL, 0);
gl::TexParameteri(gl::TEXTURE_2D_MULTISAMPLE, gl::TEXTURE_MAX_LEVEL, 0);
gl::TexImage2DMultisample(gl::TEXTURE_2D_MULTISAMPLE, m_Multisample,gl::RGBA8,width,height,gl::FALSE_);

gl::BindTexture(gl::TEXTURE_2D_MULTISAMPLE, m_Textures[eTEXTURE_CLASSBUFFER]);
gl::TexParameteri(gl::TEXTURE_2D_MULTISAMPLE, gl::TEXTURE_BASE_LEVEL, 0);
gl::TexParameteri(gl::TEXTURE_2D_MULTISAMPLE, gl::TEXTURE_MAX_LEVEL, 0);
gl::TexImage2DMultisample(gl::TEXTURE_2D_MULTISAMPLE, m_Multisample,gl::R32UI,width,height,gl::FALSE_);

两个纹理都是多重采样的,我想在渲染完成后在CPU上下载它们。虽然,当我将多重采样FBO单独放入单样本FBO时,返回的索引纹理数据由全零组成,而颜色纹理正确分辨。

// Resolve multisampling
if ( m_Multisample > 0 )
{
    gl::BindFramebuffer(gl::READ_FRAMEBUFFER, m_Framebuffers[eFBO_RENDERBUFFER]);
    gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER, m_Framebuffers[eFBO_RESOLVEBUFFER]);
    gl::BlitFramebuffer(0, 0, m_FrameDims, m_FrameDims, 0, 0, m_FrameDims, m_FrameDims, 
        gl::COLOR_BUFFER_BIT, gl::NEAREST);

    gl::enum_t blit_error = gl::NO_ERROR_;
    blit_error = gl::GetError();
    if ( blit_error != gl::NO_ERROR_ )
    {
        throw framebuffer_error(string::format<128>(
            "BlitFramebuffer failed with error: %d",blit_error));
    }

    gl::BindFramebuffer(gl::READ_FRAMEBUFFER, m_Framebuffers[eFBO_RESOLVEBUFFER]);
}

我使用NEARST标志,因为实际上整数纹理看起来不适用于LINEAR插值。

我在此处列出了用于下载图像的代码。

uint32_t* tex_data = new uint32_t[query.m_FrameDims*query.m_FrameDims];
memset(tex_data,0,sizeof(uint32_t)*query.m_FrameDims*query.m_FrameDims);
gl::BindTexture(gl::TEXTURE_2D,query.m_DestColorTexture);
{
    // Copy color texture
    gl::ReadBuffer(gl::COLOR_ATTACHMENT0);
    gl::ReadPixels(0,0,query.m_FrameDims,query.m_FrameDims,
        gl::RGBA,gl::UNSIGNED_BYTE,tex_data);
    gl::TexSubImage2D(gl::TEXTURE_2D,0,0,0,query.m_FrameDims,query.m_FrameDims,
        gl::RGBA,gl::UNSIGNED_BYTE,tex_data);
}

gl::BindTexture(gl::TEXTURE_2D,query.m_DestClassTexture);
{
    // Copy class texture
    gl::ReadBuffer(gl::COLOR_ATTACHMENT1);                      
    gl::ReadPixels(0,0,query.m_FrameDims,query.m_FrameDims,
            gl::RED_INTEGER,gl::UNSIGNED_INT,tex_data);
    gl::TexSubImage2D(gl::TEXTURE_2D,0,0,0,query.m_FrameDims,query.m_FrameDims,
            gl::RED_INTEGER,gl::UNSIGNED_INT,tex_data);
}

delete[] tex_data;

如果我禁用多重采样FBO,因此避免调用gl :: BlitFramebuffer()函数,一切正常。

我没有看到任何文档说整数纹理可以被多重采样,但即使如此,我也不确定它们是否有意义。

我可能会误以为哪些线索?

1 个答案:

答案 0 :(得分:1)

当您执行帧缓冲区blit时,您只能从单个颜色缓冲区 读取 ;你可以 到很多绘制缓冲区(技术上一次最多GL_MAX_DRAW_BUFFERS)。这里的问题是你想要从两个不同的颜色缓冲区读取,并且你试图在一个blit中进行。

OpenGL 4.4 Core Specification - 18.3。复制像素 - (第483页)

  

当传输颜色缓冲区时,将从读取帧缓冲区的读取缓冲区中获取值,并将其写入 绘制缓冲区中的每一个绘制帧缓冲区。


你的代码向我表明你忘了为第二个颜色附件实际做了第二个blit,这就是为什么它变空了。

为了纠正这个问题,我希望看到类似的内容:

// Resolve multisampling
if ( m_Multisample > 0 )
{
  //
  // Do the first resolve (COLOR_ATTACHMENT0)
  //
  gl::BindFramebuffer(gl::READ_FRAMEBUFFER,m_Framebuffers[eFBO_RENDERBUFFER]);
  gl::ReadBuffer     (gl::COLOR_ATTACHMENT0); // Read:  Attachment 0 (MSAA)

  gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER,m_Framebuffers[eFBO_RESOLVEBUFFER]);
  gl::DrawBuffer     (gl::COLOR_ATTACHMENT0); // Write: Attachment 0 (Resolve)

  gl::BlitFramebuffer(0, 0, m_FrameDims, m_FrameDims, 0, 0, m_FrameDims,
      m_FrameDims, gl::COLOR_BUFFER_BIT, gl::NEAREST);

  gl::enum_t blit_error = gl::NO_ERROR_;
  blit_error = gl::GetError();
  if ( blit_error != gl::NO_ERROR_ )
  {
      throw framebuffer_error(string::format<128>(
          "BlitFramebuffer failed with error: %d",blit_error));
  }

  //
  // Do the second resolve (COLOR_ATTACHMENT1)
  //
  gl::BindFramebuffer(gl::READ_FRAMEBUFFER,m_Framebuffers[eFBO_RENDERBUFFER]);
  gl::ReadBuffer     (gl::COLOR_ATTACHMENT1); // Read:  Attachment 1 (MSAA)

  gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER,m_Framebuffers[eFBO_RESOLVEBUFFER]);
  gl::DrawBuffer     (gl::COLOR_ATTACHMENT1); // Write: Attachment 1 (Resolve)

  gl::BlitFramebuffer(0, 0, m_FrameDims, m_FrameDims, 0, 0, m_FrameDims,
      m_FrameDims, gl::COLOR_BUFFER_BIT, gl::NEAREST);

  gl::enum_t blit_error = gl::NO_ERROR_;
  blit_error = gl::GetError();
  if ( blit_error != gl::NO_ERROR_ )
  {
      throw framebuffer_error(string::format<128>(
          "BlitFramebuffer failed with error: %d",blit_error));
  }

  gl::BindFramebuffer(gl::READ_FRAMEBUFFER,m_Framebuffers[eFBO_RESOLVEBUFFER]);
}

这假设您想要从/到blit的纹理/渲染缓冲区具有相同的附着点。如果没有,您可以相应地调整gl::ReadBuffer (...)gl::DrawBuffer (...)