wgld.orgのコードをopenFrameworksで記述する

2017/04/19

glsl, openFrameworks

3Dプログラミングの勉強がてら、@h_doxasさんが運営するwgld.orgのコードをoFで記述してみました。
oFで凝った表現をしようと思ったらおそらくシェーダーと出会うことになるかと思うのですが、oFでは頂点データや座標変換行列を自動的にシェーダーに送信する仕様になっていたり行列を掛け合わせる順番が異なったりとそこそこややこしいと感じたのでまとめておきたいと思います。

こちらがありがたい参考資料。3Dプログラミングにおける基礎知識はどの言語で実装する際にも共通なので、まずはこれらの資料を読んでみてOpenGLでのレンダリングプロセスやモデルデータの描画方法を理解してみることをおすすめします。とても丁寧に解説してくれています。ありがたい。。
wgld.org
床井研究室
独学で 1 ヶ月間 OpenGL を学んで得た基礎知識のまとめ ~ 2D 編 ~
シェーダープログラミングの意義とその実装

こちらが今回のソースコードです。(今後もサンプルは追加する予定。。)
https://github.com/rystylee/oF-wgld

今回の実装ではOpenGLのバージョンを3.2にし、GLSL 150で実装しています。
GLSL 120からGLSL 150への書き換えはこちらを参照してください。
OpenGL 3.2(GLSL 1.50)対応

以下、01-simpleModelのコードを例に簡単に解説を加えたいと思います。

まずは、main.cppです。
OpenGLのバージョンを3.2にしてGLSL 150を使えるように設定しています。

次に、ofApp.hです。
描画するモデル数の定義と各種インスタンスの生成を行っています。
ここではofVboMeshを使用しています。ofMesh、ofVbo、ofVboMeshの違いはこちらのサイトに大変分かりやすくまとまっています。
openFrameworksの3D図形の色々な描画方法

ここからofApp.cpp。まずはsetup()です。
ここでは、深度テストの有効化とシェーダの読み込み、そしてカメラの設定をしています。詳しくはwgld.orgの方を参照してほしいのですが、NearClipとFarClipを指定しています。
Debugの部分はカメラの各種情報の取得方法です。必要に応じて適宜利用してください。

update()は特になにもしていません。時間を取得しているくらい。

肝心のdraw()部分です。

ここでやっていることは、
・画面の初期化
(以下はモデルの個数分繰り返す)
・モデル変換行列・ビュー変換行列・プロジェクション変換行列・モデルビュープロジェクション変換行列の生成
・シェーダーに生成した各種座標変換行列を送信
・モデルの描画
となっています。(モデル変換行列では座標の移動と回転処理を加えています。※処理を行う順番に注意!!!!)

注意しなくてはならないのは、mvpMatrixを生成する際に行列を掛け合わせる順番です。
通常は(行列が列オーダーの場合)mvpMatrixはp*v*mで求まるのですが、oFでの行列ofMatrix4x4は行オーダーであるため掛け合わせる順番が逆になり、m*v*pで求まります。ややこしい。。

oFではshader.begin()とshader.end()で囲んだ部分に何かdrawすれば、その頂点データは自動でシェーダーに送られます。
ここではわかりやすいようにsphereのメッシュを取得してvboMeshに格納し、頂点色を付加して描画しています。
この自動でやってくれる部分、普段は便利なのですが実際に自分で記述しようとしてみるとその仕様を把握するのに少し戸惑ったりしました(僕だけかもしれませんが。。)

しかし、仕様を把握してしまえば簡単に頂点情報を送信できることの恩恵を受けることができます。
中で何をやっているかを理解するの重要!!!

では、vertex shaderです。

vertex shaderではoFから各種座標変換行列と頂点座標・色を受け取り、頂点色は何も処理を加えずそのまま、頂点座標は受け取ったモデルビュープロジェクション行列と掛け合わせてfragment shaderに送信しています。
もちろん、oFから受け取った各種座標変換行列をvertex shader内で掛け合わせることも可能です。目的に応じて使い分けてください。

fragment shaderはさらにシンプルで、受け取った頂点色をそのまま最終的なアウトプットカラーに代入して送信しているだけです。

これで晴れて球体がレンダリングできました。
しかし、ライティング処理を行っていないので非常にのっぺりとしたレンダリング結果になっているかと思います。

他のサンプルではwgld.orgの通りにライティングを行っているので試してみてください!!

ではでは。