Qt OpenGL(二十)——Qt OpenGL 核心模式版本
一、写在前面
在之前的OpenGL教程(1~19)中,采用的方式都是固定渲染管线,也就是OpenGL3.2版本之前的写法,但是OpenGL从3.2版本开始,就鼓励使用核心模式进行开发了,其目的就是为了提高效率,增加编程的灵活性。
从本篇开始,我把核心模式方法的写法分享给大家,主要还是借助以Qt开发。
二、Qt推荐的例程
打开Qt Creator,在Example界面可以搜索到OpenGL相关的例程。
打开Qt creator,可以看到我的Qt版本5.8.0, MinGW的。
搜索OpenGL
如上所示,我们可以看到其中给到的几个例子。
编译运行OpenGL Window Example,可以看到效果:
三、源码
源码部分,主要包含openglwindow.h和openglwindow.cpp文件
#include <QtGui/QWindow>
#include <QtGui/QOpenGLFunctions>
QT_BEGIN_NAMESPACE
class QPainter;
class QOpenGLContext;
class QOpenGLPaintDevice;
QT_END_NAMESPACE
//! [1]
class OpenGLWindow : public QWindow, protected QOpenGLFunctions
{
Q_OBJECT
public:
explicit OpenGLWindow(QWindow *parent = 0);
~OpenGLWindow();
virtual void render(QPainter *painter);
virtual void render();
virtual void initialize();
void setAnimating(bool animating);
public slots:
void renderLater();
void renderNow();
protected:
bool event(QEvent *event) override;
void exposeEvent(QExposeEvent *event) override;
private:
bool m_animating;
QOpenGLContext *m_context;
QOpenGLPaintDevice *m_device;
};
//! [1]
openglwindow.cpp文件内容:
#include "openglwindow.h"
#include <QtCore/QCoreApplication>
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLPaintDevice>
#include <QtGui/QPainter>
//! [1]
OpenGLWindow::OpenGLWindow(QWindow *parent)
: QWindow(parent)
, m_animating(false)
, m_context(0)
, m_device(0)
{
setSurfaceType(QWindow::OpenGLSurface);
}
//! [1]
OpenGLWindow::~OpenGLWindow()
{
delete m_device;
}
//! [2]
void OpenGLWindow::render(QPainter *painter)
{
Q_UNUSED(painter);
}
void OpenGLWindow::initialize()
{
}
void OpenGLWindow::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);
}
//! [2]
//! [3]
void OpenGLWindow::renderLater()
{
requestUpdate();
}
bool OpenGLWindow::event(QEvent *event)
{
switch (event->type()) {
case QEvent::UpdateRequest:
renderNow();
return true;
default:
return QWindow::event(event);
}
}
void OpenGLWindow::exposeEvent(QExposeEvent *event)
{
Q_UNUSED(event);
if (isExposed())
renderNow();
}
//! [3]
//! [4]
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();
}
render();
m_context->swapBuffers(this);
if (m_animating)
renderLater();
}
//! [4]
//! [5]
void OpenGLWindow::setAnimating(bool animating)
{
m_animating = animating;
if (animating)
renderLater();
}
//! [5]
四、核心模式
class OpenGLWindow : public QWindow, protected QOpenGLFunctions
通过上面的代码我们可以看到,这个类继承的父类,其中有:QOpenGLFunctions。
这个类Qt封装了对应的OpenGL的核心模式的函数,版本化的函数包装器针对给定的 OpenGL 版本和配置文件,比如 QOpenGLFunctions_3_2_Core。
QOpenGLFunctions_X_X_Core提供OpenGL X.X版本核心模式的所有功能,是对OpenGL函数的封装。
其中的initializeOpenGLFunctions用于初始化OpenGL函数,将Qt里的函数指针指向显卡的函数,之后调用的OpenGL函数才是可用的。
五、QWindow和QOpenGLWidget
Qt这个例子中,窗口类继承了QWindow,在日常的实际项目中,我们使用更多的是继承QOpenGLWidget类。
QWindow类是Qt5.0之后引入的,QWindow的重绘与QWidget重绘有点不一样,QWindow的没有提供PaintEvent相关的函数。得实现event虚函数,才能实现重绘。
QOpenGLWidget 提供了显示集成到 Qt 应用程序中的 OpenGL 图形的功能。它使用起来非常简单:自定义类继承它并像其他 QWidget 子类一样使用,还可以选择使用 QPainter 和标准 OpenGL 渲染命令。
QOpenGLWidget类提供了三个便捷的虚函数,可以重载,用来重新实现典型的OpenGL任务:
1)paintGL () :渲染OpenGL窗口,当窗口widget需要更新时调用;
2)resize () :设置OpenGL视口、投影等,当widget调整大小(或首次显示)时调用;
3)initializeGL () : 设置OpenGL资源和状态,最先调用且调用一次。
和之前的文章中继承自QGLWidget一样,这三个函数功能也一样。
上一篇:OpenGL(十九)——Qt OpenGL波动纹理(旗子的飘动效果)
下一篇:
本文原创作者:冯一川(ifeng12358@163.com),未经作者授权同意,请勿转载。