为什么 glReadPixels 这么慢并且有其他选择吗?

2023-12-29

我需要在每一帧上截取屏幕截图,并且需要非常高的性能(我正在使用 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

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

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


OpenGL方法用于管理渲染pipeline。从本质上讲,当显卡向观看者显示图像时,就会完成下一帧的计算。你打电话时glReadPixels;显卡等待当前帧完成,读取像素,然后开始计算下一帧。因此管道变得停滞并变得顺序。

如果您可以保存两个缓冲区并告诉显卡将数据读入这些缓冲区并交换每一帧;那么您可以从缓冲区读回 1 帧,但不会停止管道。这称为双缓冲。您还可以通过 2 帧延迟回读等进行三重缓冲。

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

网上还有很多关于帧缓冲区和渲染到纹理的教程。其中之一在这里:http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/ http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 glReadPixels 这么慢并且有其他选择吗? 的相关文章

随机推荐