【问题标题】:OpenGL FBO not blitting depth bufferOpenGL FBO没有blitting深度缓冲区
【发布时间】:2014-03-10 18:55:13
【问题描述】:

我正在尝试创建一个用于绘制 3D 场景的 FBO 和另一个用于绘制 HUD 的 FBO。然后,我尝试通过将 3D 场景blitting 到默认FBO,然后将HUD blitting 到默认FBO 来组合这两个FBO。

创建的每个 FBO 都具有与窗口相同的尺寸,并且具有用于颜色附件和深度附件的 RBO。

我期望发生的是,在绘制 3D 彩色 RBO 的内容时,3D FBO 的 blit 将使用来自 3D 深度 RBO 的数据填充默认 FBO 的深度缓冲区。然后第二个 blit,HUD,会将 HUD 颜色 RBO 数据绘制到默认 FBO 中,其中 HUD 深度 RBO 为 GL_LEQUAL,即默认 FBO 的深度数据。

旁注

我知道我可能想要的是用没有 alpha 的颜色清除 HUD(目前我用 清除)然后禁用深度测试并对 HUD 进行 blit到默认的 FBO。这将确保 HUD 始终位于顶部。我打算这样做,但我需要先让深度检查版本工作。

当前发生的情况是 3D FBO 正在绘制到场景中,然后 HUD FBO 完全绘制在它上面。背景应该有透明清晰颜色的点也不清晰。他们绘制了 3D 场景,将其完全覆盖。

我是否遗漏了什么或不理解 FBO 的 blitting?是否有可能深度检查工作正常,但没有混合清晰的颜色 Alpha 通道?

可在此处找到单个帧的 OpenGL 调用日志:
http://fpaste.org/84040/

节目详情

  • OpenGL 上下文版本:4.0
  • GLX 窗口色彩空间:RGBA8
  • GLX 窗口深度尺寸:24
  • GLX 窗口模板尺寸:8

开发系统详情

  • 操作系统:Ubuntu 12.04 LTS
  • 显卡:ATI Radeon HD 5750
  • 驱动版本:13.25.5

位代码

public void blit(int dstX = 0, int dstY = 0,
                 int dstWidth = 0, int dstHeight = 0,
                 uint targetFrameBuffer = 0)
{
   int mask;

   // Start out with nothing set.
   mask = 0;

   // See if we should blit the color buffer.
   if (color_buffer != null)
   {
      mask |= GL_COLOR_BUFFER_BIT;
   }

   // See if we should blit the depth buffer.
   if (depth_buffer != null)
   {
      mask |= GL_DEPTH_BUFFER_BIT;
   }

   // See if we should blit the stencil buffer.
   if (stencil_buffer != null)
   {
      mask |= GL_STENCIL_BUFFER_BIT;
   }

   // Make sure some mask was set before anything is done.
   if (mask != 0)
   {
      // Enable depth writing if a depth buffer is available.
      if (depth_buffer != null)
      {
         // Enable depth writing.
         glDepthMask(GL_TRUE);
      }

      // Bind the reading and drawing buffers.
      glBindFramebuffer(GL_READ_FRAMEBUFFER, reference);
      glReadBuffer(GL_COLOR_ATTACHMENT0);
      glBindFramebuffer(GL_DRAW_FRAMEBUFFER, targetFrameBuffer);

      // If the target buffer is the default FBO,
      // then render to the back one.
      if (targetFrameBuffer == 0)
      {
         glDrawBuffer(GL_BACK);
      }

      glBlitFramebuffer(0, 0, width, height,
                        dstX, dstY, dstWidth, dstHeight,
                        mask, GL_NEAREST);

      // Unbind the buffers.
      glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
      glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

      // Disable depth writing if it was enabled earlier.
      if (depth_buffer != null)
      {
         // Disable depth writing.
         glDepthMask(GL_FALSE);
      }
   }
}

【问题讨论】:

  • 我想纠正您代码 cmets 中的一些问题:glDepthMask (GL_TRUE) 不启用深度测试,而是启用深度写入。您可以在禁用深度写入的同时启用深度测试。另一方面(这与你的问题无关),你不能在没有启用深度测试的情况下写入深度缓冲区(如果你想无条件地写入,你需要设置一个深度函数@987654324 @)。
  • 你是对的。我添加了 glEnable(GL_DEPTH_TEST) 和 glDisable(GL_DEPTH_TEST) 调用。现在这会导致绘图区域中不显示任何内容。我将对此进行进一步测试并发布后续消息。
  • 同样重要的是要指出glBlitFramebuffer (...) 不执行任何类型的像素测试。启用或禁用深度测试毫无意义,现在我更好地了解您实际期望发生的事情。 Blitting 只是将一个或多个缓冲区从源帧缓冲区复制到目标,它可以执行过滤但不进行深度/模板测试。

标签: opengl framebuffer


【解决方案1】:

glBlitFramebuffer 只是将一块像素从一个缓冲区复制到另一个缓冲区。它不使用深度缓冲区来接受或拒绝来自源缓冲区的像素。

您可以通过使用 HUD 纹理和深度缓冲区绘制四边形来做您想做的事情(假设您将深度纹理绑定到 HUD FBO)。您需要将深度纹理的值写入片段着色器中的 gl_FragDepth。

如果您改用 alpha(正如您所说的打算做的那样),情况也是如此,除了您将只使用 HUD FBO 的 alpha 值进行混合。这是更好的解决方案,因为它取消了 HUD 深度缓冲区。

【讨论】:

  • 感谢您的启发性回答。我现在明白是什么导致了我的问题。因为我有多重采样的渲染缓冲区,所以我将每个 FBO 传送到一个临时纹理 FBO,这将允许我渲染到一个四边形。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-13
  • 1970-01-01
相关资源
最近更新 更多