dev.yuichiroharai.com
Flash Player 11から登場したStage3DによってGPUを使った高速な描画処理が可能になりましたが、Flash Player 10以前のメイン描画機能のGraphicsクラスとの処理速度の違いを検証するため、両者を比較できるサンプルをwonderflに投稿しました。
当初、Stage3DについてはGPUを使った場合のみの検証を想定していました。
しかし、先日(2011/12/06)のFLASH MEETUPにて、現時点ではFlash Player 11を搭載したマシンでStage3Dを使用する場合、GPUで動作するのは50%程度(逆に言えば残りの50%はソフトウェアレンダリングを使用している)という話が出ていたそうなので、それはちょっと少ないなぁと思いソフトウェアレンダリングを使った場合の検証も追加してみました。
※ FLASH MEETUPの内容については「2011/12/06 FLASH MEETUP #flashmeetup - Togetter」を参考にしています。
結論から言うと、Stage3Dは(Context3D.configureBackBufferメソッドで指定する)描画領域が大きいほど負荷がかかります。一方で、Graphicsの場合は描画領域の大きさも当然負荷に影響がありますが、それ以上に三角形などのひとつひとつの描画処理が増えるほど大きな負荷が掛かります。
つまり、密度の高い複雑な形状の物体を描画する場合はStage3Dの方がかなり有利ですが、フルスクリーンモード時などに画面サイズいっぱいに描画を行う場合、シンプルな形状の場合はGraphicsの方が負荷が軽くなるケースが出てきます。
極端な話、Stage3Dは特に何も描画せずにContext3Dクラスのclear()とpresent()を毎フレームごとに呼び出すだけでも負荷が掛かっていました。
では、サンプルの説明と検証内容について書いていきます。
比較になるようにStage3DとGraphicsの両方で同じものを表示していますが、細かい違いなどの留意点をいくつか先に説明しておきます。
まず、テクスチャに使っている画像は256×256で固定です。Stage3Dではミップマップを使う事で描画する面に合わせて最適なサイズの画像が使われるようにできますが、Graphicsにはそういった機能は無いのでStage3Dでもミップマップは使用していません。
次に、アンチエイリアスの設定はStage3DではContext3D.configureBackBufferメソッドを呼び出す時に16(最高品質)を指定しています。実際は2(最小限)や4(高品質)でも実用に耐えれるレベルだったりするので、その場合は処理速度はそれなりに早くなります。
GraphicsではbeginBitmapFillメソッドを呼び出す時にスムージングをtrueにしてアンチエイリアスを掛けています。こちらは細かい品質の設定はできません。
ちなみに、何故かソフトウェアレンダリングのStage3Dではアンチエイリアスが掛かりませんでした。
(このサンプルに問題があるのかもしれませんが…。)
続いて、面が重なった際に手前の面が正しく表示されるようにするための深度管理についてですが、Stage3DではContext3D.setDepthTestメソッドを使って深度管理を実現しています。面が重なった際には手前のピクセルの後に奥のピクセルを描画する時には処理をキャンセルする事ができるでの、効率良くパフォーマンスが向上されている事が想像できます。
しかし、Graphicsではピクセル単位での深度管理はできないので、drawTrianglesメソッドの第4引数を使って面の裏側(奥)を先に描画してから表側(手前)で上書きするようにしています。この方法だと正しく表示はされますが無駄な描画が発生する事になりますので、Stage3Dと違って処理速度の向上は期待できません。

キーボードの任意のキーを押す事で、Stage3D(GPU使用)、Stage3D(ソフトウェアレンダリング使用)、Graphicsの3種類の描画方法が順番に切り替わり、描画領域の背景の色が変わります。
Graphicsの場合には描画領域をクリックすると球面を構成する三角形のボーダーの表示/非表示を切り替える事ができます。
(ていうか、Stage3Dでも線を書けるようにして欲しい。。。)
右上のスライドバーを操作して球面を構成する三角形の数を変更できます。密度の違いが分かるよう5段階用意しました。
球面と三角形の関係は以下の通りです。
三角形の数 = n (縦横の分割数) ^ 2 × 2 (三角形2つで四角形を構成) × 6 (球面数)
ひとつの球面の縦横をそれぞれ四角形でn分割し、四角形は三角形2つで構成しています。球面は全部で6つになります。
以下に、いくつか例を挙げてみました。
2分割, 三角形の数=48

さすがに球面とは言えない精度の球面です。
8分割, 三角形の数=768

大きさにもよりますが、丁度良いレベルの精度の球面です。
32分割, 三角形の数=12288

かなりの精度の高い球面です。
検証に使用したマシンのスペックは以下の通りです。
2年半ほど前の廉価版のMacです。正直スペックは低いですが世間一般のマシン環境を想定する上での丁度良いサンプルではないかと思っています。
まずは描画領域が比較的小さい465×465の場合についてです。wonderflにおける固定サイズになります。
| 三角形の数 | 48 | 192 | 768 | 3072 | 12288 |
|---|---|---|---|---|---|
| Stage3D(GPU)のFPS | 60 | 60 | 60 | 60 | 60 |
| Stage3D(Software)のFPS | 50 | 49 | 48 | 42 | 37 |
| GraphicsのFPS | 60 | 60 | 60 | 37 | 15 |
GPU使用のStage3Dでは安定したパフォーマンスを発揮しています。その一方で、Graphicsでは描画量(三角形の数)が増えると処理が極端に重くなっている事が分かります(赤字の部分)。
ソフトウェアレンダリングのStage3Dでは描画量が増えると若干処理は重くなりますが、Graphics程ではなく緩やかなものです。この事から、Stage3DはGPUを使わなくても描画アルゴリズムそのものがGraphicsより優れていると言えるのではないでしょうか。
Stage3DというとGPUのパワーに目がいきがちですが、実はソフトウェアの性能もアップしているようですね。
ちなみに、Graphicsではボーダーを表示するとさらに処理が重くなっていました。
続いて、描画領域が大きい場合についてです。1920×1280のモニタにおいてブラウザウィンドウを最大化してページを開いた時のサイズになります。
| 三角形の数 | 48 | 192 | 768 | 3072 | 12288 |
|---|---|---|---|---|---|
| Stage3D(GPU)のFPS | * | 28 | 28 | 28 | 28 |
| Stage3D(Software)のFPS | 34 | 34 | 34 | 31 | 26 |
| GraphicsのFPS | 58 | 50 | 35 | 20 | 10 |
* 処理が全く安定せず計測不可。だいたい10〜60FPSを行ったり来たりでした。
まずStage3Dについてですが、検証に使ったマシンのGPUスペックが悪いせいか、ソフトウェアレンダリングの方がGPUより早いというなんとも残念な結果が出てしまいました。GPUはソフトウェアレンダリングに比べて描画領域の大きさの影響を受けやすいようです。
そして、Graphicsの方は描画量が少なければStage3Dよりも高いパフォーマンスを発揮しています(赤字の部分)。
描画量と処理速度の比例の仕方は描画領域が465×465の時と同じような結果が出ていますね。
手元にハイスペックなグラフィックボードを搭載したマシンが無いので想像ですが、スペックさえ良ければGPUを使ったStage3Dは安定して高いパフォーマンスを発揮できそうです。
しかし、世の中のFP11搭載マシン全体の50%程度しかGPUで動作しない上にその中でハイスペックなマシンというと、結局どれくらいの割合になるのでしょうか。
作るモノによっては、強制的にソフトウェアレンダリングで動作させてStage3Dを使うというのも、セーフティな手段としてアリなのかなぁと思ったりもしました。