Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QGraphicsView with QOpenGLWidget example
Forum Updated to NodeBB v4.3 + New Features

QGraphicsView with QOpenGLWidget example

Scheduled Pinned Locked Moved General and Desktop
2 Posts 1 Posters 4.6k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    kegon
    wrote on last edited by
    #1

    Hi

    I'm looking for working examples of a QGraphicsView and QGraphicsScene overpainting a QOpenGLWidget.

    I already have a QGraphicsView working with the old QGLWidget but can't work out why dropping in a QOpenGLWidget doesn't work (GL widget has only white instead of texture)

    1 Reply Last reply
    0
    • K Offline
      K Offline
      kegon
      wrote on last edited by
      #2

      OK, here's some code based on some posts I've come across via Google and the "textures" example. Someone please help me make this code work. By the way, I'm currently using OSX 10.9.

      gview.pro:

      HEADERS       = window.h \
                      glwidget.h
      
      SOURCES       = main.cc \
                      window.cc \
                      glwidget.cc
      
      QT           += core gui widgets opengl
      

      main.cc:

      #include <QApplication>
      #include <QSurfaceFormat>
      
      #include "window.h"
      
      int main(int argc, char *argv[])
      {
        QApplication app(argc, argv);
      
        Window window;
        window.show();
      
        window.resize(640,480);
        window.SetTestImage();
      
        return app.exec();
      }
      

      window.h:

      #ifndef WINDOW_H
      #define WINDOW_H
      
      #include <QWidget>
      #include <QGraphicsView>
      #include <QGraphicsScene>
      
      class Window : public QWidget
      {
        Q_OBJECT
      
      public:
        Window();
        void SetTestImage();
      
      private:
        QGraphicsView *view;
        QGraphicsScene *scene;
        QWidget *myGLWidget;
      };
      
      #endif
      

      window.cc:

      #include <QtWidgets>
      
      #include "window.h"
      #include "glwidget.h"
      
      Window::Window()
      {
        QVBoxLayout *mainLayout = new QVBoxLayout;
      
        view  = new QGraphicsView(this);
        scene = new QGraphicsScene(view);
      
        view->setRenderHints(QPainter::Antialiasing);
        scene->setBackgroundBrush(Qt::blue);
      
        myGLWidget = new GLWidget(this);
        QOpenGLWidget *oglw = qobject_cast<QOpenGLWidget *>(myGLWidget);
      
        QSurfaceFormat format;
        format.setSamples(4);
        oglw->setFormat(format);
      
        view->setViewport(myGLWidget);
        view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
      
        view->setScene(scene);
      
        mainLayout->addWidget(view);
        setLayout(mainLayout);
      
        setWindowTitle(tr("GraphicsView + OpenGL Test Unit"));
      }
      
      void Window::SetTestImage()
      {
        QImage input_image(QString("my-test-image.jpg"));
        GLWidget *glw = qobject_cast<GLWidget *>(myGLWidget);
        glw->SetImage(input_image);
      }
      

      glwidget.h:

      #ifndef GLWIDGET_H
      #define GLWIDGET_H
      
      #include <QOpenGLWidget>
      #include <QOpenGLFunctions>
      #include <QOpenGLBuffer>
      #include <QMatrix4x4>
      
      QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram);
      QT_FORWARD_DECLARE_CLASS(QOpenGLTexture)
      
      class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions
      {
        Q_OBJECT
      
      public:
        explicit GLWidget(QWidget *parent = 0);
        ~GLWidget();
      
        void SetImage(const QImage &img);
        void setClearColor(const QColor &color);
      
        QSize minimumSizeHint() const Q_DECL_OVERRIDE;
        QSize sizeHint() const Q_DECL_OVERRIDE;
        void rotateBy(int xAngle, int yAngle, int zAngle);
      
      signals:
        void clicked();
      
      protected:
        void initializeGL() Q_DECL_OVERRIDE;
        void paintGL() Q_DECL_OVERRIDE;
        void resizeGL(int width, int height) Q_DECL_OVERRIDE;
      
        void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
        void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
        void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
      
      private:
        void makeObject();
        void setView(int w, int h);
      
        QColor clearColour;
      
        int xRot;
        int yRot;
        int zRot;
        QPoint lastPos;
      
        QOpenGLShaderProgram *program;
        QOpenGLBuffer vbo;
      
        QOpenGLTexture *frame_texture;
        bool hasTexture;
        float v_aspect;
      };
      
      #endif
      

      glwidget.cc:

      #include "glwidget.h"
      
      #include <QOpenGLShaderProgram>
      #include <QOpenGLTexture>
      #include <QMouseEvent>
      
      GLWidget::GLWidget(QWidget *parent)
          : QOpenGLWidget(parent),
            clearColour(Qt::black),
            xRot(0),
            yRot(0),
            zRot(0),
            program(0),
            frame_texture(NULL),
            v_aspect(1.0)
      {
        hasTexture       = false;
      }
      
      GLWidget::~GLWidget()
      {
        makeCurrent();
      
        if(vbo.isCreated()) vbo.destroy();
        if(hasTexture) delete frame_texture;
      
        delete program;
        doneCurrent();
      }
      
      void GLWidget::SetImage(const QImage &img)
      {
        makeCurrent();
      
        if(frame_texture) delete frame_texture;
        frame_texture = new QOpenGLTexture(img);
        hasTexture    = true;
        v_aspect      = (float)(img.height())/img.width();
      
        makeObject();
        doneCurrent();
        update();
      }
      
      QSize GLWidget::minimumSizeHint() const
      {
        return(QSize(160, 90));
      }
      
      QSize GLWidget::sizeHint() const
      {
        return(QSize(800, 450));
      }
      
      void GLWidget::rotateBy(int xAngle, int yAngle, int zAngle)
      {
        xRot += xAngle;
        yRot += yAngle;
        zRot += zAngle;
        update();
      }
      
      void GLWidget::setClearColor(const QColor &color)
      {
        clearColour = color;
        update();
      }
      
      // Run once when widget is set up
      void GLWidget::initializeGL()
      {
        initializeOpenGLFunctions();
      
        glEnable(GL_DEPTH_TEST);
        // glEnable(GL_CULL_FACE);
      
      #define PROGRAM_VERTEX_ATTRIBUTE 0
      #define PROGRAM_TEXCOORD_ATTRIBUTE 1
      
        QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);
        const char *vsrc =
            "attribute highp vec4 vertex;\n"
            "attribute mediump vec4 texCoord;\n"
            "varying mediump vec4 texc;\n"
            "uniform mediump mat4 matrix;\n"
            "void main(void)\n"
            "{\n"
            "    gl_Position = matrix * vertex;\n"
            "    texc = texCoord;\n"
            "}\n";
        vshader->compileSourceCode(vsrc);
      
        QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);
        const char *fsrc =
            "uniform sampler2D texture;\n"
            "varying mediump vec4 texc;\n"
            "void main(void)\n"
            "{\n"
            "    gl_FragColor = texture2D(texture, texc.st);\n"
            "}\n";
        fshader->compileSourceCode(fsrc);
      
        program = new QOpenGLShaderProgram;
        program->addShader(vshader);
        program->addShader(fshader);
        program->bindAttributeLocation("vertex", PROGRAM_VERTEX_ATTRIBUTE);
        program->bindAttributeLocation("texCoord", PROGRAM_TEXCOORD_ATTRIBUTE);
        program->link();
      
        program->bind();
        program->setUniformValue("texture", 0);
      }
      
      void GLWidget::paintGL()
      {
        glClearColor(clearColour.redF(), clearColour.greenF(), clearColour.blueF(), clearColour.alphaF());
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      
        QMatrix4x4 m;
      
        m.ortho(0.0f, +1.0f, v_aspect, 0.0f, 4.0f, 15.0f);
        m.translate(0.0f, 0.0f, -5.0f);
      
        m.rotate(xRot / 16.0f, 1.0f, 0.0f, 0.0f);
        m.rotate(yRot / 16.0f, 0.0f, 1.0f, 0.0f);
        m.rotate(zRot / 16.0f, 0.0f, 0.0f, 1.0f);
      
        program->setUniformValue("matrix", m);
        program->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);
        program->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE);
        program->setAttributeBuffer(PROGRAM_VERTEX_ATTRIBUTE, GL_FLOAT, 0, 3, 5 * sizeof(GLfloat));
        program->setAttributeBuffer(PROGRAM_TEXCOORD_ATTRIBUTE, GL_FLOAT, 3 * sizeof(GLfloat), 2, 5 * sizeof(GLfloat));
      
        if(hasTexture)
        {
          frame_texture->bind();
          glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
        }
      }
      
      void GLWidget::resizeGL(int width, int height)
      {
        glViewport(0, 0, width, height);
      }
      
      void GLWidget::mousePressEvent(QMouseEvent *event)
      {
        lastPos = event->pos();
      }
      
      void GLWidget::mouseMoveEvent(QMouseEvent *event)
      {
        int dx = event->x() - lastPos.x();
        int dy = event->y() - lastPos.y();
      
        if (event->buttons() & Qt::LeftButton) {
            rotateBy(8 * dy, 8 * dx, 0);
        } else if (event->buttons() & Qt::RightButton) {
            rotateBy(8 * dy, 0, 8 * dx);
        }
        lastPos = event->pos();
      }
      
      void GLWidget::mouseReleaseEvent(QMouseEvent * /* event */)
      {
        emit clicked();
      }
      
      void GLWidget::makeObject()
      {
        static const float coords[4][3] = {
          { 1.0f, v_aspect, 0.0f },
          { 0.0f, v_aspect, 0.0f },
          { 0.0f, 0.0f,     0.0f },
          { 1.0f, 0.0f,     0.0f }
        };
      
        QVector<GLfloat> vertData;
        for(int j = 0; j < 4; ++j)
        {
          // vertex position
          vertData.append(1.0 * coords[j][0]);
          vertData.append(1.0 * coords[j][1]);
          vertData.append(1.0 * coords[j][2]);
      
          // texture coordinate
          vertData.append(j == 0 || j == 3);
          vertData.append(j == 0 || j == 1);
        }
      
        vbo.create();
        vbo.bind();
        vbo.allocate(vertData.constData(), vertData.count() * sizeof(GLfloat));
      }
      
      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved