glReadPixels指定分辨率

时间:2014-10-26 17:41:58

标签: ios opengl-es

我正在尝试使用glReadPixels以原始分辨率的一半从OpenGL视图捕获iOS上的屏幕截图。 glReadPixels在视网膜屏幕上相当慢,所以我想以某种方式强制读取每隔一个像素和每隔一行,导致非视网膜截图(分辨率的1/4)。

我尝试设置这些:

glPixelStorei(GL_PACK_SKIP_PIXELS, 2);
glPixelStorei(GL_PACK_SKIP_ROWS, 2);

在致电glReadPixels之前,但似乎并没有改变任何事情。相反,它只渲染原始图像的1/4,因为传递给glReadPixels的宽度和高度是视图的非视网膜尺寸。

或者,如果您知道捕获OpenGL屏幕截图的更高效方式,也可以随意共享。

1 个答案:

答案 0 :(得分:0)

我不认为这是一种非常直接的方式来做你正在寻找的事情。正如您已经发现的那样,GL_PACK_SKIP_ROWSGL_PACK_SKIP_PIXELS没有您想要的功能。它们仅控制在开始时跳过多少行/像素,而不是在每行/像素之后。我相信他们无论如何都会控制在目的地内存中跳过,而不是在你正在阅读的帧缓冲中。

部分解决方案的一个简单方法是每行单独进行glReadPixels()调用,然后可以为每隔一行进行一次调用。您仍然需要从这些行中复制每隔一个像素,但至少会将您读取的数据量减少一半。它确实将额外的内存量减少到近四分之一,因为您只能以全分辨率存储一行。当然,你需要花费更多的glReadPixels()次呼叫,所以很难预测这种呼叫是否会更快。

更好的方法是生成一个可以直接读取的半分辨率帧。要做到这一点,你可以:

  • 如果您的工具包允许,请以分辨率的一半重新渲染帧。您可以使用FBO作为渲染目标,窗口大小只有窗口的一半。
  • 复制框架,同时在此过程中缩小框架。再次,使用渲染目标创建一个大小为一半的FBO,并使用glBlitFramebuffer()从默认帧缓冲区复制到此FBO。

您还可以考虑使用像素包缓冲区使回读异步(请参阅GL_PACK_BUFFER的{​​{1}}参数)。这很可能不会使操作更快,但它允许您在等待glBindBuffer()结果到达时继续向GPU提供命令。它可以帮助您截取屏幕截图,同时减少对游戏的破坏。