一、Windows上的OpenGL库
1、Windows平台,OpenGL库已经包含在Microsoft SDK里了。
2、OpenGL库64位版本的文件名仍然是OpenGL32.Lib,和32位版本一样。
3、Visual Studio项目属性的VC++目录已经配置好了SDK的包含目录、库目录和可执行文件目录,所以OpenGL库的目录就不需要我们配置了,我们只需在链接器的附加依赖项上添加OpenGL32.Lib即可。
4、Qt Creator的pro文件里,只要加入QT += openglwidgets opengl即可。
二、Qt中有QOpenGLWidget,不需要GLFW;有QOpenGLFunctions_X_X_Core,不需要GLAD。
三、QOpenGLWidget
1、QOpenGLWidget提供了三个便捷的虚函数,可以重写,用来重新实现典型的OpenGL任务。
paintGL:渲染OpenGL场景。Widget需要更新时调用。
resizeGL:设置OpenGL视口、投影等。Widget调整大小(或首次显示)时调用。
initializeGL:设置OpenGL资源和状态。第一次调用resizeGL()/paintGL()之前调用一次。
2、如果需要从paintGL()以外的位置触发重新绘制(即重新调用paintGL(),典型示例是使用计时器设置场景动画),则应调用Widget的update()函数来安排更新。
3、调用paintGL()、resizeGL()或initializeGL()时,Widget的OpenGL呈现上下文将变为当前。
如果需要从其它位置(例如,在Widget的构造函数或自己的绘制函数中)调用标准OpenGL API函数,则必须首先调用makeCurrent()。
4、在paintGL()以外的地方调用绘制函数,没有意义,绘制图像最终将被paintGL()覆盖。
四、QOpenGLFunctions_X_X_Core
1、QOpenGLFunctions_X_X_Core提供OpenGLX.X版本核心模式的所有功能。
2、initializeOpenGLFunctions: 初始化和OpenGL API同名的所有函数指针,将这些函数指针指向显卡中真正的OpenGL函数。
五、视口
1、在渲染之前,我们必须告诉OpenGL渲染窗口的尺寸大小(像素),即视口(Viewport)。
2、这样OpenGL才能知道怎样根据视口大小显示数据和坐标,改变帧缓存大小和视口大小一一对应。
3、通过调用glViewport函数来设置视口的维度(Dimension)。
4、可以对窗口区域进行划分,在同一个窗口中显示分割屏幕的效果,以显示多个视图。
5、glViewport前两个参数定义视口矩形左下角的位置(单位像素),接着两个参数定义视口矩形的宽和高(单位像素)。
6、用户改变窗口的大小时,视口也应该被调整。
六、双缓冲(Double Buffer)
1、若应用程序使用单缓冲绘图时,可能会存在图像闪烁的问题。
因为图像不是一下子被绘制出来的,而是按照从左到右、由上而下逐像素绘制而成,这会导致渲染的结果很不真实。
2、应用双缓冲,前缓冲保存着最终输出的图像,它会在屏幕上显示。
所有的渲染指令都会在后缓冲上绘制。
当所有渲染指令执行完毕后,交换前缓冲和后缓冲,图像就立即呈显出来。
七、glClearColor()函数设置清空缓冲所用的颜色。
八、glClear()函数用于清空某个指定的缓冲。
可能的缓冲位为GL_COLOR_BUFFER_BIT、GL_DEPTH_BUFFER_BIT、GL_STENCIL_BUFFER_BIT。
九、代码:
//MyOpenGLWidget.h
#pragma once
//需要的两个头文件
#include <QOpenGLWidget>
#include <QOpenGLFunctions_4_5_Core>
class MyOpenGLWidget: public QOpenGLWidget, QOpenGLFunctions_4_5_Core
{
Q_OBJECT
public:
explicit MyOpenGLWidget(QWidget * parent = nullptr);
protected:
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
};
//MyOpenGLWidget.cpp
#include "MyOpenGLWidget.h"
MyOpenGLWidget::MyOpenGLWidget(QWidget * parent) : QOpenGLWidget(parent)
{
}
void MyOpenGLWidget::initializeGL()
{
//初始化所有指向真正OpenGL API的函数指针, 否则glXXX()会报错。
initializeOpenGLFunctions();
}
void MyOpenGLWidget::resizeGL(int w, int h)
{
}
void MyOpenGLWidget::paintGL()
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
//HelloWindow.h
#pragma once
#include <QMainWindow>
namespace Ui { class HelloWindowClass; };
class HelloWindow : public QMainWindow
{
Q_OBJECT
public:
HelloWindow(QWidget * parent = nullptr);
~HelloWindow();
private:
Ui::HelloWindowClass * ui = nullptr;
};
//HelloWindow.cpp
#include "HelloWindow.h"
#include "ui_HelloWindow.h"
HelloWindow::HelloWindow(QWidget * parent) : QMainWindow(parent)
{
ui = new Ui::HelloWindowClass();
ui->setupUi(this);
//用QOpenGLWidget替代掉中间一层Widget,不需要这个层级关系。
setCentralWidget(ui->openGLWidget);
}
HelloWindow::~HelloWindow()
{
delete ui;
}
HelloWindow.ui
运行结果: