为什么glReadPixels这么慢,还有其他选择吗?

时间:2016-10-02 21:23:46

标签: c++ performance opengl screenshot freeglut

我需要在每一帧都采用sceenshots,我需要非常高的性能(我使用freeGlut)。我想到的是它可以在glutIdleFunc(thisCallbackFunction)

内完成
GLubyte *data = (GLubyte *)malloc(3 * m_screenWidth * m_screenHeight);
glReadPixels(0, 0, m_screenWidth, m_screenHeight, GL_RGB, GL_UNSIGNED_BYTE, data);
// and I can access pixel values like this: data[3*(x*512 + y) + color] or whatever

它确实有效,但我有一个很大的问题,它真的很慢。当我的窗口是512x512时,当仅渲染立方体时,它的运行速度不会超过每秒90帧,没有这两条线以6500 FPS运行!如果我们将它与irrlicht图形引擎进行比较,我可以做到这一点

// irrlicht code
video::IImage *screenShot = driver->createScreenShot();
const uint8_t *data = (uint8_t*)screenShot->lock();
// I can access pixel values from data in a similar manner here

和512x512窗口以400 FPS运行,即使加载了巨大的网格(Quake 3 Map)!考虑到我在irrlicht中使用openGL作为驱动程序。对于我没有经验的眼睛,似乎glReadPixels正在将每个像素数据从一个地方复制到另一个地方,而(uint8_t*)screenShot->lock()只是将指针复制到已经存在的数组。我可以使用freeGlut做类似于后者的事吗?我希望它比irrlicht更快。

请注意,irrlicht也使用openGL(它也提供了directX和其他选项,但在我上面给出的示例中,我使用的是openGL,而且与其他选项相比,它是最快的)

1 个答案:

答案 0 :(得分:2)

OpenGL方法用于管理渲染管道。就其本质而言,当图形卡向观看者显示图像时,正在进行下一帧的计算。致电glReadPixels时;显卡等待当前帧完成,读取像素然后开始计算下一帧。因此,管道变得停滞并变得顺序。

如果你可以握住两个缓冲区并告诉显卡将数据读入这些缓冲区,每个帧交换;然后你可以从你的缓冲区读回1帧,但不会拖延管道。这称为双缓冲。您还可以使用2帧后期回读等进行三重缓冲。

这里有一个相对较旧的网页描述现象和实施:http://www.songho.ca/opengl/gl_pbo.html

此外,还有很多关于帧缓冲器和渲染到Web上的纹理的教程。其中一个是:http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/