こんにちは!WebGLおじさんことふかぽんです。
WebGLの案件に関わらせていただくことが多く、「サマーウォーズTV連動特設サイト」や「シン・アリマ」などの案件でもWebGL周りを担当させていただいています。
過去のアドベントカレンダーではこんなことを書きました。かれこれ4年連続の出場です。
2015 ... WebGLも怖くない!canvasライブラリを効率良く学ぶオススメの順番
2016 ... 【脱・gulp】npm-scriptsでシンプルなフロントエンド開発環境を作る
2017 ... 【WebGL】シェーダーを使って3D空間でスプライトアニメーションさせる
前置き
WebGLコンテンツの開発をさせていただくことが多かったり、社内でWebGLの勉強会を開いたりもしているのですが、ある日ふと、とある技術やテクニックにフォーカスして話すことは多いが開発のフローについて触れることは少なかったなと思い、自分なりの開発フローと、どこに気をつけているかをまとめたいなと思います。
あくまでも全体像の話ですので、jsやシェーダーなど個々の技術のTIPSだったり、パフォーマンスチューニングに関しては触れないです。
実現したいこと
自分の場合は以下に重点をおいて開発を進めています。
- フィジビリティ確認は早めに
- 表現の詰めに時間をかけられるように
全体感はこちらです。
1. WebGLライブラリ選定 2. フィジビリティ確認 - WebGL Report - WebGL Stats - モック作成 3. フロントエンド開発環境準備 - ビルド環境 - シェーダー 4. 検証環境を用意しておく - 外部サービス - 検証ページ 5. GUIエディターを作る 6. 負荷監視(モニタリング)環境を用意する - FPS - (threejs限定)renderer.info 7. 本開発 8. 完成
6番に入るころには、このようなGUIが表示されます。
1. WebGLライブラリ選定
WebGLは正式には「WebGL API」のことですが、素のAPIのままだと記述量が膨大になりどうしてもスピード感が出にくいのでライブラリを使うことがほとんどです。
3DコンテンツならThree.js、2DならPIXI.jsを使っています。ドキュメントが詳細にまとまっている点が嬉しいため、長く使っています。
読み込みには、特に制限がなければCDNを使うことが多いです。CDNであればscriptで読み込むだけなのでお手軽さがありつつ、CDNのキャッシュに期待しつつ、という意味で採用しています。
- three.js - cdnjs.com - The best FOSS CDN for web related libraries to speed up your websites!
- pixi.js - cdnjs.com - The best FOSS CDN for web related libraries to speed up your websites!
npmモジュールをインポートして適宜importする形をとることもあります。プロジェクトの要件に合わせるのが一番ですので、適宜使い分けていきましょう。
2. フィジビリティ確認
WebGL開発でよく頭を悩ませるのは、挙動の差異がブラウザの種類だけでなくグラフィックドライバーなど端末のハードウェアにも依存してくる点です。
案件ごとで対応する端末の範囲や仕様は全く異なるので、前の案件で問題なかった実装が違う案件でそのまま適用できるとは限りません。 なので、「その仕様は実現可能かどうか」「こういう表現をやってみたいけど導入できるか」を各端末でチェックしておきます。
たいていの場合、この3つを使って確認していきます
2-1. WebGL Report
自分の端末のWebGLの対応状況を表示してくれるサイトです。対応すべき端末でこのページを開いて確認していくことで、使うことのできる機能・できない機能を確認します。
2-2. WebGL Stats
WebGLのパラメーターやエクステンションが、世の中の端末でどれぐらいまで対応されているかを教えてくれるサイトです。WebGLのエクステンションによっては対応範囲が狭いものもあるので、全体感を知るときに便利です。
2-3. モック作成
あくまでもフィジビリティ確認が主な目的のモックなので、本開発では使わない前提で作り、対応端末でチェックしていきます。
以前、スマホ限定コンテンツの開発で、10個のループ動画を同時に再生する必要があり、実現するためにスプライトアニメーションを実装することにしたのですが、メモリ的に解像度感の耐えうるテクスチャサイズでその数のスプライトシートを読み込んで表示ができるかがネックだったので、様々なサイズのテクスチャを用意し、読みこむテクスチャの数と大きさをブラウザ上で自由に変更できるようにモックを作り、落とし所を決めました。
本開発においては、他の実装との兼ね合いで予定よりも負荷がかかる場合がほとんどですが、最初に開発方針の目処を立てておけば修正の範囲は少なく済みます。
3. フロントエンド開発環境準備
3-1. ビルド環境
最近は流行りに乗ってWebpackをベースにしています。特に制限がなければ、好きなものを使う方針でよいかと思います。
ひと昔前であればGulpを使ったり、npm scripts だけで作っていたりしました。
3-2. シェーダー周り
glslifyを使うことが多いです。glslは使いまわすコードが多いので、よく使うような処理を数多く引っ張ってこれる点でglslifyは便利です。
ちなみによくつかうglslifyのモジュールはこちらです。glsl-noiseは、simplex-noiseなど様々なnoiseを提供してくれています。glsl-blendは、スクリーン、乗算、オーバーレイなど、フォトショのレイヤースタイル的な感覚でブレンド処理をかけることができます。
一方、自分でシェーダーをバンドルするような仕組みを書くこともあります。jsで動的にシェーダーを生成する必要があったためです。
4. 検証環境を用意しておく
WebGLで開発を進めていると、バグを含めた意図しない挙動に出会った時にどこに問題があるかがわかりづらくなることが多いです。jsの実装を間違えていたのか、端末固有のものなのか、数学的に計算を間違えていたのか・・・。 特にシェーダーで、コンパイルエラーが出てないのに意図しない表示になると何がなんだかさっぱりになります。
そこで問題を切り分けるために、開発環境から実装場所を切り離して該当部分だけ検証できるような環境を用意しておきます。
無理に開発環境下ですべてを行わず、機能ごとに切り出していく という点がポイントです。
4-1. 外部サービス
Codepenやjsdo.itはブラウザ上のエディターでjsなどを実行できるのでとても便利です。 検証に関わらず、シェーダーのモックなんかを開発したりもします。
CodePen - Front End Developer Playground & Code Editor in the Browser
jsdo.it - Share JavaScript, HTML5 and CSS
4-2. 検証ページ
案件のアセットを外部サービスにアップロードしてはいけないですが、3Dモデルなどそのアセットじゃないと確認できないものもあります。 そういう時は、開発環境下に検証用のページを作って確認します。
5. GUIエディターを作る
例えばちょっとした数値変更をしたい時に、プログラム上で変更してブラウザで実行して、それを繰り返して・・・は非常に時間がかかります。
そこで、ブラウザ上で挙動を調整できるようなGUIツールを用意しておきます。よく使うのは dat.gui です。数値や色の調整はもちろん関数の呼び出しもできて便利です。threejsやpixijsのexampleでも頻繁に見かけます。
ちょっとした数値変更で思いもよらない動きも出てきたりするので、新たな発見があったりもして楽しいです。
また、Three.jsであればOrbitControlsを使ってグリグリ視点を変えられるようにしています。
https://threejs.org/docs/#examples/controls/OrbitControls
6. 負荷監視(モニタリング)環境を用意する
開発を進めていると、気がついたら動作が重くなっていることが起こったりします。いざチューニングしよう!と思ってあれこれ試してみても上手くいかないことはざらです。
パフォーマンスチューニングの際は、何が原因なのかを特定してから進めていく必要があります。そこで、FPSやメモリ周りを画面上に表示しておくことで、パフォーマンスチューニングの元となる指標を可視化するようにしておきます。
原因を特定するフローや問題自体の特定については、こちらの本の第二章「GPU最適化入門」がわかりやすかったので、参考にさせていただいています。
Computer Graphics Gems JP 2015 - コンピュータグラフィックス技術の最前線 -
- 作者: 山本醍田,鈴木健太郎,小口貴弘,?吉雄介,白鳥貴亮,向井智彦,五十嵐悠紀,岡部誠,森本有紀,上瀧剛,坂東洋介,加藤諒
- 出版社/メーカー: ボーンデジタル
- 発売日: 2015/09/12
- メディア: 大型本
- この商品を含むブログ (1件) を見る
6-1. FPS
おそらく、FPSはもっともお手軽にパフォーマンスを確認できる指標だと思います。
自分はよくStats.jsを使っています。CDNもありますし、ちなみに製作者はThree.jsと同じでmrdoobさんです。
const stats = new Stats(); document.body.appendChild(stats); const tick = () => { stats.begin(); .. 色々な処理 stats.end(); requestAnimationFrame(tick); } requestAnimationFrame(tick);
6-2. (threejs限定)renderer.info
threejsであればWebGLRenderer.infoからドローコールやポリゴン数などの情報にアクセスできるようになっています。ドローコールやポリゴン数は特に気にしています。
# 詳しくは https://threejs.org/docs/#api/en/renderers/WebGLRenderer を参照 - memory - geometries - textures - render - calls - triangles - points - lines - programs
例えばドローコールであればこのようにアクセスすることができます。
const renderer = new THREE.WebGLRenderer(オプション); const logElem = document.querySelector(セレクタ); logElem.textContent = `drawCalls: ${renderer.info.render.calls}`; // ドローコール表示 ... その他ログ表示
7. 本開発
用意ができたら開発をガシガシ進めていきます。ここまできたら、マークアップや検証、パフォーマンスチューニングが入り交ざりながら開発していきます。適宜npmモジュールが追加されるなど開発環境も変化していきます。
パフォーマンスチューニングは様々なアプローチがあります。繰り返しになってしまいますが、まずは問題を特定できるようにしておくことが肝心です。5番で紹介したような本を参考にしていただければなと思います。
7. 完成
あっという間に完成!
まとめ
ポイントは大きく二つです。
- ブラウザ上でログを確認できるようにした
- ブラウザ上で調整できるようにした
本開発にたどり着くまでが長く、開発環境の準備に時間をかけていました。UnityやUnrealEngineなどのゲームエンジンはすでにそれが用意されているので大変便利です。
たしかに、Web開発において、開発者ツールなどを除きそういったGUIのエディターは基本的に存在しませんが、あった方が間違いなく開発を進める手立てになると思います。
最近は WebGLStudio のようなエディター付きのライブラリも出てきていますし、PlayCanvasを使ったコンテンツを見かけることも以前より多くなってきている気がします。また、UnityやUnrealEngineのゲームエンジンのWebGL書き出しも進化してきているので、これからWebGLの開発フローは大きく変わっていくんじゃないかという気がしています。
最後に
ここまで読んでいただいてありがとうございました。