2017-02-23 4 views
0

Ich benutze Qt 5.7 mit C++ auf Ubuntu 16.04. Ich versuche, eine Klasse zu implementieren, die qglwidget erbt, die Bilder auf dem Bildschirm mit einer bestimmten Rate (3-10 Hz) rendert.Malen Sie eine Rect auf qglwidget zu bestimmten Zeiten

Außerdem möchte ich irgendwo auf dem Bildschirm eine kleine Rect zeichnen, die ihre Farbe von Schwarz nach Weiß ändert und umgekehrt. Wenn das Bild erscheint, sollte es von Weiß zu Schwarz wechseln und einige Zeit vor dem nächsten Bild wieder auf Schwarz umschalten. Im Moment bin ich mit einer Textur, die Bilder zu laden (von QImage Objekten),

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, img.width(), img.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); 

mit und das ist mein paintGL() Überlastung:

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 
glEnable(GL_TEXTURE_2D); 
drawTexture(QRect(0,0,1,1),texture,GL_TEXTURE_2D); 
swapBuffers(); 
glDisable(GL_TEXTURE_2D); 

und ich habe mich gefragt, ob es möglich Zeichnen Sie das Widget und lassen Sie es gleichzeitig Rekt und Bild rendern. Ich habe versucht, mit QPainter, aber immer noch bekommen, dass die Zeichnung der rect das Bild verschwinden (die Rect sollte nicht auf dem Bild sein, aber auf einer Ecke des Widgets, wo nichts jetzt gezeichnet wird).

Würde mich über jede Hilfe freuen!

+0

Wenn 'QPainter' verwendet wird, exklusiven Zugriff auf OpenGL Staaten haben annimmt. Wenn Sie die OpenGL-API direkt verwenden, müssen Sie bestimmte Zustände wiederherstellen, bevor Sie die QPainter-API aufrufen. Auf diese Weise löste ich Probleme, um ein HUD mit 'QPainter' zu rendern, nachdem eine 3D-Szene mit OpenGL gerendert wurde. – Scheff

+0

Wahrscheinlich sollten Sie 'swapBuffers();' nicht aufrufen, weil dies durch 'QGLWidget' erfolgen soll. (Ich musste in meinen Quellcode schauen, um mehr Details dazu zu geben.) – Scheff

+0

Sie müssen sich bewusst sein, dass die Verwendung von 'QOpenGLFunctions' Methoden und das Aufrufen von GL Funktionen (aus jeder Nicht-Qt Bibliothek) ein Unterschied ist. Es ist möglich und insbesondere im Doc berücksichtigt. z.B. [QGLWidgetClass] (http://doc.qt.io/qt-5/qglwidget.html#details). Wenn "Nicht-Qt" OpenGL-Funktionen aufgerufen werden, kann dies die interne Zustandsverfolgung in Qt umgehen. – Scheff

Antwort

1

Dies ist eine minimal-Beispielanwendung, die OpenGL-Code und QPainter in Lack-Handler mischt:

#include <cassert> 
#include <QApplication> 
#include <QOpenGLFunctions_1_1> 
#include <QOpenGLWidget> 
#include <QMainWindow> 
#include <QPainter> 
#include <QTimer> 

// manually added types (normally provided by glib) 
typedef unsigned guint; 
typedef unsigned char guint8; 

extern const struct { 
    guint  width; 
    guint  height; 
    guint  bytes_per_pixel; /* 3:RGB, 4:RGBA */ 
    guint8  pixel_data[1]; 
} fluffyCat; 

class GLWidget: public QOpenGLWidget, protected QOpenGLFunctions_1_1 { 
    private: 
    float _step; 
    GLuint _idTex; 
    QTimer _qTimer; 
    public: 
    GLWidget(QWidget *parent = 0): 
     QOpenGLWidget(parent), 
     _step(0.0f), _idTex(0) 
    { 
     _qTimer.setInterval(100); // 100 ms -> 10 Hz 
     QObject::connect(&_qTimer, &QTimer::timeout, 
     this, &GLWidget::timeout); 
    } 
    protected: 
    virtual void initializeGL(); 
    virtual void paintGL(); 
    private: 
    void timeout(); 
}; 

void GLWidget::initializeGL() 
{ 
    initializeOpenGLFunctions(); 
    glClearColor(0.525, 0.733f, 0.851, 1.0); 
    glGenTextures(1, &_idTex); 
    glBindTexture(GL_TEXTURE_2D, _idTex); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, fluffyCat.width, fluffyCat.height, 0, 
    GL_RGB, GL_UNSIGNED_BYTE, fluffyCat.pixel_data); 
    glBindTexture(GL_TEXTURE_2D, 0); 
    _qTimer.start(); 
} 

void GLWidget::paintGL() 
{ 
    // prepare OpenGL rendering 
    QPainter qPainter(this); 
    qPainter.beginNativePainting(); 
    // do OpenGL rendering 
    glColor3f(1.0f, 1.0f, 1.0f); 
    bool tex2dOld = glIsEnabled(GL_TEXTURE_2D); 
    glEnable(GL_TEXTURE_2D); 
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 
    static GLfloat envColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; 
    glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envColor); 
    glBindTexture(GL_TEXTURE_2D, _idTex); 
    float x = sin(_step) * 0.5f, y = cos(_step) * 0.5f; 
#if 0 // does not work (no tex-coords) 
    glRectf(x - 0.5f, y - 0.5f, x + 0.5f, y + 0.5f); 
#else // (not) 0 
    glBegin(GL_QUADS); 
    glColor3f(1.0f, 1.0f, 1.0f); 
    glTexCoord2i(0, 1); 
    glVertex2f(x - 0.5f, y - 0.5f); 
    glTexCoord2i(1, 1); 
    glVertex2f(x + 0.5f, y - 0.5f); 
    glTexCoord2i(1, 0); 
    glVertex2f(x + 0.5f, y + 0.5f); 
    glTexCoord2i(0, 0); 
    glVertex2f(x - 0.5f, y + 0.5f); 
    glEnd(); 
#endif // 0 
    glBindTexture(GL_TEXTURE_2D, 0); 
    //if (!tex2dOld) glDisable(GL_TEXTURE_2D); 
    // prepare Qt painting 
    qPainter.endNativePainting(); 
    // do Qt painting (HUD) 
    QPen qPen; 
    qPen.setWidth(1); 
    qPen.setColor(QColor(Qt::black)); 
    qPen.setStyle(Qt::SolidLine); 
    qPainter.resetMatrix(); 
    qPainter.setPen(qPen); 
    qPainter.drawLine(0, 0, width(), height()); 
    qPainter.drawLine(0, height(), width(), 0); 
} 

void GLWidget::timeout() 
{ 
    _step = fmod(_step + 0.1, 2 * 3.141); 
    update(); // force redraw 
} 

int main(int argc, char **argv) 
{ 
    QApplication app(argc, argv); 
    QMainWindow win; 
    GLWidget view3d; 
    win.setCentralWidget(&view3d); 
    win.show(); 
    return app.exec(); 
} 

und die Quelle für die Bildtextur:

/* GIMP RGB C-Source image dump (fluffyCat.cc) */ 

// manually added types (normally provided by glib) 
typedef unsigned guint; 
typedef unsigned char guint8; 

extern const struct { 
    guint  width; 
    guint  height; 
    guint  bytes_per_pixel; /* 3:RGB, 4:RGBA */ 
    guint8  pixel_data[16 * 16 * 3 + 1]; 
} fluffyCat = { 
    16, 16, 3, 
    "x\211s\215\232\200gw`fx`at[cx^cw^fu\\itZerWn|ap~cv\204jnzedq^fr^kzfhv^Ra" 
    "GRbMWdR\\jXer^qw_\311\256\226\271\253\235\275\264\252\315\277\260\304\255" 
    "\231u~i\213\225\207l{fly`jx\\^nRlz_z\206nlx`t~i\221\211s\372\276\243\375" 
    "\336\275\376\352\340\356\312\301\235\216\212judgwcl~f\212\226u}\206h\212" 
    "\224q\231\237z\232\236{\216\225v\225\230\200\306\274\244\376\360\327\376" 
    "\361\331\376\360\341\326\275\272\253\240\244{\203p\202\220xp~e{\204^\222" 
    "\230n\212\217g\240\242{\234\236z\214\222r\270\271\247\360\353\340\376\370" 
    "\336\376\363\334\375\357\336\310\254\262\232\223\234\\gRfrX\204\220z\212" 
    "\225g\225\232j\254\255\177\252\250{\225\226u\304\302\265\374\365\351\376" 
    "\375\366\376\367\341\376\361\320\374\346\324\306\241\242\237\232\235n{fj" 
    "[email protected]\231\231\207\374\374\371\377\372\354\376\376\374\376\376" 
    "\372\376\362\332\375\340\301\341\300\264\260\253\262jvdbq\\XkVJTDNTCCG8O" 
    "TE\322\321\313\377\377\375\376\376\373\376\377\376\376\376\375\376\374\362" 
    "\376\360\342\344\311\306\250\244\254R_PL^HXkT<@[email protected]`dP\217\220\177\374\374" 
    "\370\377\377\374\376\375\371\377\377\376\376\374\360\377\367\336\376\350" 
    "\316\342\303\274\246\236\245jtbXdQTdNQYGU\\KchV\317\315\302\377\376\372\377" 
    "\376\367\376\373\360\377\376\367\376\366\337\376\355\312\374\331\271\323" 
    "\263\251\216\214\214\\hTP^HL\\FR[LMXI^dW\355\352\342\376\375\366\377\374" 
    "\360\376\374\361\376\374\361\376\356\321\374\331\264\374\330\266\330\270" 
    "\260\200||Y`SLVE>K9BJ<CN?VYP\347\330\322\376\366\345\376\363\330\376\367" 
    "\337\377\372\350\374\342\314\326\243\210\375\350\314\352\317\304shc^`TV`" 
    "RVbT>B4IS?PTD\244\232\216\374\355\320\376\354\311\376\351\306\376\362\332" 
    "\374\344\321\267\206u\375\362\337\326\274\272\\POMNBT]LNZH:<*<A*TV>OI;\242" 
    "\222\207\340\304\243\375\335\262\372\336\272\376\361\334\320\241\212\374" 
    "\352\322\266\233\237c\\WFH;MR>\\`F~xP\220\214[pqE\211\202\\g]=\230\214`\313" 
    "\266\207\344\303\240\362\336\274\323\257\201\333\304\240\305\252\204\254" 
    "\232p\216\206\\\206\203U\232\224b\234\244b\246\257m\220\232`\224\227h~\202" 
    "W\206\213]\204\210W\227\227i|\177RvzNlsGrtJwtLz}N{\204RlxF", 
}; 

(Sorry, für die niedrige Bildqualität Hi-res Bild wäre zu groß für diese Seite.)

Die beiden Dateien müssen kompiliert und miteinander verknüpft werden. (Anstatt eine Überschrift zu verwenden, deklarierte ich einfach die Variable in fluffyCat.cc am Anfang der anderen Datei.)

Leider kann ich kein Qt-Projekt bereitstellen. (Ich habe es mit CMake-Skripten kompiliert.) Dies ist als Übung übrig.

Snapshot of the testQGLWidgetHUD

By the way, ich wusste nicht, das OP ist mit QGLWidget verwendet. Das Beispiel verwendet das neue QOpenGLWidget, das seit Qt5 + empfohlen wird.

Die QTimer wird für sehr einfache Art der Animation verwendet (um zu zeigen, dass periodisches Malen gemacht wird).

Btw. Ich stolperte über einen Fehler (der mich nicht beim ersten Mal traf ...) Es ist wichtig, GL_TEXTURE_MIN_FILTER und GL_TEXTURE_MAG_FILTER zu setzen, weil dies zwei der seltenen OpenGL-Zustände sind, die nicht funktionieren, wenn sie mit Standardwerten belassen werden.

+0

Wenn ich nur Qpainter erstelle (mit QPainter qPainter (this)), überschreibt es die Textur, die ich zeichne, auch wenn ich keine anderen Malanweisungen anrufe. Irgendwelche Ideen warum? Ich habe auch den ganzen Block Code ausprobiert, und es funktioniert nicht, nur die diagonalen Linien. – JLev

+0

@JLev Ich habe explizit 'QOpenGLFunctions_1_1' angefordert, um OpenGL 1.1 wie Sie zu verwenden. Der Standard 'QOpenGLFunctions' stellt' glColor3f() 'und' glRectf() 'nicht mehr zur Verfügung. (Es ist in OpenGL 3+ veraltet.) Vielleicht werden die angeforderten OpenGL 1.1-Funktionen nicht auf Ihrem OpenGL-Treiber unterstützt (obwohl - das ist kaum zu glauben ...) – Scheff

+0

@JLev Ich versuchte mich zu erinnern, was passiert, wenn 'QOpenGLFunctions'xx nicht ist in der Lage, die angeforderten OpenGL-Funktionen zu binden. Ich konnte im Qt 'QOpenGLFunctions'-Dokument keine Erfolgsabruffunktion finden. Ich schätze, in diesem Fall stürzt es einfach ab. (Ich sah dies, wenn der Treiber auf dem Windows-Computer eines Colaborator fehlgeschlagen und fiel zurück auf generische Treiber ohne entsprechende OpenGL-Unterstützung. Über Linux Ich weiß nicht.) – Scheff

0

Nun, schließlich arbeitete dies ein kleines rect für das Hinzufügen -

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 
QPainter qPainter(this); 
QPainterPath path; 
path.addRect(10, 10, 30,30); 
QPen pen(Qt::black, 1); 
qPainter.setPen(pen); 
qPainter.fillPath(path, Qt::black); 
qPainter.drawPath(path); 
qPainter.end(); 
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 
glShadeModel(GL_FLAT); 
glEnable(GL_LIGHTING); 
glEnable(GL_LIGHT0); 
glEnable(GL_TEXTURE_2D); 
glColor3f(0.5, 0.5, 0); 
glBindTexture(GL_TEXTURE_2D, texture); 
glBegin(GL_QUADS); 
glTexCoord2f(0.0f, 1.0f); glVertex2f(0.5f, -0.5f); // vertex 1 
glTexCoord2f(0.0f, 0.0f); glVertex2f(0.5f, 0.5f); // vertex 2 
glTexCoord2f(1.0f, 0.0f); glVertex2f(-0.5f, 0.5f); // vertex 3 
glTexCoord2f(1.0f, 1.0f); glVertex2f(-0.5f, -0.5f); // vertex 4 
glEnd(); 
glDisable(GL_TEXTURE_2D); 
glDisable(GL_LIGHTING); 
glDisable(GL_LIGHT0); 
+0

Und natürlich, danke @Scheff – JLev

Verwandte Themen