【问题标题】:Preserving back buffer content after eglSwapBuffers在 eglSwapBuffers 之后保留后台缓冲区内容
【发布时间】:2014-05-29 08:13:36
【问题描述】:

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

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

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

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

  1. 绘制到后台缓冲区
  2. 复制后台缓冲区到临时缓冲区
  3. 交换
  4. 复制临时缓冲区到(新的)后台缓冲区
  5. 绘制更多的东西到后台缓冲区
  6. 等等……

我的问题 - 有没有办法执行步骤 2,4?

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

还是我的做法都错了?

我已经做过的事情:

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

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

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

【问题讨论】:

    标签: android opengl-es egl double-buffering


    【解决方案1】:

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

    但是,我可以想到一个可能更好的方法,至少在OES_framebuffer_object 可用的情况下:

    1. 绘制到纹理或用户定义的渲染缓冲区
    2. 将纹理渲染到 BACK 缓冲区/blit 渲染缓冲区到 BACK 缓冲区
    3. 交换
    4. 更新纹理/渲染缓冲区
    5. 将纹理渲染到 BACK 缓冲区/blit 渲染缓冲区到 BACK 缓冲区
    6. 交换
    7. [...等等...]

    这样您就没有每帧 2 个副本的复制/更新/复制/交换循环,而只有一个额外副本的更新/复制/交换。

    【讨论】:

    • 感谢您的回答。你愿意详细说明一下吗?步骤 1,2 我应该使用什么方法?我对使用 gl 非常陌生(将跨平台代码移植到 android.. - 试图找到 ios 的“presentRenderbuffer”的替代方案)
    • @DrorFichman:也许this GL wiki page 可以帮助你。它解释了 FBO 的基础知识(这也适用于 GLES,只是在这方面有一些限制)。因此,当您的程序启动时,您会创建一个 FBO,附加一个渲染缓冲区或纹理作为颜色缓冲区。也许您还需要一个深度缓冲区。对于第 1 步,您只需绑定 FBO,所有渲染都将对其进行。对于第 2 步,您可以使用 glBlitFramebuffer,或者,如果您附加了纹理而不是渲染缓冲区,则只需渲染应用该纹理的全屏四边形。
    猜你喜欢
    • 1970-01-01
    • 2011-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    相关资源
    最近更新 更多