Qt5下OpenGL程序的新写法

Wesley13
• 阅读 780

在Qt5中,引入了QOpenGL*系列类,以取代Qt4时代的QGL*系列类。

下面是从Qt5例子中抠出的两种OpenGL程序模板,方便参考。

第一种写法:

#ifndef TRIANGLEWINDOW_H
#define TRIANGLEWINDOW_H

#include <QWindow>
#include <QOpenGLFunctions>

class QPainter;
class QOpenGLContext;
class QOpenGLPaintDevice;

class TriangleWindow : public QWindow, protected QOpenGLFunctions
{
    Q_OBJECT
public:
    explicit TriangleWindow(QWindow *parent = 0);
    ~TriangleWindow();
    
    virtual void render(QPainter *);
    virtual void render();
    virtual void initialize();
    
public slots:
    void renderNow();

protected:
    void exposeEvent(QExposeEvent *);
    void resizeEvent(QResizeEvent *);

private:
    bool m_update_pending;

    QOpenGLContext *m_context;
    QOpenGLPaintDevice *m_device;
    
};

#endif // TRIANGLEWINDOW_H

实现代码如下:

#include "trianglewindow.h"

#include <QCoreApplication>
#include <QPainter>
#include <QOpenGLContext>
#include <QOpenGLPaintDevice>

TriangleWindow::TriangleWindow(QWindow *parent) :
    QWindow(parent)
  , m_update_pending(false)
  , m_context(0)
  , m_device(0)
{
    setSurfaceType(QWindow::OpenGLSurface);
}

TriangleWindow::~TriangleWindow()
{
    delete m_device;
}

void TriangleWindow::render(QPainter *painter)
{
    Q_UNUSED(painter);
}

void TriangleWindow::render()
{
    if (!m_device)
        m_device = new QOpenGLPaintDevice;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    m_device->setSize(size());

    QPainter painter(m_device);
    render(&painter);
}

void TriangleWindow::initialize()
{
    glClearColor(1, 0, 0, 1);
}

void TriangleWindow::renderNow()
{
    if (!isExposed())
        return;

    m_update_pending = false;

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

    render();

    m_context->swapBuffers(this);
}

void TriangleWindow::exposeEvent(QExposeEvent *event)
{
    Q_UNUSED(event);

    if (isExposed())
        renderNow();
}

void TriangleWindow::resizeEvent(QResizeEvent *event)
{
    Q_UNUSED(event);

    if (isExposed())
        renderNow();
}

main方法:

#include "trianglewindow.h"

#include <QGuiApplication>

int main(int argc, char **argv)
{
    QGuiApplication app(argc, argv);

    QSurfaceFormat format;
    format.setSamples(4);

    TriangleWindow window;
    window.setFormat(format);
    window.resize(640, 480);
    window.show();

    return app.exec();
}

另一种写法:

#ifndef TRIANGLEWINDOW_H
#define TRIANGLEWINDOW_H

#include <QWindow>

class QOpenGLContext;

class Renderer : public QObject
{
    Q_OBJECT
public:
    explicit Renderer(const QSurfaceFormat &format, Renderer *share = 0, QScreen *screen = 0);
    QSurfaceFormat format() const { return m_format; }

public slots:
    void render(QSurface *surface, const QColor &color, const QSize &viewSize);

private:
    void initialize();

    bool m_initialized;
    QSurfaceFormat m_format;
    QOpenGLContext *m_context;
};

class TriangleWindow : public QWindow
{
    Q_OBJECT
public:
    explicit TriangleWindow(const QSharedPointer<Renderer> &renderer);
    
signals:
    void needRender(QSurface *surface, const QColor &color, const QSize &viewSize);

private slots:
    void render();

protected:
    void exposeEvent(QExposeEvent *);

private:
    const QSharedPointer<Renderer> m_renderer;
};

#endif // TRIANGLEWINDOW_H

实现文件:

#include "trianglewindow.h"

#include <QOpenGLContext>

Renderer::Renderer(const QSurfaceFormat &format, Renderer *share, QScreen *screen)
    : m_initialized(false)
    , m_format(format)
{
    m_context = new QOpenGLContext(this);
    if (screen)
        m_context->setScreen(screen);
    m_context->setFormat(format);
    if (share)
        m_context->setShareContext(share->m_context);
    m_context->create();
}

TriangleWindow::TriangleWindow(const QSharedPointer<Renderer> &renderer)
    : m_renderer(renderer)
{
    setSurfaceType(QWindow::OpenGLSurface);
    setFlags(Qt::Window | Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint);

    setGeometry(QRect(10, 10, 640, 480));

    setFormat(renderer->format());

    create();

    connect(this, SIGNAL(needRender(QSurface *, const QColor &, const QSize &)),
            renderer.data(), SLOT(render(QSurface *, const QColor &, const QSize &)));

}

void TriangleWindow::exposeEvent(QExposeEvent *)
{
    render();
}

void TriangleWindow::render()
{
    if (isExposed())
        emit needRender(this, QColor(255, 0, 0), size());
}

void Renderer::render(QSurface *surface, const QColor &color, const QSize &viewSize)
{
    if (!m_context->makeCurrent(surface))
        return;

    if (!m_initialized) {
        initialize();
        m_initialized = true;
    }

    glViewport(0, 0, viewSize.width(), viewSize.height());

    glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF());
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    m_context->swapBuffers(surface);

}

void Renderer::initialize()
{
    glClearColor(0.1f, 0.1f, 0.2f, 1.0f);
}

main方法:

#include "trianglewindow.h"

#include <QGuiApplication>

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

    QSurfaceFormat format;
    format.setDepthBufferSize(16);
    format.setSamples(4);

    QSharedPointer<Renderer> renderer(new Renderer(format));
    TriangleWindow *window = new TriangleWindow(renderer);
    window->resize(640, 480);
    window->setVisible(true);

    return app.exec();
}

在Qt5,推荐使用QOpenGL*系列的类。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
3年前
Nginx反向代理upstream模块介绍
!(https://oscimg.oschina.net/oscnet/1e67c46e359a4d6c8f36b590a372961f.gif)!(https://oscimg.oschina.net/oscnet/819eda5e7de54c23b54b04cfc00d3206.jpg)1.Nginx反
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这