前回の記事で伝わったかと思いますが、Stage3D の登場により Flash Player の描画機能は一世代確実に進化しました。 久しぶりに一歩進んだ感じです。
この記事で紹介している Starling の他にも ND2D のようなフレームワークが登場したりとか、今から Flash の周りでいろいろと新しいことが起こりそうな予感がします。 (Alchemy の話や Flash Player のマルチスレッド対応の話とかもありますし)
さて、今回は少し詳細な Starling の仕様の紹介です。
Starling のアーキテクチャー
Starling は Stage3D 上に構築されています。Stage3D は、デスクトップ環境では DirectX や OpenGL、モバイル環境では OpenGL ES2 上に構築されています。そして OpenGL 等が GPU の API を直接呼び出すので、Starling は間に 2 階層挟んで GPU を利用していることになります。
- Starling
- Stage3D
- OpenGL, DirectX, OpenGL ES2
- GPU
もちろん余分なレイヤーは無い方がよいわけですが、ネイティブコードを実装したくなければ Stage3D を使うことになりますし、表示オブジェクト風の API から Stage3D を利用したければ Starling を使うことになります。
(まあ、Starling は約 80KB と軽量で、Flash Player 11 さえあれば動くので、それほど負荷は気にしなくてもよいのかもしれません)
とはいえ、軽量なのと引き換えに、Starling では表示リストの全ての機能が提供されるわけではなく、定義されているクラスも限定的です。これは主にゲーム用途での使用を念頭に設計されたためだと思われます。(もちろんゲーム以外にも使えます)
Starling では、イベントモデルも表示リストと共通です。表示オブジェクトに相当するクラスの階層構造も似ています。階層の上から順に、
- starling.events.EventDispatcher
- starling.display.DisplayObject
- starling.display.DisplayObjectContainer
と続き、その下に Button, Sprite, Stage, TextField が並びます。
MovieClip は少し変わっていて、Image クラスのサブクラスになります。以下のような階層関係です。
- starling.display.DisplayObject
- starling.display.Quad
- starling.display.Image
- starling.display.MovieClip
MovieClip が Image のサブクラスなのは、GPU 向けの最適化をした経験がある人にはピンと来たのではないでしょうか?。そうです、Starling のムビクリはパラパラ漫画になります。従来のタイムラインアニメーションが好きな人はここが引きのポイントかもしれません。
それから、Quad という新しいクラスが登場しています。Quad は四角い領域を塗るためのクラスです。そこにテクスチャーが加わると Image というわけです。
ともあれ、Starling のプログラムは、ほぼ見た目今までと一緒です。例えばビットマップ画像を表示する場合は、以下のようになります。
// ビットマップを埋め込む [Embed(source = "myBitmap.png")]
private static const myBitmap:Class; // ビットマップからテクスチャーを生成 var texture:Texture = Texture.fromBitmap(new myBitmap()); // テクスチャーを使ってイメージオブジェクトを生成 var image:Image = new Image(texture); // イメージの表示位置を指定 image.x = 300; image.y = 150; // イメージを表示 addChild(image);
今までどおりのイメージで書けるのが分かるかと思います。
表示オブジェクトと Starling を同時に使う場合
Stage3D は、従来の表示オブジェクトとは別のレイヤーに描画されます。ちなみに GPU でビデオ再生を行う StageVideo (Flash Player 10.2 から導入) も独立したレイヤーに描画されます。
それぞれのレイヤーの関係は、画面の表面から順に、
- 表示リスト
- Stage3D
- StageVideo
となっています。各々が独立したレイヤーのため、他のレイヤー内の表示データに直接アクセスすることはできません。例えば、StageVideo で再生中の映像を表示オブジェクトに貼り付ける、といったことは (いまのところ) できません。
表示リストと Starling (すなわち Stage3D) を同時に利用した場合、表示リストの方が上のレイヤーなので、全ての表示オブジェクトは Starling のオブジェクトの上に表示されます。Starling オブジェクトを表示オブジェクトの上に表示することはできません。
Stage3D はフレームごとに全ての領域を再描画します。表示リストのみで描画する場合は、再描画領域を限定してパフォーマンスを向上させることができますが、Starling と表示リストを組み合わせて使う場合は、この手段は有効でなくなります。
それから、現在のバージョンでは Stage3D オブジェクトを透過にできません。従って、StageVideo の上にオブジェクトをオーバーレイ表示したい場合は、Starling オブジェクトではなく表示オブジェクトを使うことになります。
Stage3D が利用できない場合
Starling ひいては Stage3D を使うには、wmode=direct を指定する必要があります。wmode が指定されていない場合、または他の wmode が指定されていると、ランタイムエラーが発生します。
Starling はこのエラーを発見すると、wmode が正しく指定されていないことを示すメッセージを表示します。そのため HTML に正しく SWF が埋め込まれていない場合を発見しやすくなっています。
wmode が正しく指定されていても、ドライバーのバージョンが古いなどの理由で (2009 年より前のものは全てサポート外です) GPU が利用できない場合、Stage3D はソフトウェアにフォールバックします。その際は SwiftShader というエンジンが使われます。
この状況が最も遅い再生環境だと考えると、ソフトウェアにフォールバックした状態で動作確認をしておくのがよさそうです。そのために? Starling にはソフトウェアでの実行を明示的に指定するオプションが用意されています。 (もしくは 3 年間ドライバーを更新していない PC を 1 台持っておくと便利かもしれません)
Flash Player 11 が正式に公開されたら、もう少し具体的な API 等を紹介したいと思います。
Starling のプログラミングはかなり表示リストに使えそうですね。
本気で表示リストからの移行を考えたくなります。
気になるのはstarlingが描画した画像をstage以外のSpriteでaddChildできるかどうかですね。
↓
// ビットマップを埋め込む
[Embed(source = "myBitmap.png")]
private static const myBitmap:Class;
var image:Image = new Image(texture);
// イメージの表示位置を指定
//starlingを表示するsprite作成
var bg_sp:Sprite=new Sprite();
// イメージを表示
addChild(bg_sp);
bg_sp.addChild(image);
こんな感じにも表示できたらすぐにでも移行したいですね。
まだまだ不明点は多いですが、2D描画パフォーマンスの向上は全開発者の夢なので、Starlingの今後の続報に期待してます。