在eglSwapBuffers之后保留后台缓冲区内容

时间:2014-05-29 08:13:36

标签: android opengl-es egl double-buffering

我正在使用egl 1.1在Android和原生C ++中实现Android的场景绘图。 目前正在使用android的glSurfaceView - 它允许我绘制一个显示在“onDrawFrame”末尾的后台缓冲区 - 当后台缓冲区和前台缓冲区交换时。

我的问题是这个 - 我需要能够显示后台缓冲区并继续写入,就像我没有交换一样。这种需求背后的原因是场景非常大,并且每帧构建它是不可能的,也不等待绘图的结束 - 因为用户将不得不等待太长时间。

换句话说 - 我需要构建场景增量。 在渲染过程中的某个时刻,我决定它的时间,我调用eglSwapBuffers显示后缓冲区中绘制的内容,但是当我继续写入时,显然我正在写入'前前缓冲区',是不同步..(不包含我到目前为止绘制的东西)。

据我所知,我唯一的选择是在交换之前复制后台缓冲区。伪:

  1. 绘制到后台缓冲区
  2. 复制 Back Buffer to temp Buffer
  3. 交换
  4. 临时缓冲区复制到(新)后台缓冲区
  5. 向后台缓冲区绘制更多内容
  6. 依旧......
  7. 我的问题 - 有没有办法执行第2,4步骤?

    • glCopyPixels在这种情况下有用吗?示例
    • glBlitFramebuffer

    还是我接近这一切都错了?

    我已经做过的事情:

    • 我尝试将EGL_SWAP_BEHAVIOR设置为EGL_BUFFER_PRESERVED,但它似乎只适用于某些设备(如khronos notes中所述):
      

    某些曲面允许应用程序控制是否保留颜色缓冲区内容

    • 在每个帧中重新渲染场景 - 不可能。我多次读到这是推荐的。

1 个答案:

答案 0 :(得分:2)

您的一般方法是正确的。使用glBlitFramebuffer()可能会更有帮助,因为glCopyPixels只是将缓冲区的一些子矩形复制到同一缓冲区中的某个位置。

但是,我可以考虑一种可能更好的方法,至少在OES_framebuffer_object可用的情况下:

  1. 绘制到纹理或用户定义的渲染缓冲区
  2. 将纹理渲染到BACK缓冲区/ blit渲染缓冲区到BACK缓冲区
  3. 交换
  4. 更新纹理/渲染缓冲区
  5. 将纹理渲染到BACK缓冲区/ blit渲染缓冲区到BACK缓冲区
  6. 交换
  7. [......等等......]
  8. 这样你就没有复制/更新/复制/交换周期,每帧有2个副本,但只能用一个额外的副本进行更新/复制/交换。