45 votes

Rendu hors écran efficace des QPainterPaths (solution OpenGL et non-OpenGL requise)

  1. Dans mon application, je peins une carte des rues à l'aide de QPainter sur un widget
    • fait par QPainterPaths qui contiennent des chemins précalculés à dessiner
    • le site widget est actuellement un QWidget et non un QGLWidget mais cela pourrait changer.
  2. J'essaie de déplacer la peinture hors de l'écran et de la diviser en plusieurs tâches.
    • Je veux peindre chaque morceau sur un QImage et enfin dessiner toutes les images sur le widget
    • QPainterPaths ont déjà été découpées en morceaux, ce n'est donc pas le problème.
    • Le problème est que le fait de dessiner sur QImages Il s'agit de 5 fois plus lent que de puiser dans QWidget
  3. Quelques tests de référence que j'ai effectués
    • les valeurs temporelles sont des moyennes arrondies sur plusieurs cycles.
    • le morceau de test contient 100 QPainterPaths qui ont chacune environ 150 segments de ligne linéaire
    • les quelque 15 000 chemins sont dessinés avec QPainter::Antialiasing un indice de rendu, QPen utilise un chapeau rond et un joint rond
  4. Rappelez-vous que mes sources sont QPainterPaths (et largeur de ligne + couleur ; certains dessiné certains rempli )

    • Je n'ai pas besoin de tous les autres types de dessins. QPainter soutient
    • Can QPainterPaths être converti en quelque chose d'autre qui peut être dessiné sur un OpenGL buffer ce serait une bonne solution.
    • Je ne suis pas familier avec OpenGL le rendu hors écran et je sais qu'il existe différents types de tampons OpenGL, dont la plupart ne sont pas destinés au rendu d'images 2D mais aux données de vertex.

    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!

Ce serait bien si vous pouviez me dire un solution non basée sur OpenGL car je veux compiler mon application en deux versions : OpenGL y non-OpenGL version.
De plus, je veux que la solution puisse être rendue dans un fichier de type Fil de discussion non-GUI .


Existe-t-il un bon moyen de dessiner efficacement les morceaux en dehors de l'écran ?
Y a-t-il une contrepartie hors écran de QGLWidget (un OpenGL tampon hors écran) qui peut être utilisé comme un dispositif de peinture pour QPainter ?

5voto

Bloodwolf Points 575

Le document de Archives Qt-interest, août 2008 QGLContext::create()

dit :

Un QGLContext ne peut être créé qu'avec un périphérique de peinture GL valide. ce qui signifie qu'il doit être lié soit à un QGLWidget, soit à un QGLPixelBuffer ou à un QPixmap lorsque vous le créez. Si vous utilisez un QPixmap, vous obtiendrez un un rendu uniquement logiciel, ce que vous ne voulez pas. Un QGLFramebufferObject n'est pas en soi un périphérique de peinture GL valide, il peut seulement être créé dans le dans le contexte d'un QGLWidget ou d'un QGLPixelBuffer. . Ce que cela signifie, c'est que vous besoin de un QGLWidget ou un QGLPixelBuffer comme base pour votre QGLFramebufferObject.

Comme l'indique le document, si vous voulez effectuer un rendu dans un tampon hors écran en utilisant opengl, vous avez besoin de QGLPixelBuffer. Le code ci-dessous est un exemple très simple qui démontre comment utiliser QGLPixelBuffer avec 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();
}

Le résultat du programme est un fichier image png en tant que :

enter image description here

Pour la version non-opengl utilisant QPixmap, le code peut être sous la forme de ce qui suit :

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();
}

Le résultat du programme ci-dessus est un fichier png qui ressemble :

enter image description here

Bien que le code soit simple, mais il fonctionne, vous pouvez peut-être apporter quelques modifications pour qu'il vous convienne.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X