Qt5下OpenGL程序的新写法

在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*系列的类。

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值