QtとC++でモダンなOpenGLプログラムを書いてみる

shaderを基本としたモッダーンなOpenGLプログラムをQtとC++で書こうって話。Qt5.9を使ってますが5.7あたりでもいけるんじゃないでしょうか。compute shaderがサポートされたのは5.9からのような気もしますが、別にQOpenGLFunctions_4_3_Coreとか使えばそれ以前からも使えないことはない…まあ、そのへんはいいか。

QtでOpenGLを使うと良い点と言えば、とりあえず色んな環境で動くようにコンパイルできることとか、ウィンドウ操作周りやらマウス入力系等をQt一式に任せられるとか、おなじみsignal/slotでのコードが書けるとか、まあ色々ありますが、個人的にQt大好きっ子ですので「かっこいい」が一番ですかねえ。
と言うことで、QtっぽくOpenGLのコードを書くぜーと言う感じでGo。

QOpenGLWidgetを使う

以前はQGLWidgetとかだったような感じですが、QOpenGLWidgetを使うとQOpenGL軍団を使えるWidgetを作ることが出来る素晴らしい。
基本的にこの上に色々実装していくことになりましょうが、とりあえずオーバーロードしておくところとしては、

  • QOpenGLWidget::initializeGL()
  • QOpenGLWidget::paintGL()
  • QOpenGLWidget::resizeGL(int width,int height)

この辺ですねえ。まあ内容は名前の通りです。

OpenGLのfunctionsを使う

QOpenGLWidgetにQOpenGLFunctions〜…的なクラスを多重継承させることでOpenGLの関数、glほげほげ()とかが使えるようになるのね。Qt的なコードを書くのであればあまり使いたくは無いところだけど、glDrawElements()とかがこれに該当してたような気がしますので結局使わないと、と言う感じなんでしょうか。

initializeGL()内でinitializeOpenGLFunctions()を忘れずに呼んでおく。

VertexArrayObjectを使う

QOpenGLVertexArrayObjectをnewしてcreate()してbind()して、間で処理してrelease()する。呼び出しはbind()するだけ。うっは簡単ですね。

VertexBuffer/IndexBufferを使う

QOpenGLBufferをnewして使う。new時にVertexBufferかIndexBufferか指定して例によってcreate()してbind()して使う。setUsagePattern()でバッファの使い方を指定してやれる。

データの流し込みはallocate()で。

Shaderを使う

Shaderに関してはQOpenGLShaderProgramってのがあるので、使う。Vertex、Fragment、Geometry、Compute、Tessellation周りもあるね。これらShaderをひとまとめに管理できる。

addShaderFromSourceFile()なんて見たままのメソッドもあってわかりやすいです。link()してbind()して使う。

Shaderに値を渡したりするにはsetUniformValue()とかでShaderの変数と関連付ける。

Texture使う

これ!、これめっさ便利。QImageから直接テクスチャ作れます。

QOpenGLTextureを使う。イメージを読み込んでおいて、bind()。これだけー。

行列計算をCPUでする

Shaderでやれ?でもあると便利。QMatrix4x4を使う。名前の通り4×4の行列を処理できる型なのだけど、メソッドにtranslate()やらrotate()やらlookAt()やらいかにも便利そうなものが揃ってる。

    m_model.translate(QVector3D(0.0, 0.0, -4.0));
    m_model.rotate(angle,1.0,0);
    m_view = QMatrix4x4();
    m_view.lookAt(QVector3D(0.0, 2.0, 0.0),QVector3D(0.0, 0.0, -4.0),QVector3D(0.0, 1.0, 0.0));
    m_modelViewProjection = m_projection * m_view * m_model;

こんな感じのことが簡単にできる。glm使わなくて良い感じですか。

描画する

initializeGL()でVAOにまとめてあればpaintGL()でやることはあんまりない。

    m_vertexArrayObject->bind();
    m_texture->bind();
    glDrawElements(GL_TRIANGLES, m_indexBuffer->size()/sizeof(ushort), GL_UNSIGNED_SHORT, 0);
    m_vertexArrayObject->release();

ビュー関連を除けばこれくらい。

書く

イメージからメッシュを作りくるくる回すプログラムが、250行くらいで書ける。

QTimer::singleShotとか使ってアニメーションもできる。基本的にQtに元々備わってるものは使っていけると思って問題なさげ。勿論、shaderのソースやテクスチャをリソースにぶち込むこともできるので書きやすく管理しやすい。

結論

楽しいし楽だぞ!。

 

コメントを残す