この記事はゲームエンジン・ライブラリ・ツールの開発 Advent Calendar 2016の17日目の記事です。
はじめに
みなさんこんにちは、GLBoost開発者の @emadurandal です。
WebGL界隈をうろついております。
WebGLもようやく再生環境が普及し、どんどん実案件に使われるようになってきました。嬉しいことです。
そうした状況の中で、何かコンテンツを作るにあたり、WebGLのAPIレベルからいちいち叩くのは何かと効率が悪い…。ゲーム業界とかでよくある状況がWebGLの世界でも起きておりまして、今世の中ではThree.jsとかのライブラリが9割以上の案件で使われているという情報もあるとかないとか……。
でも、世の中猫も杓子もThree.jsでは面白くないですね。
Three.jsに負けないライブラリを作りたい、と思い、私、 @emadurandal が作り始めたのがGLBoostです。
GLBoostとは
まずはGithubのプロジェクトサイトをご覧ください。
https://github.com/emadurandal/GLBoost
コンセプトで
"Convenience like Three.js, Infinite Flexibility like raw WebGL, We get both."
(日本語訳)Three.jsのような便利さ、そして生WebGLのような無限の柔軟性。両方取りするぜ!
って感じで強気にぶち上げてますね。まぁ実際にできるのか、についてはなかなか大変ですが、目指すところはそこだったりします。
世にあるWebGLライブラリは、WebGLのローレベルの機能・APIを内部でうまく活用して(隠蔽して)、ユーザーサイドとして本質的に3Dでやりたいことを高級APIを通してできるようにするものが多いです。
なので、便利なんですけど、その点CG研究者やゲーム開発者がやりたいような、レンダリングのいろんな実験とか、レンダリングパイプラインに介入してガリガリカスタマイズするとか、そういうことはやりにくい設計になっていたりするんですね。
そこで、GLBoostでは、便利さは狙いつつも、カスタマイズ性・WebGLとしての柔軟性は手放さない、という設計思想で行こうとしています。
さらに今後は、研究者よりというニッチ方面だけでなく、本格的なゲーム制作にも使えるように、という方向性も志向し始めています。
GLBoostでどんなことができるの?
まずは公式のサンプルページをみてください。これらはデモンストレーションというより、むしろそれぞれの3D機能がちゃんとエラーなく表示できるかのテストページに近いので、派手なものは全くないんですが(汗)
あとは、GLBoostの熱心なユーザーさんである @cx20 さんのjsdoページとかですかね。
また、私 @emadurandal が作っている3DRPG制作Webサービス「WebRPGTool」では、最初3D実装にThree.jsやBabylon.jsを使っていたんですが、少し前からGLBoostに切り替えています。
最近ですと、最近出てきた新しい3Dフォーマット「glTF」への対応を頑張っていまして、これを使えばスキニングアニメーションとかができます。
デモサンプル:http://jsrun.it/emadurandal/swoN/
GLBoostの特徴と現状
サポートされている機能を列挙しますね。
- 頂点データを与えて表示するMeshやGeometryクラス
- カメラクラス
- 良い感じに対象モデルを捉えてその周りにカメラを回転できるカメラコントローラー
- クラシックなマテリアルクラス(物理ベースにはまだ未対応です)
- スフィアや平面、四角形などのプリミティブクラス
- Objファイルローダー
- glTFファイルローダー(スキニングアニメーションまで対応しています)
- アニメーション機能
- スキニングアニメーション機能
- Phong、Lambert、HalfLambertシェーダー
- ドノーマルなForwardレンダラー(Deferred未対応)
- ドノーマルなシャドウマップもできなくはない
うーん。ちょっとまだお寒い状況ですね。この2016年においては。
なので、まだThree.jsのようなメジャーなライブラリには全然比べ物になりません。まだ生暖かく成長を見守って頂くフェーズではあるのですが、それでも恥を忍んで、世に出しちゃうのは結構大事なことだと思うんだ…。
簡単なサンプル
簡単なレンダリングのサンプルを載せておきます。GLBoostだとこんな感じです。Three.jsなどと雰囲気がちょっと似ているかもしれませんね。
// GLBoostコンテキストとGLBoostレンダラーを準備します。
var canvas = document.getElementById("world");
var glBoostContext = new GLBoost.GLBoostMiddleContext(canvas);
var renderer = glBoostContext.createRenderer({
clearColor: {
red: 0.0,
green: 0.0,
blue: 0.0,
alpha: 1
}
});
// シーンを作成します。
var scene = glBoostContext.createScene();
// マテリアルを作成・設定します。
var material = glBoostContext.createClassicMaterial();
var texture = glBoostContext.createTexture('resources/texture.png');
material.setTexture(texture);
material.shaderClass = GLBoost.PhongShader;
// スフィアジオメトリを作成します。
var geometry = glBoostContext.createSphere(20, 24, 24, null);
// スフィアジオメトリとマテリアルを引数にして、メッシュを作成します。
var earth = glBoostContext.createMesh(geometry, material);
// add the earth mesh to the scene
scene.addChild(earth);
// ディレクショナルライトを作成します。
var directionalLight = glBoostContext.createDirectionalLight(new GLBoost.Vector3(1, 1, 1), new GLBoost.Vector3(-1, -1, -1));
// add the light to the scene
scene.addChild( directionalLight );
// カメラを作成、セットアップします。
var camera = glBoostContext.createCamera({
eye: new GLBoost.Vector3(0.0, 0.0, 60.0),
center: new GLBoost.Vector3(0.0, 0.0, 0.0),
up: new GLBoost.Vector3(0.0, 1.0, 0.0)
}, {
fovy: 45.0,
aspect: 1.0,
zNear: 0.1,
zFar: 1000.0
});
// カメラをシーンに追加します。
scene.addChild(camera);
// エクスプレッションを作成します(複数のレンダリングパスを管理するものです)
var expression = glBoostContext.createExpressionAndRenderPasses(1);
// シーンをエクスプレッション中のレンダーパスの一つにセットします。
expression.renderPasses[0].scene = scene;
// レンダリングの前に、必ずこのprepareToRenderメソッドを呼びます。
expression.prepareToRender();
// レンダリング・ループです
var render = function() {
// Canvasをクリアします。
renderer.clearCanvas();
// エクスプレッションに追加されたシーンの内容をすべて描画します。
renderer.draw(expression);
// カメラを回転させます。
var rotateMatrixY = GLBoost.Matrix33.rotateY(-1.0);
rotatedVector = rotateMatrixY.multiplyVector(camera.eye);
camera.eye = rotatedVector;
// 画面の垂直同期に合わせて、レンダリング・ループを再び実行します。
requestAnimationFrame(render);
};
// レンダリング・ループを起動します。
render();
だいたいこんな感じです。Three.jsより若干記述が冗長ですが、ギーク向けということでまぁいいかな的に考えています。
GLBoostの今後
国産2Dゲームライブラリphina.js
との連携
もともとこのGLBoostプロジェクトは、私の友達の @phi さんが作られている2Dゲームライブラリ phina.jsの3D機能部分として機能するよう、開発を始めた…はずなのですが、いつの間にか単体WebGLライブラリになって今に至る状況です。
(ただ、すでにphina.jsと疎結合で連携できるようにはなっています)
今後、より深く連携できるように、ということで @phiさんたちと話はしていまして、おそらく今後何か展開があるのではないかな、と思います。
今後の機能増強について
以下を予定しています。
- PBR(物理ベースレンダリング)対応
- Deferred Shading対応
- もう少しまともなシャドウマップ(影)を
- 処理パフォーマンス向上
- TypeScriptでコード書きなおし
- Low、Middle、Highと3層に設計をレイヤー分けし、好きなレイヤーで開発ができるようにする(別途記事で解説)
- 3Dゲーム開発に便利なよう意識して開発
コミュニティづくりについて
作りたいですねーorz
幸いにもお一人、熱心に使ってくれる方がいらっしゃって、日頃からフィードバックをくれたりするのですが、完全に一人で孤独にコツコツやるのと、こういう方が一人いてくれるのとでは、天と地ほどのモチベーションの差が出てきます。
さらには本Advent Calendar10日目、Grimoire.jsの @kyasbal_1994 さんとはよく技術的な相談をし合う仲でして、こういうライブラリ作者間の交流というのも非常にモチベアップにつながります。
さらに最近では、もう少し使ってくださる方も出始めてきて、嬉し限りです。
なので、現在のGLBoostフェーズとしては、最初期の「ぼっち」状態からは脱して、数人〜規模のコミュニティになってきつつあります。コミュニティとしてはまだまだですが、少なくともモチベーションは維持できるレベルになったかな、そこは幸運でした。
もっと大きなコミュニティを作りたいという夢はありますが、そのためにはやはり何は無くとも機能の充実が必要だと感じています(後、チュートリアル・API資料等のドキュメント)。
開発を通じて感じたこと:「オレオレ作っちゃえばいいんだよ」
私、実は元はCG研究生・研究者の端くれだったので、諸々のこと分かってたつもりではいたんですが、しかし実際に実装していくと……特に書きすての検証プログラムなどでなく、他の人が使う前提のライブラリの実装をやっていると、得られるモノが違いますね。
それまで、なんとなく理解していると思い込んでいたものが、実装を通じて「ああ、ここら辺理解が曖昧だったんだな」と痛感したことは数知れません。
そして、あるCG技法を自分でライブラリとして実装するということは、机上で仕組みを理解する以上の理解として、実践を通じて体得することができます。
なので、皆さん。オレオレライブラリの開発はオススメですよ。書き捨ての検証プログラムを増産するより、ライブラリ作りましょう。うまく続けて規模が大きくなれば、いろいろ使い出があるしGithubで公開すればそれなりに話題になることもあるかもしれないしで、いいこと多い気がするぉ!(`・ω・´)
最後に
GLBoost、どんなライブラリなのか。どんな状況なのか。知っていただけましたでしょうか。
まだまだ未熟なライブラリではありますが、これからも何年もずっと開発を続けていくことになると思います。
どう成長していくのか、見守っていただけると幸いです。
あ、見守るだけじゃなくて、開発やら周辺環境作りを助けてくれる人がいてもいいのよ?←
興味ある方はGLBoost Gitterチャットで声かけてくださいねー!
あとGLBoost Advent Calendar 2016もよろしくね!