以非常大的图像分辨率捕捉OpenGL窗口的快照

我目前正在尝试使用glReadPixels在各种相机位置拍摄OpenGL渲染的3D世界的快照以及不同的图像分辨率。 我有两个select实现OpenGL Windows程序的GUI库:Qt和Freeglut。 经过两次实验之后,我意识到Qt不会将QGLWidget的快照图像分辨率限制为桌面大小,但对于FreeGlut则无法做到这一点。

我希望我可以使用Qt来抓取这个抓图程序,但是由于我的项目团队伙伴正在使用同一个程序的另一个模块,所以我不能花时间学习一个新库和IDE(Qt Creator)。 他正在使用Visual Studio 2008。

是否有我创build一个不受桌面大小限制的大小窗口,可以大到4000 x 2000?

经过两次实验之后,我意识到Qt不会将QGLWidget的快照图像分辨率限制为桌面大小,但对于FreeGlut则无法做到这一点。

被警告:如果您创建的窗口大于桌面,那些不在视图中的像素不能通过像素所有权测试。 因此,这些像素的内容是不确定的 。 他们可能包含你想要的,但他们可能不是。

对于任何不可见的像素来说都是如此,无论窗口是刚刚离开桌面还是被另一个窗口覆盖。

无论如何,你不应该创建一个窗口大小的桌面。 你应该创建一个正常的窗口,并制作一个包含大颜色和深度渲染 缓冲区的framebuffer对象 。 把所有的渲染都放到这些离屏缓冲区中。 那么你将不必担心窗口的大小限制。

用OpenGL做高分辨率渲染是有点棘手的。 一个问题是,像素所有权测试会阻碍。 另一个是帧缓冲区(对象)的最大尺寸。 第一个问题可以通过使用framebuffer对象或PBuffer来解决。

第二个需要一些技巧:假设我们要渲染一个大小为W×H的图像,其中W和H超过最大帧缓冲区大小; 标记GL_MAX_VIEWPORT_SIZE,GL_MAX_TEXTURE_SIZE,GL_MAX_RENDERBUFFER_SIZE的glGetInteger给出了这些限制。 所以你必须做的是将目标图像分割成小于这些限制的图块,渲染这些图块然后重新组合它们。 假设W_t和H_t是瓦片大小, W_t := W / NH_t := H / M并且我们有相应大小的PBuffer或Framebuffer对象。 然后我们可以用2个循环渲染这些图块:

 for m in 0 to M: for n in 0 to N: render_tile(n, m) 

那么render_tile(n,m)怎么样的呢?

 render_tile(n,m): 

显然我们使用整个瓦片作为渲染缓冲区

  glViewport(0, 0, W_t, H_t) 

所以投影有什么变化。 不知何故,我们必须将投影与投影平面中的瓦片一起移动。 投影平面也被称为“近”平面。 近平面的范围是right - lefttop - bottom ,所以我们把近平面分成大小(right - left) / N × (top - bottom) / M瓦片,这就是我们需要使用的移步长:

  shift_X = (right - left) / N shift_Y = (top - bottom) / M glMatrixMode(GL_PROJECTION) glLoadIdentity() switch Projection: case Ortho: glOrtho( left + shift_X * n, left + shift_X * (n+1), bottom + shift_Y * m, bottom + shift_Y * (n+1), near, far) case Perspective: glFrustum( left + shift_X * n, left + shift_X * (n+1), bottom + shift_Y * m, bottom + shift_Y * (n+1), near, far) render_scene() 

以防万一,我们如何得到left, right, top, bottom的角度来看:

 right = -0.5 * tan(fov) * near left = -right; top = aspect * right bottom = -top