Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
152 views
in Technique[技术] by (71.8m points)

c++ - How to use QPainter with OpenGL 3.3 format?

I'm trying to use QPainter in my QOpenGLWidget. But it only works with 3.0 OpenGL version. What is the problem?

Here is my code.

#include <QApplication>
#include <QMainWindow>
#include "window.h"

int main(int argc, char *argv[])
{
  QApplication app(argc, argv);

  QSurfaceFormat format;

  format.setRenderableType(QSurfaceFormat::OpenGL);
  format.setProfile(QSurfaceFormat::CoreProfile);
  format.setVersion(3,3);

  // Set widget up
   Window *widget = new Window;
   widget->setFormat(format);

  // Set the window up
  QMainWindow window;
  window.setCentralWidget(widget);
  window.resize(QSize(800, 600));
  window.show();

  return app.exec();
}

If i'll comment "format.setVersion(3,3);" everything will work fine. But my shaders won't start up.

And QOpenGLWidget subclass

#ifndef WINDOW_H
#define WINDOW_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions>

class QOpenGLShaderProgram;

class Window : public QOpenGLWidget,
               protected QOpenGLFunctions
{
  Q_OBJECT

// OpenGL Events
public:

  void initializeGL();
  void resizeGL(int width, int height);
  void paintGL();

};

#endif // WINDOW_H

and simpliest example.

#include "window.h"
#include <QDebug>
#include <QString>
#include <QOpenGLShaderProgram>
#include "vertex.h"
#include <QPainter>


void Window::initializeGL()
{}

void Window::resizeGL(int width, int height)
{}

void Window::paintGL()
{
      QPainter p(this);
      p.setPen(Qt::red);
      p.drawLine(rect().topLeft(), rect().bottomRight());
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I just had the same problem. Basically, QPainter is designed to work with OpenGL ES 2.0. The 3.3 Core desktop OpenGL profile is not compatible with ES 2.0. If you use the 3.3 core OpenGL profile then you cannot use QPainter with it (at least not on OS X).

The issue is however apparently being worked on (https://codereview.qt-project.org/#/c/166202/). So perhaps next release this will be possible.

Currently, the way to get around this is to use QPainter to draw to a QImage and then draw that image as a texture in OGL.

Here is a proof of concept I just put together. In production code don't do this. Setup a shader + VAO (with VBO attached) for a quad. Then use glDrawArrays with an appropriate transform to put the texture on screen.

    glClearColor(1.f,1.f,1.f,1.f);
    glClear(GL_COLOR_BUFFER_BIT);

    // Use QPainter to draw to a QImage and then display the QImage

    QFont f{"Helvetica",18};
    QStaticText txt{msg};
    txt.prepare({},f);
    auto dims = txt.size().toSize();

    QImage buffer(dims,QImage::Format_ARGB32);
    {
        QPainter p(&buffer);
        p.fillRect(QRect{{0,0},dims},QColor::fromRgb(255,255,255));
        p.setPen(QColor::fromRgb(0,0,0));
        p.setFont(f);
        p.drawStaticText(0,0,txt);
    }

    // Blit texture to screen
    // If you at all care about performance, don't do this!
    // Create the texture once, store it and draw a quad on screen.
    QOpenGLTexture texture(buffer,QOpenGLTexture::DontGenerateMipMaps);

    GLuint fbo;
    glGenFramebuffers(1,&fbo);
    glBindFramebuffer(GL_READ_FRAMEBUFFER,fbo);

    texture.bind();
    glFramebufferTexture2D(
        GL_READ_FRAMEBUFFER,
        GL_COLOR_ATTACHMENT0,
        GL_TEXTURE_2D,
        texture.textureId(),
        0);

    glBlitFramebuffer(
        0,
        dims.height(),
        dims.width(),
        0,
        width() / 2 - dims.width() / 2,
        height() / 2 - dims.height() / 2,
        width() / 2 + dims.width() / 2,
        height() / 2 + dims.height() / 2,
        GL_COLOR_BUFFER_BIT,
        GL_LINEAR);

    glDeleteFramebuffers(1,&fbo);

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...