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のソースやテクスチャをリソースにぶち込むこともできるので書きやすく管理しやすい。
結論
楽しいし楽だぞ!。