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

ksm*_*ing 4 windows opengl resize

我目前正在尝试使用glReadPixels拍摄各种相机位置和不同图像分辨率的OpenGL渲染3D世界的快照.我有两个实现OpenGL窗口程序的GUI库选择:Qt和freeglut.经过两次实验后,我意识到Qt并没有将QGLWidget快照的图像分辨率限制在桌面大小,但我无法对freeglut做同样的事情.

我希望我可以使用Qt进行这个快照抓取程序,但我只限于过剩,因为我的项目团队伙伴正在研究同一个程序的另一个模块,他们没有时间学习新的库和IDE(Qt Creator).他正在使用Visual Studio 2008.

无论如何,我有没有创建一个不受桌面尺寸限制的过剩窗口,可以大到4000 x 2000?

dat*_*olf 9

使用OpenGL进行高分辨率渲染有点棘手.一个问题是像素所有权测试妨碍了.另一个是帧缓冲区(对象)的最大大小.第一个问题可以通过使用帧缓冲对象或PBuffer来克服.

第二个需要一些技巧:假设我们想要渲染大小为W×H的图像,其中W和H超过最大帧缓冲区大小; glGetInteger令牌GL_MAX_VIEWPORT_SIZE,GL_MAX_TEXTURE_SIZE,GL_MAX_RENDERBUFFER_SIZE为您提供这些限制.因此,您需要做的是将目标图像分割成小于这些限制的图块,渲染这些图块然后重新组合它们.比方说,W_T和H_t是瓷砖尺寸W_t := W / N,H_t := H / M并且我们有一个相应大小的p缓冲器或帧缓冲区对象.然后我们可以使用2循环渲染这些图块:

for m in 0 to M: for n in 0 to N:
    render_tile(n, m)
Run Code Online (Sandbox Code Playgroud)

那怎么render_tile(n,m)样?

render_tile(n,m):
Run Code Online (Sandbox Code Playgroud)

显然我们将整个图块用作渲染缓冲区

    glViewport(0, 0, W_t, H_t)
Run Code Online (Sandbox Code Playgroud)

所以预测会有什么变化.不知何故,我们要将投影与投影平面中的图块一起移动.投影平面也称为"近"平面.近平面的范围是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()
Run Code Online (Sandbox Code Playgroud)

以防我们如何获得left, right, top, bottom透视:

right = -0.5 * tan(fov) * near
left = -right;
top = aspect * right
bottom = -top
Run Code Online (Sandbox Code Playgroud)


Nic*_*las 4

经过对两者的一些实验后,我意识到 Qt 不会将 QGLWidget 快照的图像分辨率限制为桌面大小,但我无法对 freeglut 做同样的事情。

请注意:如果您创建的窗口大于桌面,则那些不在视图中的像素不会通过像素所有权测试。因此,这些像素的内容是未定义的。它们可能包含您想要的内容,但也可能不包含。

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

无论如何,您不应该创建一个与桌面大小相同的窗口。您应该创建一个普通窗口,并创建一个包含大颜色和深度renderbuffer 的帧缓冲区对象。对这些离屏缓冲区进行所有渲染。那么您就不必担心窗口的大小限制。

尽管您将受到渲染缓冲区的最大大小以及最大视口大小的限制。