QPainterPaths的高效屏幕外渲染(需要OpenGL和非OpenGL解决scheme)

  1. 在我的应用程序中,我使用QPainterwidget上绘制街道地图
    • QPainterPaths ,包含预先绘制的path
    • widget目前是一个QWidget ,而不是一个QGLWidget ,但这可能会改变。
  2. 我正试图将这幅画移出屏幕,并将其分割成大块的作业
    • 我想绘制每个块到QImage ,最后将所有图像绘制到widget
    • QPainterPaths已经分块,所以这不是问题
    • 问题是,在QImages上绘图比在QWidget绘图大约5倍
  3. 我做了一些基准testing
    • 时间值在多次运行中取平均值
    • testing块包含100个QPainterPaths ,每个QPainterPaths具有大约150个线性线段
    • QPainter::Antialiasing渲染提示绘制了大约15k条path, QPen使用圆顶和圆形连接
  4. 请记住,我的源代码是QPainterPaths (线宽+颜色;一些绘制 ,一些填充
    • 我不需要QPainter支持的所有其他types的绘图
    • QPainterPaths可以转换成其他可以在OpenGL buffer上绘制的东西,这将是一个很好的解决scheme。
    • 我不熟悉OpenGL离屏渲染,我知道有不同types的OpenGL缓冲区,其中大部分不是用于2D图像渲染,而是用于顶点数据。
 Paint Device for chunk | Rendering the chunk itself | Painting chunk on QWidget -----------------------+----------------------------+-------------------------- QImage | 2000 ms | < 10 ms QPixmap (*) | 250 ms | < 10 ms QGLFramebufferObj. (*) | 50 ms | < 10 ms QPicture | 50 ms | 400 ms -----------------------+----------------------------+-------------------------- none (directly on a QWidget in paintEvent) | 400 ms ----------------------------------------------------+-------------------------- 

(*) These 2 lines have been added afterwards and are solutions to the problem!

如果你能告诉我一个非基于OpenGL的解决scheme ,那就太好了,因为我想编译两个版本的应用程序: OpenGLnon-OpenGL版本。
另外,我希望解决scheme能够在非GUI线程中呈现。


有没有一个很好的方法来有效地画出块?
QGLWidget (一个OpenGL的屏幕外缓冲区)有一个离屏计数器部分,可以用作QPainter的绘图设备吗?

Qt-interest档案,2008年8月QGLContext :: create()

说:

一个QGLContext只能用一个有效的GL绘图设备来创build,这意味着当你创build它的时候,它需要被绑定到一个QGLWidget,QGLPixelBuffer或者QPixmap。 如果你使用QPixmap,它会给你只有软件的渲染,而你不需要它。 QGLFramebufferObject本身不是一个有效的GL绘图设备,它只能在QGLWidget或QGLPixelBuffer的上下文中创build 。 这意味着你需要一个QGLWidget或QGLPixelBuffer作为你的QGLFramebufferObject的基础。

正如文档所指出的那样,如果你想使用opengl在一个离屏的缓冲区中渲染,你需要QGLPixelBuffer。 下面的代码是一个非常简单的例子,演示了如何在OpenGL中使用QGLPixelBuffer:

 #include <QtGui/QApplication> #include <Windows.h> #include <gl/GL.h> #include <gl/GLU.h> #include <QtOpenGL/QGLFormat> #include <QtOpenGL/QGLPixelBuffer> int main(int argc, char *argv[]) { QApplication a(argc, argv); // Construct an OpenGL pixel buffer. QGLPixelBuffer glPixBuf(100, 100); // Make the QGLContext object bound to pixel buffer the current context glPixBuf.makeCurrent(); // The opengl commands glClearColor(1.0, 1.0, 1.0, 0.0); glViewport(0, 0, 100, 100); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, 100, 0, 100); glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 0.0, 0.0); glPointSize(4.0); glBegin(GL_TRIANGLES); glVertex2i(10, 10); glVertex2i(50, 50); glVertex2i(25, 75); glEnd(); // At last, the pixel buffer was saved as an image QImage &pImage = glPixBuf.toImage(); pImage.save(QString::fromLocal8Bit("gl.png")); return a.exec(); } 

该程序的结果是一个PNG图像文件为:

在这里输入图像说明

对于使用QPixmap的非opengl版本,代码可能采用以下forms:

 int main(int argc, char *argv[]) { QApplication a(argc, argv); QPixmap pixmap(100, 100); QPainter painter; painter.begin(&pixmap); painter.drawText(10, 45, QString::fromLocal8Bit("I love American.")); painter.end(); pixmap.save(QString::fromLocal8Bit("pixmap.png")); return a.exec(); } 

上面的程序的结果是一个PNG文件,如下所示:

在这里输入图像说明

虽然代码很简单,但它的工作原理,也许你可以做一些改变,使其适合你。