2013年12月15日日曜日

Qt5/QML2でteapot: まともにglutSolidTeapotできるよう修正しました

先日公開した「C++ Advent Calendar 2013-12-14: Qt5/QML2でteapot」の末尾で触れていた実は glutSolidTeapot するとみょんな事になるバグを修正しました。


左が昨日やっつけてしまった時に確認されたバギーなレンダリング挙動。右はこの記事で修正した結果です。

結論を先に書くと、原因は QOpenGLFramebufferObjectで生成した FBO に OpenGL の生の C API で言うところの GL_RENDERBUFFER を生成して bind して居なかった事でした。

ソースコードの修正は、

fbo = new QOpenGLFramebufferObject(width(), height());

fbo = new QOpenGLFramebufferObject(width(), height(), QOpenGLFramebufferObject::Depth);


commit: https://github.com/usagi/qml2teapot/commit/b570eefa1f8d9eb313a9a4c75b174a4ea387869b

基本的にはこれだけです。

少し解説すると、 OpenGLでFramebuffer-object を扱う際に、深度やステンシルについて扱いたい場合には Renderbuffer-object を生成して、ともに bind する必要があります。

Qt5ではFBO/RBOの取り扱いを QOpenGLFramebufferObject 型に集約してラップしていて、コンストラクターでRBOの有無と取り扱いを第3パラメーターとして設定できるようになっています。 bind 処理は QOpenGLFramebufferObject::bind を呼び出すと自動的にFBOとRBOの bind を処理してくれます。

参考:


(おまけ: どうして気付かなかった?)

仕様の確認不足の一言(;´∀`)

レンダリングの異常を見た時、実はテスト用の書きなぐったコードでは glEnable(GL_DEPTH_TEST) は実装していて、QOpenGLFramebufferObjectはデフォルトでデプス・ステンシルバッファーも有効な便利なやつなはず…、コンストラクターで指定できるのはwidthとheightとフォーマットだけだ、なんて勝手に思い込んでコードを書いてしまっていたのでした。

そんな次第で、面法線の向き(glFrontFace)やカリング(glCullFace)、或いは深度比較関数(glDepthFunc)が何故か逆転した世界になっているのではないか、それらが複合的に関与しているのではないか、GLのレンダリングステートのリセットに問題があり照明の計算に何か不具合が生じているのではないか、いっそのことGLSLを書いて確実にレンダリング処理を規定してしまおうか、あれあれ、でももう時間が残って居ないよ・・・?

それで急遽 glutWireTeapot で誤魔化しつつ、修正は後で書きますごめんなさいーになりました。

いやはや、にんげんもうさぎも納期に追われて焦るとダメですね・w・

0 件のコメント:

コメントを投稿