eglSwapBuffers之后如何保留后备缓冲区内容

7
我正在Android和本地C++中实现一个场景绘制,使用EGL 1.1在Android上进行。目前使用Android的glSurfaceView - 它允许我绘制到后缓冲区,该缓冲区在“onDrawFrame”结束时显示,当交换后缓冲区和前缓冲区时。
我的问题是:我需要能够显示后缓冲区并继续编写,就好像我没有交换一样。这个需求背后的原因是场景非常大,每帧都要构建不可能,等待绘制结束也不行-因为用户将不得不等待太长时间。
换句话说-我需要逐步构建场景。
在渲染过程中的某个特定点上,我决定是时候调用eglSwapBuffers了,它会显示从后缓冲区绘制的内容,但当我继续编写时,我显然正在写入“前面的缓冲区”,它已经失去同步...(不包含我到目前为止绘制的东西)。
据我所见,我唯一的选择是在交换之前复制后缓冲区。伪代码如下:
  1. 绘制到后备缓冲区
  2. 复制后备缓冲区到临时缓冲区
  3. 交换
  4. 复制临时缓冲区到(新的)后备缓冲区
  5. 在后备缓冲区中绘制更多内容
  6. 等等...

有没有方法可以完成步骤2和4?

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

还是我的方法不对?

我已经做的事情:

  • 我尝试将 EGL_SWAP_BEHAVIOR 设置为 EGL_BUFFER_PRESERVED,但似乎只在某些设备上起作用(如khronos notes所述):

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

  • 每帧重新渲染场景-不可能。 我已经多次阅读到这是推荐的做法。

1个回答

3
您的一般方法是正确的。使用glBlitFramebuffer()可能更有帮助,因为glCopyPixels只是将缓冲区的某个子矩形复制到同一缓冲区中的其他位置。
但是,如果OES_framebuffer_object可用,我可以想到一个潜在更好的方法:
  1. 绘制到纹理或用户定义的渲染缓冲区
  2. 将纹理渲染到后备缓冲区/将渲染缓冲区复制到后备缓冲区
  3. 交换
  4. 更新纹理/渲染缓冲区
  5. 将纹理渲染到后备缓冲区/将渲染缓冲区复制到后备缓冲区
  6. 交换
  7. [...以此类推...]
这样,您就不必进行每帧两次复制/更新/复制/交换循环,而只需进行一次额外的复制/更新/交换。

谢谢您的回答。您能详细解释一下吗?在步骤1、2中应该使用哪种方法?我很新,正在使用gl(将跨平台代码移植到Android..-试图找到iOS“presentRenderbuffer”的替代方法) - Dror Fichman
@DrorFichman:也许这个GL维基页面可以帮助你。它解释了FBO的基础知识(在GLES中也适用,只是有些限制)。所以当你的程序启动时,你需要创建一个FBO,将渲染缓冲区或纹理附加为颜色缓冲区。也许你还需要深度缓冲区。对于第一步,你只需绑定FBO,所有渲染都将在其中完成。对于第二步,你可以使用glBlitFramebuffer,或者如果你附加了纹理而不是渲染缓冲区,你只需使用该纹理应用于全屏四边形进行渲染。 - derhass

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接