2017-02-23 21 views
0

我在ubuntu 16.04上使用Qt 5.7和C++。我試圖實現一個繼承qglwidget的類,它以給定的速率(3-10 Hz)將圖像渲染到屏幕上。在特定時間在qglwidget上繪製矩形

除此之外,我想在屏幕上的某個地方繪製一個小的矩形,將其顏色從黑色變爲白色,反之亦然。當圖像出現時,它應該從白色切換到黑色,並在下一個圖像到來之前的某個預定義時間切換回黑色。 現在我使用一個紋理加載圖像(QImage的從對象),使用

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

,這是我paintGL()過載:

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

,如果可能,我想知道繪製小部件,並同時渲染矩形和圖像。我已經嘗試過使用QPainter,但一直在繪製矩形使得圖像消失(矩形不應該在圖像上,而是在小部件的某個角落裏,現在什麼都沒有繪製)。

將不勝感激任何幫助!

+0

如果'QPainter'使用它假定有OpenGL的狀態獨佔訪問。如果您直接使用OpenGL API,則必須在調用'QPainter'-API之前恢復某些狀態。通過這種方式,我解決了使用OpenGL渲染3D場景後使用'QPainter'呈現HUD的問題。 – Scheff

+0

也許你不應該調用'swapBuffers();',因爲這應該由'QGLWidget'來完成。 (我必須查看我的源代碼以提供更多關於此的詳細信息。) – Scheff

+0

你必須知道,使用'QOpenGLFunctions'方法並調用GL函數(來自任何非Qt庫)是一個區別。這是可能的,尤其是在文檔中考慮。例如[QGLWidgetClass](http://doc.qt.io/qt-5/qglwidget.html#details)。如果調用「非Qt」OpenGL函數,這可能繞過Qt中的內部狀態跟蹤。 – Scheff

回答

1

這是混合的OpenGL代碼和QPainter塗料處理程序的最小樣本應用程序:

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

和紋理圖像的源:

/* 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", 
}; 

(抱歉,低圖像質量。高分辨率的圖片對於這個網站來說太大了。)

這兩個文件必須被編譯和被鏈接在一起。 (而不是使用頭,我簡單地(重新)在另一個文件的開頭聲明fluffyCat.cc中的變量。)

不幸的是,我無法提供Qt項目。 (我用CMake腳本編譯它。)這留下來作爲練習。

Snapshot of the testQGLWidgetHUD

順便說一句,我沒有意識到的OP有關QGLWidget。該示例使用自Qt5 +以來推薦的新的QOpenGLWidget

QTimer用於非常簡單的動畫類型(以顯示定期繪畫已完成)。

Btw。我偶然發現了一個錯誤(這並不是第一次......) 設置GL_TEXTURE_MIN_FILTERGL_TEXTURE_MAG_FILTER是很重要的,因爲這些是兩種罕見的OpenGL狀態,如果保留默認值,這些狀態不起作用。

+0

當我創建Qpainter(使用QPainter qPainter(this))時,它會覆蓋我正在繪製的紋理,即使我沒有調用任何其他繪畫說明。任何想法爲什麼?我也嘗試了整個代碼塊,它不起作用,只是繪製了對角線。 – JLev

+0

@JLev我明確要求'QOpenGLFunctions_1_1'像你一樣使用OpenGL 1.1。默認的'QOpenGLFunctions'不再提供'glColor3f()'和'glRectf()'。 (在OpenGL 3+中已棄用)。或許,請求的OpenGL 1.1函數在您的OpenGL驅動程序中不受支持(儘管 - 這很難相信...) – Scheff

+0

@JLev我試圖記住如果'QOpenGLFunctions'xx不是能夠綁定請求的OpenGL函數。我在Qt'QOpenGLFunctions'文檔中找不到任何成功的檢索功能。我想,這只是在這種情況下崩潰。 (我曾經在Windows計算機上的驅動程序更新失敗時看到了這一點,並且在沒有相應的OpenGL支持的情況下回退到通用驅動程序。關於Linux我不知道。) – Scheff

0

好了,終於這工作了增加一個小矩形 -

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

當然,謝謝@Scheff – JLev