在我的应用程序中,我拍摄QGLWidget内容的快照有两个目的:
- 当只有叠加层发生变化时,不要一直重绘场景,而是使用缓存的像素图
- 用户拍摄特定情节的屏幕截图(3D场景(
我尝试的第一件事是grabFrameBuffer()
.对于第一个应用程序,使用此功能是很自然的,小部件中当前可见的内容正是我想要缓存的内容。问题:在某些硬件上(例如英特尔集成显卡、带有 GeForce 显卡的 Mac OS X(,获得的图像不包含当前屏幕内容,而是包含之前的内容。因此,如果场景要绘制两次,在屏幕上您会看到第二幅绘图,在图像中您会看到第一幅绘图(这应该是后台缓冲区的内容?
我尝试的第二件事是renderToPixmap()
。这会使用 paintGL()
渲染,但不使用 paint()
。我把我所有的东西都放在paint()
,因为我使用Qt的绘画功能,只有一小部分代码使用原生GL(beginNativePainting()
,endNativePainting()
(。
我也尝试了常规QWidget的快照功能(QPixmap::fromWidget((,或者它的名字(,但那里的GL帧缓冲是黑色的。
关于如何解决问题并获得当前绘制场景的可靠描述的任何想法?
如何拍摄可靠的QGLWidget快照
将当前场景渲染到帧缓冲,将数据从帧缓冲保存到文件。或者在glFlush之后获取电流背缓冲器。其他任何内容都可能包括伪影或不完整的场景。
QGLWidget::grabFrameBuffer(( 似乎在内部从 OpenGL 调用 glReadPixels((。在双缓冲配置中,初始模式读取后台缓冲区(GL_BACK(,使用 OpenGL 调用 glReadBuffer(GL_FRONT( 切换到前端缓冲区,然后再使用 QGLWidget::grabFrameBuffer(( 在屏幕上显示图像。
QGLWidget::grabFrameBuffer()
的结果与其他所有OpenGL调用一样,取决于视频驱动程序。Qt只是将您的调用转发给驱动程序并获取它返回的图像,但图像的内容不受Qt的控制。除了确保您为视频卡安装了最新的驱动程序外,除了向视频卡制造商报告错误并祈祷之外,您无能为力。
我使用paintGL();
和glFlush()
;在使用grabFrameBuffer()
之前。paintGL 有助于在抓取帧缓冲区之前再次绘制当前帧,从而精确复制当前显示的内容。