QOpenGLWindow 、QOpenGLWidget 和 QPainter混合渲染方法初探

来源:互联网 发布:淘宝卖家开通花呗设置 编辑:程序博客网 时间:2024/04/29 21:16

该方法不存在普遍性。别按照此方法了


我用的是OpenGL 3.3 ,Qt 5.4.0

先说QWindow 和 QPainter 结合,这个Qt有现成的例子。就是 那个openglWindow那个例子。

这个基本直接照搬代码:

.h

#include <QSurfaceFormat>#include <QOpenGLContext>#include <QOpenGLShaderProgram>#include <QTimer>class OpenGLWindow : public QWindow,protected QOpenGLFunctions_3_3_Core{    Q_OBJECTpublic:    OpenGLWindow(QWindow *parent = 0);    ~OpenGLWindow();    virtual void render();    virtual void initialize();public slots:    void renderLater();    void renderNow();protected:    bool event(QEvent *event) Q_DECL_OVERRIDE;    void exposeEvent(QExposeEvent *event) Q_DECL_OVERRIDE;private:    bool m_update_pending;    bool m_animating;    QOpenGLContext *m_context;    QOpenGLPaintDevice *m_device;    QOpenGLBuffer * vbo;    QOpenGLVertexArrayObject * vao;    QOpenGLShaderProgram *m_program;    QTimer * timer;    float frame;};#endif // OPENGLWINDOW_H

.cpp

#include "openglwindow.h"#include <QCoreApplication>#include <QMatrix4x4>static const char *vertexShaderSource =    "#version 330 core \n"    "in vec4 posAttr;\n"    "uniform mat4 matrix;\n"    "void main() {\n"    "   gl_Position = matrix * posAttr;\n"    "}\n";static const char *fragmentShaderSource =    "#version 330 core \n"    "out vec4 col;\n"    "void main() {\n"    "   col = vec4(1.0f,0.0f,0.0f,1.0f);\n"    "}\n";OpenGLWindow::OpenGLWindow(QWindow *parent)    : QWindow(parent), m_update_pending(false)    , m_context(0)    , m_device(0){    setSurfaceType(QWindow::OpenGLSurface);    QSurfaceFormat format;    format.setDepthBufferSize(24);    //format.setVersion(3,3);    format.setProfile(QSurfaceFormat::CoreProfile);    setFormat(format);    timer = new QTimer;    connect(timer,SIGNAL(timeout()),this,SLOT(renderNow()));    timer->start(50);    frame =0 ;//    m_context = new QOpenGLContext;//    m_context->setFormat(format);//    m_context->create();}OpenGLWindow::~OpenGLWindow(){}void OpenGLWindow::initialize(){    m_program = new QOpenGLShaderProgram(this);    m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);    m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);    m_program->link();}void OpenGLWindow::render(){    m_program->bind();    QMatrix4x4 matrix;    matrix.perspective(60.0f, float(width())/float(height()), 0.1f, 100.0f);    matrix.rotate(frame, 0, 1, 0);    GLfloat vertices[] = {        0.0f, 0.707f,-1.0f,1.0f,        -0.5f, -0.5f,-1.0f,1.0f,        0.5f, -0.5f,-1.0f,1.0f    };    glClearColor(0.5f,0.5f,0.5f,1.0f);    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);    QOpenGLVertexArrayObject vao;    vao.create();    vao.bind();    QOpenGLBuffer vertex;    vertex.create();    vertex.bind();    vertex .setUsagePattern(QOpenGLBuffer::StaticDraw);    vertex.allocate(vertices,sizeof(vertices));    m_program->enableAttributeArray(0);    m_program->setAttributeBuffer(0,GL_FLOAT,0,4,0);    m_program->setUniformValue("matrix",matrix);    glDrawArrays(GL_TRIANGLES, 0, 3);    frame++;}void OpenGLWindow::renderLater(){    if (!m_update_pending) {        m_update_pending = true;        QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));    }}bool OpenGLWindow::event(QEvent *event){    switch (event->type()) {    case QEvent::UpdateRequest:        m_update_pending = false;        renderNow();        return true;    default:        return QWindow::event(event);    }}void OpenGLWindow::exposeEvent(QExposeEvent *event){    Q_UNUSED(event);    if (isExposed())        renderNow();}void OpenGLWindow::renderNow(){    if (!isExposed())        return;    bool needsInitialize = false;    if (!m_context) {        m_context = new QOpenGLContext(this);        m_context->setFormat(requestedFormat());        m_context->create();        needsInitialize = true;    }    m_context->makeCurrent(this);    if (needsInitialize) {        initializeOpenGLFunctions();        initialize();    }    if (!m_device)        m_device = new QOpenGLPaintDevice;     m_device->setSize(size());    QPainter painter(m_device);    painter.beginNativePainting();    render();    painter.endNativePainting();    QPen pen;    pen.setColor(Qt::green);    painter.setPen(pen);    painter.setFont(QFont("微软雅黑"));    painter.drawText(20,50,"frame:"+QString::number(frame));    painter.drawEllipse(100,100,50,80);    painter.end();    m_context->swapBuffers(this);    QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));}



2 QOpenGLWidget 和 QOpenGLWindow


这个我原来按照一篇博客 叫“

Qt Weekly #20: Completing the offering: QOpenGLWindow and QRasterWindow

结果总是不成功,多方发帖询问未果。


后来自己研究了下,基本实现了混合渲染,但是有个缺点就是只能在OpenGL上面绘制图形。具体做法:


那个Qt博客中说,只要在虚函数paintGL()中写上QPainter,然后就可以混合渲染了,但是我按照他的做法没有成功过。我的做法是不再重写 paintGL(),而是重写paintEvent()。

原来的paintEvent()是会自动调用paintGL()的,重写以后的paintEvent如下代码:

void Render::paintEvent(QPaintEvent *e){    makeCurrent();    paintGL();    QPainter pter(this);    QImage pic;    pic.load("../Select/timg.jpg");    pter.setPen(Qt::blue);    pter.drawText(20,50,"This is a Text!");    pter.drawEllipse(80,100,40,50);    pter.drawImage(200,40,pic);    pter.end();    update();}

paintGL()中还是OpenGL代码。


其次还要注意的时,在类中构造函数中要设置好 format,我试着加入format的版本信息

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


但是这样会导致QPainter不起作用。我是在main函数中设置的全局format。


QOpenGLWindow 和 QOpenGLWidget 实现是一样的,就是继承的时候换一下就可以。具体代码在下面的连接可以下载。

我只是初步探索一下,肯定很多不足的地方,如果有更好的方法,记得分享呀。

QOpenGLWindow QPainter混合代码



0 0
原创粉丝点击