Google I/O の WebGL セッションが素晴らしいのでハイライトを紹介してみる
今週はみんな Google I/O に気を取られているだろうから、ブログの更新はサボろうかな…と思っていたのですが、なんとなく動画を見てみた WebGL セッションの内容があまりに素晴らしかったので、ハイライトをご紹介することにしました。
WebGL を活用するためのテクニックやパフォーマンス Tips などが解説されていて、 WebGL に関わっている方は必見です。また、けっこう見栄えの良いデモがいろいろ出てくるので、「WebGL ってなに?」という方でも楽しく見れると思います。
とはいえ、解説されている内容をきちんと理解するには WebGL の基礎知識が必須です。もしセッションを見て興味を持たれたら、こちらの記事もぜひご参照くださいませ。
前半は処理を GPU へ移行してパフォーマンス改善する例
最初にまず WebGL の基本概念を説明。その後、円や立方体などのオブジェクトをアニメーションさせるデモを使って、不要なステート変更を削ったり座標演算を CPU (JavaScript) から GPU (Vertex Shader) に移行することでパフォーマンスが大幅に向上することを説明。
最終的にはオブジェクトが 40,000 個まで増えますが、 GPU を利用することでスムーズにアニメーションできていました。まあ、このあたりは定番のネタなので、説明は省略。
しかし、ここでひとつトラブルが。スライドのウィンドウが突然閉じて、 Windows update が始まってしまいました。
Thank you Microsoft!!! \(^o^)/
というわけで、しばし中断。その間、オーディエンスから「IE の WebGL サポートについて話してくれよ!」という質問 (?) が飛んで、「とりあえず Chrome Frame を使ってくれ」と答えてました(笑)
ポストプロセス(色変換)
Fragment Shader を利用したポストプロセスの解説へ。キューブ状の色空間の変換テーブルをテクスチャとして用意するやり方です。
ただし、 WebGL では 3D テクスチャが使えないので、 2D テクスチャに展開します。
Fragment Shader で RGB 値を UV 値に変換します。スライス間の Bi-linear フィルタもシェーダーで実装しています。
Video タグと組み合わせて動画のポストプロセスを実行するデモもありました。イカス。
変換用のテクスチャの作り方も解説。変換したい画像の隅のほうに変換前の RGB 値を格納したテクスチャ画像を貼り付けておいて、 Photoshop などで好きなようにフィルタをかければ、その結果がそのまま変換用テクスチャとなる仕掛け。なるほど。
ポストプロセス(モーションブラー)
2 つの FBO を使ったモーションブラーの解説。具体的なコードは示されなかったので、デモだけご紹介。これまたよく作ってあって、パラメータを変更することでいろんなエフェクトが試せます。ノーマルなモーションブラーはもちろん…
横方向に流れるブラーや、
拡大 + 回転をかけたり。 FF っぽい(笑)。
静止画だとイマイチかもしれませんので、ぜひ動画で見てください。
2D Canvas API を使ったアプリでこうしたエフェクトを使いたい場合は、 webgl-2d.js というライブラリを使うと良い、とのことです。 WebGL で Canvas API を実装したライブラリです。
WebGL でやるべきこと、やってはいけないこと
WebGL のコーディングでよくある間違い(主にパフォーマンス関連)が 3 つ挙げられていました。
レンダリング中に gl.getXXX を呼ばない
まあ基本ですね。エラーチェックのときに出てきている Debug Context というのは、 WebGL Wiki で公開されているこれのことだと思います。ネイティブで実装するような提案もあるみたいですが、まだ実装されてないんじゃないかなぁ。
レンダリング中に Renderbuffer をアタッチしない
これも基本。 FBO 自体は単なるステート(テクスチャや Renderbuffer を結びつけるだけ)でメモリフットプリントは小さいので、初期化時に必要な組み合わせの FBO をすべて作ってしまいましょう。
(setInterval() の代わりに) requestAnimationFrame() を使おう
私は恥ずかしながら知らなかったのですが、 WebKit や Firefox ではそれぞれ webkitRequestAnimationFrame(), mozRequestAnimationFrame() という API があり、 CSS や SVG のアニメーションと同じタイミングでコールバック関数を呼んでくれるみたいです。バックグラウンド・タブやウィンドウの最小化などの状態では呼び出し頻度が落ちるので(Chrome はまったく呼ばなくなる?)負荷が軽減されます。以下のように使います。
var canvasEl = document.getElementById('screen'); // WebGLでレンダリングするCanvas要素 var startTime = window.mozAnimationStartTime || +new Date; // Chrome は未サポート var requestAnimationFrame = window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame; function renderLoop(time) { var deltaTime = time - startTime; startTime = time; render(deltaTime); // レンダリング処理 requestAnimationFrame(renderLoop, canvasEl); } requestAnimationFrame(renderLoop, canvasEl);
実際には、クロスブラウザで動くこちらのラッパーを使うと良いでしょう。
※ 公開時、上記コードの「startTime = time;」の行が抜けていました。申し訳ありません m(_ _)m
Tips
最後に Tips です。
canvas を拡大してパフォーマンスを稼ぐ
canvas 要素の width, height 属性に適切な速度でレンダリングできる解像度を指定しておき、それを style で拡大することでパフォーマンスを稼ごうというものです。透視投影行列を計算するときにアスペクト比を clientWidth / clientHeight で計算すれば、縦横の拡大比率が異なっても正しく表示できます。とくにゲームなどの全画面表示するアプリケーションでは、この方法を適用するのが無難でしょう。
トラブルシューティングのためにユーザーを get.webgl.org に導く
こんな感じで http://get.webgl.org/ のページにユーザーを誘導することで、ブラウザのアップグレードを指示してくれたり、ブラウザの適切なヘルプページに誘導したりしてくれるみたいです。もちろんすべて英語ですが…。日本語化されないかなぁ。
WebGL Inspector を使おう
WebGL のデバッグツールである WebGL Inspector を実際に動かして紹介していました。 Chrome Extension として実装されていて、それぞれの描画コマンドを実行した時点での画面やテクスチャ、シェーダーの状態が確認できます。 WebGL で開発するときはもちろん、他人の制作したデモなどがどういう仕組みで動いているのか調べるのにも有用です。
以降は質疑応答で、いつモバイル WebKit で WebGL が使えるようになるのかとか、例の脆弱性の件などが質問されてましたが、開発にはあまり役立つものではなかったと思うので、省略。
以上で終わりです。興味を持たれたら、ぜひセッション動画の方も視聴してみてください。
詳しくはこちらの記事をどうぞ!
この記事にコメントする