サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

EaselJS次期バージョンでWebGLを使う

ID: FN1401003 Technique: HTML5 and JavaScript Library: EaselJS NEXT

2014年1月28日付CreateJS Blogに「WebGL & EaselJS: a Technical Intro」という記事が投稿されました。EaselJSの次期バージョンがサポートするでWebGLレンダラをどのように使うかの入門的な解説です。現在、EaselJS次期バージョンはパブリックプレビューがGitHubに公開されています。本稿はblog記事にもとづいて、新しいWebGLレンダラについてご紹介します。なお、次期バージョンに備わる機能については、「EaselJSがWebGLをサポート」をお読みください。


01 はじめに

これまで試されたかぎりでは、一般的に使うWebGLレンダラをEaselJS向けに開発する意味はないと考えられていました。最近のCanvasの実装は、すでにさまざまな2DコンテンツをGPUで適切に描くことができます。それも、ネイティブコードにより、重い仕事をこなしているのです。あえて、JavaScriptでそれを超えようとするには及ばないでしょう。

けれども、コンテンツに一定の制限を設けると、WebGLで大幅にパフォーマンスを高められることがわかりました。新たなSpriteStageとSpriteContainerクラスがつくる表示オブジェクトはEaselJSのなじみのあるAPIを備えながら、コンテンツにいくつかの制限を加えることで、WebGLの描画を大きく最適化します。

新たなAPIでは、WebGLがサポートされなければ、Canvasの2Dに意識することなく切り替わります。そのため、コンテンツはどの環境でも動きます。さらに、多くの点で統合が行われましたので、WebGLレンダラの高いパフォーマンスを活かしつつ、より安定したCanvasレンダラを組合わせて、両者のいいとこどりができます。


02 SpriteStageとSpriteContainerクラス

SpriteStageクラスは、WebGLのステージを扱います。このクラスは、おなじみのEaselJSのStageクラスを継承します。新たなメソッドがいくつか備わり、そして大事なことはSpriteStage.addChild()メソッドで加えられる子がWebGLで描きやすい表示オブジェクトにかぎられることです。それらは、BitmapとSpriteにBitmapText、およびSpriteContainerです。ShapeやText、あるいはContainerのオブジェクトは含まれません。

var mySpriteStage = new SpriteStage("mycanvas");
mySpriteStage.addChild(myBitmap, mySprite, myBitmapText);   // OK
mySpriteStage.addChild(myText);   // エラー: 子として加えられない

同じように、SpriteContainerは、Containerクラスを継承します。そして、SpriteContainerクラスとしての縛りがかかります。SpriteContainerクラスのコンストラクタは、SpriteSheetオブジェクトを引数に受取って、spriteSheetプロパティにもちます。そして、SpriteContainerオブジェクトに加えるSpriteやBitmapText、あるいはSpriteContainerオブジェクトは、同じSpriteSheetオブジェクトを共有しなければなりません。さらに、そのスプライトシートには、イメージがひとつしか使えません。

var mySpriteContainer = new SpriteContainer(mySpriteSheet);

var myGoodSprite = new Sprite(mySpriteSheet, "idle");
mySpriteSheetContainer.addChild(myGoodSprite);   // OK

var myBadSprite = new Sprite(otherSpriteSheet, "run");
mySpriteSheetContainer.addChild(myBadSprite);   // エラー: スプライトシートが異なる

この仕組みが意味するのは、SpriteStageオブジェクトのルートからの階層は、それがどれだけ深くて入組んでいても、スプライトシートひとつのイメージとして描けるということです。つまり、表示リストの階層のすべてを、ひとつの描画の呼出しにまとめられます。そのため、コンテンツはとても素速く描けるのです。

ほとんどの場合、表示オブジェクト(のxyrotationscaleXscaleYalphaなど)は普通に扱えます。ただし、マスクやフィルタなどの高度な機能は、WebGLでは無視されます。

初めは制約が気になるかもしれません。けれど、実際の効果はきわめて高いです。ゲームなら、ステージに背景のビットマップを敷き、地形のSpriteが入ったSpriteContainerと、キャラクタのSpriteが納められた別のSpriteContainerオブジェクトを置きます。さらに、一番上のSpriteContainerに加えたBitmapTextとSpriteインスタンスでUIとスコアを示せばよいでしょう。これらのSpriteContainerは、それぞれのSpriteSheetオブジェクトが使えます。

そして、ご注目いただきたいのは、DOMElementもSpriteStageとSpriteContainerオブジェクトで問題なく扱えることです。それは、DOMElementがWebGLに描画しなくてよいからです。


03 自動フォールバック

WebGLがサポートされないデバイスでは、SpriteStageオブジェクトは自動的にCanvasの2Dレンダラにフォールバックされます。もちろん、WebGLの高速なレンダリングにもとづいてつくられたコンテンツでは、パフォーマンスが大きな問題になりえます。SpriteStage.isWebGLプロパティでどのレンダラが使われているかわかりますので、それに応じてコンテンツを調整することはできます。

if (mySpriteStage.isWebGL) {
  numParticles = 20000;   // いける!
} else {
  numParticles = 2000;   // ここは注意
}

新しいレンダラのパフォーマンスの詰めには、もうしばらく時間がかかります。このアプローチにより、きわめて高いパフォーマンスのコンテンツを幅広いデバイス向けに開発できるようになります。さらに、CreateJSの豊富なAPIやツール群が使えるのです。


04 SpriteStageとStageをともに使う

WebGLレンダラとともに、より安定したCanvasレンダラを使う手もいろいろあります。

Canvasがイメージのソースとして使えますので、StageオブジェクトのターゲットのCanvasをラップすればSpriteStageに加えられます。Stageオブジェクトには複雑なベクターアニメーションのコンテンツがつくれます。それをSpriteStageに、問題なく描けるのです。逆に、SpriteStageのWebGLコンテンツをStageオブジェクトのCanvasに表示することもできます。

var stageBmp = new Bitmap(myStage.canvas);
mySpriteStage.addChild(stageBmp);

つぎに、SpriteSheetBuilderクラスを用いると、Canvasレンダラのスプライトシートがつくれます。そのスプライトシートはWebGLでも使えます。このやり方で、たとえばすでにあるTTFフォントから、ランタイムでビットマップフォントが生成できます。また、読込んだスプライトシートの色味をフィルタで調整したりもできるでしょう。そして、ベクターのコンテンツからスプライトシートがつくれます。

さらに、StageとSpriteStageのCanvasをレイヤーとして簡単に重ねられます。そして、マウスやタッチのインタラクションを、新たに備わったStage.nextStageのAPIにより互いに受け渡せます。マウスオーバーやアウトのインタラクションも、ステージの間で正しく扱えます。

// Stage.nextStageプロパティでつぎのステージにマウスイベントを渡す
myTopStage.nextStage = myBottomStage;
// 複数のステージを順につなぐ
myBottomStage.nextStage = yetAnotherStage;

ステージが複数あるとき、上記のやり方で順につなげきます。各Canvasはそれぞれの大きさをもち、異なった間隔で更新できます。したがって、高速でフルスクリーンのゲームエンジンはWebGLの60fpsで描き、ベクターの美しいUIを半分の高さのCanvasで重ねて20fpsにすることもできるのです。


05 WebGLを始めよう

WebGLを使ったサンプルがいくつかGitHubで公開されました。「Runners」は、SpriteStageとSpriteContainerの使い方を示します。そして、コンテンツをWebGLがサポートされないデバイスでどう動かすかもわかります。また、「TwoStages」は、Stage.nextStageプロパティにより、マウスインタラクションをレイヤーの間でやり取りする例です。

Planetary Gary」は、新たなAPIを用いたより複雑なゲームのサンプルです。Canvasレンダラでつくられたコードのうち、つぎの中身の3行を書替えるだけでWebGLで動かせました。

  • ふたつ目のCanvasを加える。
  • SpriteStageオブジェクトをつくる。
  • ゲームエンジンのContainerの替わりにSpriteContainerを使う。

また、このゲームはSpriteSheetBuilderクラスによりランタイムで、小さなベクターグラフィックス(85kbにgzip圧縮)をWebGLで扱いやすいスプライトシートに変換しています。

図001■Planetary Gary
図001

これから数ヶ月の間、さらにサンプルが加えられ、正規リリースに向けた仕上げが行われます。目指すのは、EaselJS開発者が使いやすく、安定した豊富な機能をもったレンダラの提供です。CreateJSの開発チームはみなさんのフィードバックを待っているとのことです。



作成者: 野中文雄
作成日: 2014年1月29日


Copyright © 2001-2014 Fumio Nonaka.  All rights reserved.