Подтвердить что ты не робот

Эффективное внеэкранное рендеринг QPainterPaths (требуется решение OpenGL и не OpenGL)

  • В моем приложении я рисую карту улицы, используя QPainter на widget
    • сделанный QPainterPaths, который содержит предварительно просчитанные пути, которые нужно нарисовать
    • widget в настоящее время является QWidget, а не QGLWidget, но это может измениться.
  • Я пытаюсь переместить картину за пределы экрана и разделить ее на отдельные задания
    • Я хочу нарисовать каждый кусок на QImage и, наконец, нарисую все изображения на widget
    • QPainterPaths уже помечены, поэтому это не проблема.
    • проблема заключается в том, что рисунок QImages примерно в 5 раз медленнее, чем рисование на QWidget
  • Некоторое тестовое тестирование, которое я сделал
    • значения времени представляют собой округленные средние значения по нескольким прогонам
    • тестовый фрагмент содержит 100 QPainterPaths, которые имеют около 150 линейных сегментов линии
    • грубые 15k пути рисуются с помощью QPainter::Antialiasing подсказки рендеринга, QPen использует круглую кепку и круглое соединение
  • Помните, что мой источник QPainterPaths (и ширина строки + цвет, некоторые отрисованные, некоторые заполнены)
    • Мне не нужны все остальные типы чертежей QPainter поддерживает
    • Может QPainterPaths быть преобразован в нечто другое, которое можно нарисовать на 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
----------------------------------------------------+--------------------------

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

Было бы неплохо, если бы вы могли сказать мне решение, отличное от OpenGL, так как я хочу скомпилировать свое приложение в двух версиях: OpenGL и non-OpenGL version. < ш > Кроме того, я хочу, чтобы решение могло отображаться в потоке без GUI.


Есть ли хороший способ эффективно вырезать куски за пределами экрана?
Есть ли внеэкранная счетная часть QGLWidget (OpenGL за пределами экрана), который может использоваться как устройство рисования для QPainter?

4b9b3361

Ответ 1

Документ Qt-interest Archive, август 2008 г. QGLContext:: create()

говорит:

QGLContext может быть создан только с помощью действительного устройства GL-краски, которое означает, что он должен быть привязан к QGLWidget, QGLPixelBuffer или QPixmap при его создании. Если вы используете QPixmap, это даст вам только для программного обеспечения, и вы этого не хотите. Объект QGLFramebufferObject само по себе не является действительным устройством окраски GL, оно может быть создано только внутри контекст QGLWidget или QGLPixelBuffer. Это означает, что вам нужен QGLWidget или QGLPixelBuffer в качестве базы для вашего QGLFramebufferObject.

Как указано в документе, если вы хотите отображать в буфер вне экрана с помощью opengl, вам нужен QGLPixelBuffer. Код ниже - очень простой пример, демонстрирующий, как использовать QGLPixelBuffer с OpenGL:

#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 как:

enter image description here

Для версии non-opengl с использованием QPixmap код может быть в следующих формах:

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, который выглядит следующим образом:

enter image description here

Хотя код прост, но он работает, возможно, вы можете сделать некоторые изменения, чтобы сделать его подходящим для вас.