Hanaのプログラミング日記

プログラミング関連で勉強したことの記録です。

Qt5でOpenGLを使用する

概要

Qt5でOpenGLを使うにはQOpenGLWidgetクラスとQOpenGLFunctionsクラスを使用します。
今回はプロジェクト作成から画面のクリアまで行います。

f:id:hana1187:20210307190542p:plain
OpenGLで画面を青色で塗りつぶした状態

実行環境

手順

  1. Qt Widget Applicationのプロジェクトの作成
  2. QOpenGLWidgetクラスを継承したGLWidgetクラスの作成
  3. QOpenGLWidgetクラスの関数のオーバーライド
  4. OpenGLのバージョンの指定
  5. 描画部分の作成
  6. GLWidgetをMainWindowにセット

ソースコード

<glwidget.h>

#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions>

class GLWidget : public QOpenGLWidget, public QOpenGLFunctions
{
    Q_OBJECT
public:
    GLWidget(QWidget *parent = nullptr);
    virtual ~GLWidget();

    void initializeGL();
    void paintGL();
    void resizeGL(int w, int h);
};

#endif // GLWIDGET_H

<glwidget.cpp>

#include "glwidget.h"

GLWidget::GLWidget(QWidget *parent) : QOpenGLWidget(parent)
{
}

GLWidget::~GLWidget()
{
}

void GLWidget::initializeGL()
{
    initializeOpenGLFunctions();
}

void GLWidget::paintGL()
{
    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
}

void GLWidget::resizeGL(int w, int h)
{
    Q_UNUSED(w);
    Q_UNUSED(h);
}

<main.cpp>

#include "mainwindow.h"

#include <QApplication>
#include <QSurfaceFormat>

int main(int argc, char *argv[])
{
    QSurfaceFormat fmt;
    fmt.setVersion(4,0);
    QSurfaceFormat::setDefaultFormat(fmt);

    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

<mainwindow.h>

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

<mainwindow.cpp>

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "glwidget.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    GLWidget* glw = new GLWidget(this);
    this->setCentralWidget(glw);
}

MainWindow::~MainWindow()
{
    delete ui;
}

詳細

1. Qt Widget Applicationのプロジェクトの作成

Qt Creatorの「ファイル」→「ファイル/プロジェクトの新規作成」から「Qt Widgets Application」を選択してプロジェクトを作成します。

f:id:hana1187:20210307191609p:plain
Qt Widgets Applicationを選択

2. QOpenGLWidgetクラスを継承したGLWidgetクラスの作成

Qt CreatorでSourcesのところを右クリックして「Add New...」でC++クラスを追加します。

f:id:hana1187:20210307191951p:plain
C++クラスの作成

基底クラスはQWidgetにします。

f:id:hana1187:20210307200700p:plain
基底クラスはQWidget

生成されたGLWidgetクラスはQWidgetクラスを継承しているので、ここをQOpenGLWidgetクラスに書き換えます。また、QOpenGLFunctionsクラスも継承させます。
QOpenGLFunctionsに関してはGLWidgetが所有するようにしてもいいですが、継承した方が便利だったので継承させました。

3. QOpenGLWidgetクラスの関数のオーバーライド

QOpenGLWidgetクラスを使うときは以下の3つの関数をオーバーライドして使います。

  • void initializeGL();
    OpenGLの初期化時に呼ばれる関数。QtでOpenGLの関数を使用するにはQOpenGLFunctionsクラスのinitializeOpenGLFunctions関数を呼ぶ必要がありますので、この初期化のタイミングで呼びます。
  • void paintGL();
    OpenGLの描画時に呼ばれる関数。今回は画面をクリアする関数をここで呼びます。
  • void resizeGL(int w, int h);
    Widgetのサイズが変わったときに呼ばれる関数。引数のwとhにはWidgetの幅と高さが入ります。

4. OpenGLのバージョンの指定

使用するOpenGLのバージョンの指定はQSurfaceFormatクラスのsetDefaultFormat関数で行います。
QtのドキュメントによるとsetDefaultFormat関数はQApplicationを生成する前に呼ぶことが推奨されているので main関数の最初のところで呼びます。

5. 描画

QOpenGLWidgetクラスではOpenGLの描画が必要な時にpaintGL関数が呼ばれます。
ここでglDrawArrays関数などを呼んでポリゴンを描画しますが、今回は画面のクリアだけなので使用しません。

6. GLWidgetをMainWindowにセット

GLWidgetクラスをMainWindowクラスの中で生成し、setCentralWidget関数でセントラルウィジェットに設定します。
setCentralWidgetでウィジェットをセットするとdeleteはMainWindowクラスが行うので、自分でdeleteする必要はありません。


以上です。

QtでOpenGLを使う際にたくさん躓いたので備忘録として書きました。
いろいろと初心者ですので、間違い等ご指摘いただけますと幸いです。