QPainterPaths的高效离屏渲染(需要OpenGL和非OpenGL解决方案)

lee*_*mes 45 c++ opengl qt qpainter

  1. 在我的应用程序中,我使用QPaintera 绘制街道地图widget
    • QPainterPaths它制作包含预先绘制的路径
    • widget目前是QWidget,不是QGLWidget,但这可能会改变.
  2. 我正试图将这幅画移出屏幕并将其拆分成大块的工作
    • 我想将每个块QImage绘制成a 并最终将所有图像绘制到widget
    • QPainterPaths 已经分块了,所以这不是问题
    • 问题是,绘图比绘图QImages5倍QWidget
  3. 我做过一些基准测试
    • 时间值是多次运行的四舍五入平均值
    • test chunk包含100个QPainterPaths,每个有大约150个线性线段
    • 使用QPainter::Antialiasing渲染提示绘制大约15k路径,QPen使用圆顶和圆形连接
  4. 请记住,我的来源是QPainterPaths(和线宽+颜色;一些绘制,一些填充)
    • 我不需要所有其他类型的绘图QPainter支持
    • 可以QPainterPaths转换为可以在a上绘制的其他东西OpenGL buffer,这将是一个很好的解决方案.
    • 我不熟悉OpenGL屏幕外渲染,我知道有不同类型的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
----------------------------------------------------+--------------------------
Run Code Online (Sandbox Code Playgroud)

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

如果您能告诉我一个非基于OpenGL的解决方案,那将是很好的,因为我想在两个版本中编译我的应用程序:OpenGLnon-OpenGL版本.
此外,我希望该解决方案能够在非GUI线程中呈现.


是否有一种有效的方法可以在屏幕外有效地绘制块?
是否有一个屏幕外计数器部分QGLWidget(OpenGL屏幕外缓冲区)可以用作涂装设备QPainter

Ala*_*ars 5

Qt-interest Archive的文档,2008年8月QGLContext :: create()

说:

QGLContext只能使用有效的GL绘图设备创建,这意味着在创建它时需要将其绑定到QGLWidget,QGLPixelBuffer或QPixmap.如果您使用QPixmap,它将为您提供纯软件渲染,而您不需要它.QGLFramebufferObject本身不是有效的GL绘图设备,它只能在QGLWidget或QGLPixelBuffer的上下文中创建.这意味着您需要 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();
}
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

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

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();
}
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

虽然代码很简单,但它可以工作,也许你可以做一些改动,使它适合你.