我目前正尝试使用glReadPixels拍摄各种相机位置和不同图像分辨率的OpenGL渲染3D世界的快照。我有两个实现OpenGL窗口程序的GUI库选择:Qt和freeglut。经过两次实验后,我意识到Qt并没有将QGLWidget快照的图像分辨率限制为桌面大小,但我不能对freeglut做同样的事情。
我希望我可以使用Qt进行这个快照抓取程序,但我只限于过剩,因为我的项目团队伙伴正在研究同一个程序的另一个模块,他们没有时间学习新的库和IDE(Qt Creator) 。他正在使用Visual Studio 2008。
无论如何,我是否可以创建一个不受桌面尺寸限制的过剩窗口,可以大到4000 x 2000?
答案 0 :(得分: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
,我们有一个相应大小的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 - left
和top - 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
答案 1 :(得分:4)
经过两次实验后,我意识到Qt并没有将QGLWidget快照的图像分辨率限制为桌面大小,但我不能对freeglut做同样的事情。
警告:如果您创建的窗口大于桌面,那些不在视图中的像素不会通过像素所有权测试。因此,这些像素的内容是 undefined 。他们可能包含您想要的内容,但可能没有。
对于任何不可见的像素都是如此,无论窗口是在桌面之外还是被另一个窗口覆盖。
无论如何,您不应该创建一个与桌面大小相同的窗口。您应该创建一个普通窗口,并创建一个包含大颜色和深度framebuffer object的renderbuffer。对这些屏幕外缓冲区进行所有渲染。然后,您不必担心窗口的大小限制。