现在我假设我们正在谈论 Qt4。
是否可以在 QGLWidget 中完全离屏渲染
离屏渲染根本不是一个真正依赖于窗口系统的任务。大多数工具包中 WGL(至少)和 GLX 的唯一问题是您无法拥有无表面的背景,即未绑定到窗口系统提供的可绘制对象的上下文。换句话说,您将始终提供窗口系统默认帧缓冲区只要当前上下文存在,就不可变。
有一些方法可以创建不需要的上下文window手动使用 X11 但通常不值得这么麻烦。例如,对于 EGL 和 OpenGL ES,这个问题不存在,因为有一个扩展专门针对这个问题,即离屏渲染。
但是,您可以在设置有效上下文后简单地隐藏 QGLWidget,并使用帧缓冲区对象来完成所有操作,而无需默认帧缓冲区干预。
我可以避免 QGLWidget 中的显示器刷新率吗?
不,据我所知,Qt4 的 OpenGL 模块无法以编程方式关闭垂直同步。您可以向 SDL 或 GLFW 寻求类似的帮助(不确定 FreeGLUT)。
但是,您始终可以在驱动程序设置中关闭某些功能。这也会影响 QGLWidget (或者更好地说,底层窗口系统的交换行为。)
在帧缓冲区上进行离屏渲染可以更快吗?
最后真的应该不重要。您需要将图像数据存放在 VRAM 之外的其他位置,因此在将当前帧渲染到 FBO 后,无论如何您都需要获取图像。您要么将结果传输到前缓冲区(如果需要双缓冲和交换,则将结果传输到后缓冲区),或者需要在进一步处理当前帧之前读回内容。
然而,与任何 OpenGL 和性能相关的事情一样,不要猜测 - 简介!
如何在帧缓冲区上完全渲染而不需要缓慢的 PaintGL() 调用?
一旦设置了上下文,您就不需要该小部件at all。您可以自己完成所有的魔法,无需 Qt 的干预。唯一的原因paintGL()
存在的目的是为用户提供一个易于使用的界面,保证在需要更新小部件时调用该界面。
EDIT:关于评论中的查询,请参阅这个最小的代码示例,它应该可以跨平台工作而无需更改。
#include <iostream>
#include <QtOpenGL/QGLWidget>
#include <QtGui/QApplication>
void renderOffScreen ()
{
std::cout << glGetString(GL_VENDOR) << std::endl;
std::cout << glGetString(GL_RENDERER) << std::endl;
std::cout << glGetString(GL_VERSION) << std::endl;
// do whatever you want here, e.g. setup a FBO,
// render stuff, read the results back until you're done
// pseudocode:
//
// setupFBO();
//
// while(!done)
// {
// renderFrame();
// readBackPixels();
// processImage();
// }
}
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QGLWidget gl;
// after construction, you should have a valid context
// however, it is NOT made current unless show() or
// similar functions are called
if(!gl.isValid ())
{
std::cout << "ERROR: No GL context!" << std::endl;
return -1;
}
// do some off-screen rendering, the widget has never been made visible
gl.makeCurrent (); // ABSOLUTELY CRUCIAL!
renderOffScreen ();
return 0;
}
在我当前的机器上,程序打印:
ATI 科技公司
AMD Radeon HD 7900 系列
1.4(2.1(4.2.12337 兼容性配置文件上下文 13.101))
请注意如何QGLWidget
实际上从未变得可见,并且不会发生任何事件处理。 Qt OpenGL 库仅用于上下文创建。其他任何事情都可以在没有 Qt 干预的情况下完成。只是不要忘记根据您的需要设置视口和其他内容。
请注意:如果您需要的只是一些方便的方法来设置上下文,您可能需要切换到一些比 Qt4 更轻量的工具包,例如 FreeGLUT。就我个人而言,我发现 FreeGLUT 在设置有效上下文方面要可靠得多,这与我在某些硬件上想要的方式完全一致,例如桑迪桥 CPU。