WebGLフレームワークを作る Part2 作ってみる
フレームワークを作るプロセス
フレームワーク作成は基本的に以下のプロセスを繰り返しました。
1. 勉強する。わかったかもという自信。
2. 勉強したことを実践するため、サンプル作成。
3. サンプル作成中のWeGL側のエラー、もしくはエラーがなくても真っ白の画面しか出てこず、どこから着手すればいいのか。心折れそうになる。
4. 勉強資料を読み返す、ひたすらググる、自分の作成しているものに近いサンプル・チュートリアルを探す。
5. サンプルが動くようになり、解決できたという達成感と少しできるかもという希望。
6. 有名なWebGLライブラリのコードを確認・勉強する。
7. ライブラリと自分の今ある状況との埋めがたい距離に絶望する。
8. できるところからやろうと開き直る。
9. サンプルや勉強したライブラリで自分が使えそうな関数やクラス化してこつこつ地道にまとめ・整理する。
10. あまり成長は実感してないけど、とりあえず形にするぞと言う執念(呪い)。そして、1に戻る。
こんな感じで、フレームワーク制作をすすめていきました。
ライブラリのように壮大なビジョンを持つのはやめました。
自分にとってプラスだったのは行列やベクトルを学んでいたことです。
カメラの回転・座標から逆変換でView Matrixを求めるなどの学習にあまり時間を割かずにすすめることができました。
もともと数学好きです。行列やベクトルを使って世界を眺め、モニター上に物体を構築するコンピュータグラフィックスは悠久の浪漫を感じます。
参考・勉強に使用した書籍・サイト
three.jsなどのライブラリを使った書籍やサイトは多いです。
WebGL単体でどのAPIをどうやって使うのか、なぜ使わないといけないのかについて説明している記事・書籍は少ないです。
この本はゼロからWebGL APIについて詳しく解説しています。
詳しすぎて何度も挫折しそうになりました。最初に学んだことなど忘れたりしたので、何度も読み返しました。
下の画像は本にある図解です。
JavaScript上で作成するFloat32Arrayをどうやってattributeとして使用するかを図解しています。
WebGL Fundamentalsはwebglがどうやって動く、shaderとは何かから始まり、2D、3Dをレンダリングしていくと発展していきます。
図解の説明も親切です。上の図解ではvertex shader上でattributeがどのようにしてclipspace上で計算されるのかを図解しています。
WebGL APIの確認、特にWebGL constantsの確認ではよく使います。チュートリアルも充実しています。
日本語だとこちらのサンプルや解説も参考になりました。
WebGL以上にOpenGLのほうが書籍やサイトが多いので、OpenGLのチュートリアルをWebGLに書き直したりして、勉強したりもしています。
参考・勉強にしたWebGLライブラリ
NanoGL
前回の記事でnanoglに衝撃を受けたと書きました。
最初のフレームワークはnanoglをかなり参考にし、作成しました。
githubに書いてある通りmicro frameworksで最小限の7つのファイル(コンポーネント)で構成されています。
1つ1つのコンポーネントも100行未満から多くても300行後半ぐらいと非常にコンパクトです。
サンプルは少ないですが、テストコードをサンプルとして理解できます。WebGL書くのに慣れてないと結構苦行です。
nanogl-pbrのように実践で使えるプラグイン的なnanogl-xxxシリーズが多数存在します。
stack.gl
stackglはオープンコミュニティのメンバーが自由に作成してるでwebglのパッケージコレクションだと理解しています。
基本はWebGLをそのまま書くけど、必要に応じてメンバーそれぞれがパッケージを作成し、公開しています。
軽いノリでゆるく作っている印象です。
コミュニティーは活発で自然と色々なパッケージがあり、勉強するのに参考になります。(最近はあまり活発じゃなく、新しいパッケージが出てこない印象があります。)
stack.glのマイナス面としてコア部分がなく、ふんわりたくさんのパッケージが存在してるところです。
three.jsのような1つのマッチョーライブラリとも違うし、nanoglみたいな自分のための最適なフレームワークというものとも違います。
three.js
WebGLの原点であり、頂点のようなライブラリ。
ほとんどのパーツを内部で管理していて、初心者から上級者まであるゆる人たちがあらゆる用途に応じて使えます。
快適すぎてWebGLとは何か、行列・ベクトルとは何かなどについて知らなくても書けます。それが良いところでもあり、悪いところでもあります。
前回の記事でも書いたとおり50,000行近くのコードがあるので、少しの挙動を理解するのにも一苦労です。
three.js内ではどうやってマテリアル扱っていて、シェーダーをどのタイミングでコンパイルするのかのようにポイントを絞って勉強しました。
サンプル・デモが豊富なので勉強も兼ねてthree.jsのサンプルをwebglに変換します。
以下はガッツリは見てないけど、何回か流し読みしたライブラリ・ツールです。
フレームワークを作ってみる
NanoGLのアイディアをベースに作成することにしました。
NanoGLのアイディアはNanoGLのコア部分をNanoGLで作成し、派生的にプラグインを作成するというものでした。
しかし、ハブとなるリポジトリがなかったり、three.jsのような多機能にしていくとしたら、コアとプラグインの部分がより細分化する必要があるのかなと感じました。
ハブ的なリポジトリで全体を把握し、コアをメインのモジュールとして、サブでコアをサポートし、1つ1つのモジュールを軽量化させるフレームワークにしようと考えました。
NanoGLに対抗して粒GL(TubuGL)と命名しました。
TsubuではなくTubuにしたのは、4文字が収まり良いのと英語圏の人がなんて発音するのかと思ったからです。(ツゥブ(?)みたいな感じで発音していました。)
最初は恐る恐るコア部分を作成し、割と使えそうなカメラ、立方体や球体などのシェープといったサブモジュールを作成していきました。
これまでコアモジュールが3こ、サブモジュールが10個作成しました。
それ以外にもレシピや教室といって興味あることをまとめるリポジトリも作成しました。
これまでに作成したサンプルの一部です。
作ってみた気づいたこと
少しのアップデートに対して、全てのモジュールで動作不良がないか、今まで使ったサンプルは動くかという確認作業が発生しました。
モジュールが別リポジトリなので、メンテナンスがものすごく大変で面倒だということがわかりました。
何でもかんでもクラスにすることに違和感を感じていました。
例えば
var program = new Tubu.Program(gl, vetexShader, fragmentShader)
というように書いたときProgramの中にWebgl APIのgl.createProgram()としてprogramを作成するのは気持ち悪さを感じるようになってきました。
目玉焼きの中に目玉焼きみたいな感じです。味同じやったら目玉1つでいいんじゃないか、毎日それに触れるのは流石に気持ち悪いという感情です。
学んだことをクラスにするというペースでTubuGLを作っていきました。
計画なく増やすことで一気に知識、ノウハウを増やすことができたのはすごいよかったです。
その反面、まとまりがなく、管理が面倒・煩雑になってきました。
新しいフレームワーク(断捨離GL)を制作始めるにあたって
WebGLをわからないなりにおぼろげにわかってきて、俯瞰してまとめるような方向性にしたほうがいんじゃないかと考えました。
一旦TubuGLの開発は中断し、以下の方針で作り直すことを決めました。
・ 基本的に関数メインにする。カメラのような行列とカメラという概念を一致させるときだけにクラスを作成する。
・ スマートなもの(賢そうに見えるもの)より自分がより使いやすいものを作る・アップデートし続ける。
・ リポジトリは1つにまとめる。
サラッと書きましたが個人的には頑張って書いたものに思い入れがありました。それを一度リセットする新しい気持ちと思い入れのものとバイバイする複雑な思いがありました。
次回の記事では現在開発しながら、使用している断捨離 GLついて自分に馴染むツール作りのためにどう開発しているか、javascriptでの開発をtypescriptに変えたか、どう実践に投入するかについて書きたいと思います。