0

我正在开发一个屏幕图像通常是静态的 OpenGL 应用程序。我可以想到 3 种方法来处理这种情况:

  1. 无论如何,只需一遍又一遍地渲染整个屏幕
  2. 要求OpenGL仅在有变化时调用渲染循环
  3. 仅在图像更改时重绘图像,否则立即退出渲染循环

显然,选项 1 会极大地浪费处理能力(即移动设备上的电池充电),而选项 2 将是最佳解决方案。

选项 2 和选项 3 之间的功耗差异可能非常小(如果我错了,请纠正我),因为对渲染循环的不必要调用和任何相关的设置开销应该很小。事实证明,对于我的多线程渲染管道,选项 3 比选项 2 更容易实现。所以,如果我能让它工作,我想先试一试。

当我尝试通过渲染静态图像一次时,屏幕开始在该图像和黑色之间疯狂地闪烁。我的猜测是这是由于双重(或三重?)缓冲:我的图像只被绘制到一个缓冲区中,但是在每次调用渲染循环时,缓冲区都会翻转,因此图像最终会出现在仅当该缓冲区恰好是活动缓冲区时才筛选。

简单的解决方案:在每个缓冲区中绘制一次静态图像,然后才立即开始退出渲染循环。

为此,我需要知道缓冲区的数量,即我需要绘制图像的次数。有没有办法查询这个号码?或者,如果我的渲染循环变成 NO-OP,我可以以某种方式阻止缓冲区切换吗?

我正在构建此代码的 OpenGL ES 1.0 和 OpenGL ES 2.0 版本,以获得最大的设备支持。

4

2 回答 2

1

有两种触发渲染的方式,具体取决于框架/平台。

  1. 显式开始一个新帧并自己翻转缓冲区。
  2. 设置渲染回调并在回调返回后翻转缓冲区。

选项 1 是您通常会在 PC 程序中看到的内容。选项 2 是您通常会在移动应用程序 (iOS/Android) 上看到的内容。

使用选项 1 控制何时开始渲染,如果没有任何更改,您显然不会发出渲染。当您的应用程序需要重绘(假设另一个应用程序被部分拖到您的应用程序上)时,操作系统也会有一个事件。如果你不听这个事件并重绘,你会得到闪烁的毛刺。

如果操作系统调用您的渲染函数,则使用选项 2,您必须绘制。如果不绘制任何内容,则将显示缓冲区内存中的任何随机数据。例如,在 android 上,您可以停止使用 GLSurfaceView.RENDERMODE_WHEN_DIRTY 连续触发重绘。然后,您可以在需要时 requestRender(),但操作系统仍会在需要时调用重绘(例如,当事物在顶部合成时)。

于 2015-08-02T10:21:52.560 回答
0

我不确定这是否可能——它实际上对 OpenGL ES 是不可见的,实际上可能在某些平台上发生了变化(我已经看到至少一个系统在 2 和 3 之间动态切换,具体取决于 vsync 是否被命中)。EGL 可能会给您一些提示,但即使存在假设是应用程序不需要知道。

设置表面属性 EGL_BUFFER_PRESERVE 将确保保留最后一帧的内容,但这实际上是由驱动程序插入的全屏副本,因此重绘所有内容通常不会更昂贵。

如果您确实选择了部分更新情况,请记住处理屏幕方向更改的情况。

于 2015-08-02T19:54:34.760 回答