NeHe-OpenGL-Qt5是用到QWindow和QOpenGLFunctions。
而OpenGLFunctions是OpenGL ES 2.0。
OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准。
OpenGL ES 是从 OpenGL 裁剪的定制而来的,去除了glBegin/glEnd,四边形(GL_QUADS)、多边形(GL_POLYGONS)等复杂图元等许多非绝对必要的特性。经过多年发展,现在主要有两个版本,OpenGL ES 1.x 针对固定管线硬件的,OpenGL ES 2.x 针对可编程管线硬件。OpenGL ES 1.0 是以 OpenGL 1.3 规范为基础的,OpenGL ES 1.1 是以 OpenGL 1.5 规范为基础的,它们分别又支持 common 和 common lite两种profile。lite profile只支持定点实数,而common profile既支持定点数又支持浮点数。 OpenGL ES 2.0 则是参照 OpenGL 2.0 规范定义的,common profile发布于2005-8,引入了对可编程管线的支持。 [1]
OpenGL ES 还有一个safety-critical profile。
Qt5.13.0下的OpenGL例子都是继续了QOpenGLWindow。
而QGLWidget类尽量不要用了,它归到legacy传统中了。如果硬件不支持新的可以试一下。
代码:
Lesson01_CreateWindow.pro
#-------------------------------------------------
#
# Project created by QtCreator 2014-06-09T11:37:36
#
# Modify by LINYOUBIAO 2021-02-11 15:43:00
#
#-------------------------------------------------
#为什么不用添加opengl和相关的lib了 ???
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
#输出目标位置
target.path = E:/home/pi/NeHe_OpenGL_Qt5
#生成对象名称
TARGET = Lesson01_CreateWindow
INSTALLS += target
TEMPLATE = app
SOURCES += main.cpp \
openglwindow.cpp
HEADERS += \
openglwindow.h
openglwindow.h
#ifndef OPENGLWINDOW_H
#define OPENGLWINDOW_H
#include <QWindow>
#include <QOpenGLFunctions>
#include <QCoreApplication>
#include <QEvent>
#include <QResizeEvent>
#include <QKeyEvent>
#include <QMatrix4x4>
// QWindow
// The QWindow class represents a window in the underlying windowing system.
// Header: #include<QWindow>
// qmake: QT += qui
// Since: Qt 5.0
// inherits: QObject and QSurface
// inherited By: QPaintDeviceWindow, QQuickWindow, and QVulkanWindow
//
// Protected Functions
// virtual void exposeEvent(QExposeEvent *ev)
// virtual void focusInEvent(QFocusEvent *ev)
// virtual void focusOutEvent(QFocusEvent *ev)
// virtual void hideEvent(QHideEvent *ev)
// virtual void keyPressEvent(QKeyEvent *ev)
// virtual void keyReleaseEvent(QKeyEvent *ev)
// virtual void mouseDoubleClickEvent(QMouseEvent *ev)
// virtual void mouseMoveEvent(QMouseEvent *ev)
// virtual void mousePressEvent(QMouseEvent *ev)
// virtual void mouseReleaseEvent(QMouseEvent *ev)
// virtual void moveEvent(QMoveEvent *ev)
// virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result)
// virtual void resizeEvent(QResizeEvent *ev)
// virtual void showEvent(QShowEvent *ev)
// virtual void tabletEvent(QTabletEvent *ev)
// virtual void touchEvent(QTouchEvent *ev)
// virtual void wheelEvent(QWheelEvent *ev)
// QOpenGLFunctions
// The QOpenGLFunctions class provides cross-platform access to the OpenGL ES 2.0 API.
// Header: #include<QOpenGLFunctions>
// qmake: QT += qui
// Since: Qt 5.0
// Inherited By: QOpenGLExtraFunctions
class OpenGLWindow : public QWindow, protected QOpenGLFunctions
{
Q_OBJECT
public:
explicit OpenGLWindow(QWindow *parent = 0);
~OpenGLWindow();
void setAnimating(bool animating);
public slots:
void renderLater();
void renderNow();
protected:
// Override this to handle any event (ev) sent to the window. Return true if the event was recognized and processed.
//
// Remember to call the base class version if you wish for mouse events, key events, resize events,
// etc to be dispatched as usual.
bool event(QEvent *event);
// The expose event (ev) is sent by the window system whenever an area of the window is invalidated,
// for example due to the exposure in the windowing system changing.
void exposeEvent(QExposeEvent *event);
// Override this to handle resize events (ev).
//
// The resize event is called whenever the window is resized in the windowing system,
// either directly through the windowing system acknowledging a setGeometry() or resize() request,
// or indirectly through the user resizing the window manually.
void resizeEvent(QResizeEvent * event);
// Override this to handle key press events (ev).
void keyPressEvent(QKeyEvent * event);
// 定义render虚函数,用于渲染
virtual void render();
// 定义initialize虚函数,用于初始化
virtual void initialize();
// 定义resizeGL虚函数,用于缩放事件
virtual void resizeGL(int w, int h);
QMatrix4x4 m_projection;
QMatrix4x4 m_modelView;
private:
// 等待
bool m_update_pending;
// 动画
bool m_animating;
// 上下文
// QOpenGLContext
// The QOpenGLContext class represents a native OpenGL context, enabling OpenGL rendering on a QSurface.
// Header: #include<QOpenGLContext
// qmake: QT += gui
// Since: Qt 5.0
// Inherits: QObject
QOpenGLContext *m_context;
// 是否全屏显示
bool m_show_full_screen;
};
#endif // OPENGLWINDOW_H
openglwindow.cpp
#include "openglwindow.h"
OpenGLWindow::OpenGLWindow(QWindow *parent) :
QWindow(parent),
m_update_pending(false),
m_animating(false),
m_context(NULL),
m_show_full_screen(false)
{
// Sets the surfaceType of the window.
//
// Specifies whether the window is meant for raster rendering with QBackingStore,
// or OpenGL rendering with QOpenGLContext.
// Specifies whether the window is meant for raster rendering with QBackingStore, or OpenGL rendering with QOpenGLContext.
//
// The surfaceType will be used when the native surface is created in the create() function.
// Calling this function after the native surface has been created requires calling destroy() and create()
// to release the old native surface and create a new one.
setSurfaceType(QWindow::OpenGLSurface);
resize(640, 480);
}
OpenGLWindow::~OpenGLWindow()
{
}
void OpenGLWindow::render()
{
}
void OpenGLWindow::initialize()
{
}
void OpenGLWindow::resizeGL(int w, int h)
{
if(h == 0)
{
h = 1;
}
if (m_context)
{
glViewport(0, 0, w, h);
}
m_projection.setToIdentity();
m_projection.perspective(45, (float)w/float(h), 1, 1000);
m_modelView.setToIdentity();
}
void OpenGLWindow::setAnimating(bool animating)
{
m_animating = animating;
if(animating)
{
renderLater();
}
}
void OpenGLWindow::renderLater()
{
if (!m_update_pending)
{
m_update_pending = true;
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
}
}
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;
}
// Makes the context current in the current thread, against the given surface.
// Returns true if successful; otherwise returns false.
// The latter may happen if the surface is not exposed,
// or the graphics hardware is not available due to e.g. the application being suspended.
m_context->makeCurrent(this);
if (needsInitialize)
{
// Initializes OpenGL function resolution for the current context.
//
// After calling this function, the QOpenGLFunctions object can only be used with the current context and
// other contexts that share with it. Call initializeOpenGLFunctions() again to
// change the object's context association.
initializeOpenGLFunctions();
initialize();
const qreal retinaScale = devicePixelRatio();
resizeGL(width()*retinaScale, height()*retinaScale);
}
render();
// Swap the back and front buffers of surface.
//
// Call this to finish a frame of OpenGL rendering, and make sure to call makeCurrent() again
// before issuing any further OpenGL commands, for example as part of a new frame.
m_context->swapBuffers(this);
if (m_animating)
renderLater();
}
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)
{
if (isExposed())
{
renderNow();
}
QWindow::exposeEvent(event);
}
void OpenGLWindow::resizeEvent(QResizeEvent *event)
{
int w = event->size().width();
int h = event->size().height();
const qreal retinaScale = devicePixelRatio();
resizeGL(w*retinaScale, h*retinaScale);
renderNow();
QWindow::resizeEvent(event);
}
void OpenGLWindow::keyPressEvent(QKeyEvent *event)
{
switch(event->key())
{
// 全屏显示
case Qt::Key_F1:
{
m_show_full_screen = !m_show_full_screen;
if(m_show_full_screen)
{
showFullScreen();
}
else
{
showNormal();
}
break;
}
// 退出
case Qt::Key_Escape:
{
qApp->exit();
break;
}
}
QWindow::keyPressEvent(event);
}
main.cpp
#include <QApplication>
#include <QSurfaceFormat>
#include "openglwindow.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
// QSurface是一个可渲染的抽象类,继承自QOffscreenSurface和QWindow。
QSurfaceFormat format;
// Set the preferred number of samples per pixel when multisampling is enabled to numSamples.
// By default, multisampling is disabled.
format.setSamples(16);
OpenGLWindow window;
// Sets the window's surface format.
// The format determines properties such as color depth, alpha, depth and stencil buffer size, etc.
// For example, to give a window a transparent background (provided that the window system supports compositing,
// and provided that other content in the window does not make it opaque again):
//
// QSurfaceFormat format;
// format.setAlphaBufferSize(8);
// window.setFormat(format);
//
window.setFormat(format);
window.resize(640, 480);
window.show();
window.setAnimating(true);
return app.exec();
}
这是工程代码,加了注释。迟点会上传的。也可以到github上下载。
运行结果:
相关:
QOpenGLFunctions
https://doc.qt.io/qt-5/qopenglfunctions.html#initializeOpenGLFunctions
QWindow
https://doc.qt.io/qt-5/qwindow.html#protected-functions
QSurfaceFormat
https://doc.qt.io/qt-5/qsurfaceformat.html#setSamples
QOpenGLWidget
https://doc.qt.io/qt-5/qopenglwidget.html
Qt OpenGL examples
https://doc.qt.io/qt-5/qtgui-openglwindow-example.html#example-opengl-rendering-sub-class
多谢,亲爱的美美。