Meshを継承したカスタムDisplayObjectを作る：Triangle(パフォーマンス計測編)


カスタムDisplayObjectを作るやり方を覚えるためのTriangleクラス作成でしたが、使いどころがあるかもしれないので、その辺りの考察とパフォーマンス検証をしてみます。

えー、先に書きますとあまり役に立たない投稿内容となりました。

その1 [Meshを継承したカスタムDisplayObjectを作る：Triangle](http://qiita.com/harayoki/items/097407336b3379630786)
その2 [Meshを継承したカスタムDisplayObjectを作る：Triangle(補足)](http://qiita.com/harayoki/items/69c398206deb8b47467c)

#使い道
三角形のままだと、使える場面がかなり限られそう(抽象的なビジュアルのゲーム作成など?)ですが、三角形の中にも四角形部分が存在しますので、ここにテクスチャを適用することを考えます。これならば四角いDisplayObjectの代わりに使うことができそうです。

![fig6.png](https://qiita-image-store.s3.amazonaws.com/0/8302/1822e61b-6242-ad11-3366-128746e01b78.png "fig6.png")
この、赤い部分だけにテクスチャを適用したいですが、頂点は３つしかなくこれ以上分割できない（しない）ので、いらない部分はテクスチャ側に透明部分をもたせることで解決します。テクスチャ適用が前提で、描画面積に無駄が出ますが。。


Triangle用テクスチャ(32x32)
![スクリーンショット](https://qiita-image-store.s3.amazonaws.com/0/8302/636d88cd-e6c5-2d82-e70c-bfe6a877b6c1.png)
実際に適用するテクスチャはこのようなものです。右下に黒い点が打ってありますが、これはTexturePackerなど設定で余白をトリムする機能をもっているパッキングツールを使うときに、そのトリムを抑制するためのものです。

Triangleは余白テクスチャにも対応していますが、左上部分の余白は良いものの、右下方向がトリムされてしまうと、実際にテクスチャを適用する際に、隣接している他のパーツが入り込んできてしまうので、このダミーの点が必要になります。

ピクセルシェーダーでなんとかするような手もあるかもしれませんが、まあ、とりあえず。

Quad用テクスチャ(16x16)
![スクリーンショット](https://qiita-image-store.s3.amazonaws.com/0/8302/80b1a3e9-68cb-35bd-d0fd-bdc1b5715eaf.png)
この下で、Quadと比較してのパフォーマスンス検証をします。Quad側にはこのテクスチャを使います。無駄な透明部分がなく大きさが４分の１です。どちらがパフォーマンスがいいでしょうか。

#パフォーマンス計測用デモ
![DemoCapture_2016_5_25_0_32_46.png](https://qiita-image-store.s3.amazonaws.com/0/8302/587b2766-cc3f-c044-e240-d3068f3e249d.png "DemoCapture_2016_5_25_0_32_46.png") ![DemoCapture_2016_5_25_0_33_30.png](https://qiita-image-store.s3.amazonaws.com/0/8302/1451e440-80ee-9c28-02af-3eaf9d1197c4.png "DemoCapture_2016_5_25_0_33_30.png")
テストはAIR書き出しで行っていますが、こちらにweb上で動く[デモ](http://harayoki.github.io/qiita_demo/triangle_demo/demo3.html)があります。適当にボタンを押すとTriangleとQuadが作られます。デモのソースは[ここ](https://github.com/harayoki/-qiita1/blob/triangle_demo3/src/demos/TriangleTest3Demo.as)にあります。

![DemoCapture_2016_5_25_0_34_3.png](https://qiita-image-store.s3.amazonaws.com/0/8302/7e4dbaf4-4f9b-028c-8936-36ff744cc4b1.png "DemoCapture_2016_5_25_0_34_3.png")
テクスチャなしで表示すると(わかりやすく着色はしましたが)こんな感じになります。描画面積に違いがありますね。

#計測
結論から言うと、ほとんどパフォーマンスの差はありませんでした。

![スクリーンショット 2016-05-25 0.41.49.png](https://qiita-image-store.s3.amazonaws.com/0/8302/d2eddddc-4dfc-8fe7-7738-f13cde3eb80f.png "スクリーンショット 2016-05-25 0.41.49.png")

![スクリーンショット 2016-05-25 0.41.39.png](https://qiita-image-store.s3.amazonaws.com/0/8302/b2b2a2e4-f157-1c2d-8d0b-385d8ec932cc.png "スクリーンショット 2016-05-25 0.41.39.png")
Scountで見ると、5000個、1000個のDisplayObject切り替え時でともにこんな感じです。どちらがどちらだかわからない。

![スクリーンショット 2016-05-25 0.42.30.png](https://qiita-image-store.s3.amazonaws.com/0/8302/a72b2d56-21f0-e5e2-1f71-5b83b2b93bc1.png "スクリーンショット 2016-05-25 0.42.30.png")
グラフの青い部分がActionScriptの負荷なんですが、詳細を見ると、頂点データやインデックスデータのコピーに時間がかかっているようです。ちゃんと異なるデータが取れてるのか心配になりますが、GPUメモリをみてみると

![スクリーンショット 2016-05-25 1.24.37.png](https://qiita-image-store.s3.amazonaws.com/0/8302/558317d9-9b4e-03ea-53a0-3b81bed8a977.png "スクリーンショット 2016-05-25 1.24.37.png")
_Triangle_

![スクリーンショット 2016-05-25 1.24.44.png](https://qiita-image-store.s3.amazonaws.com/0/8302/64dc552a-fb27-5e6b-16e0-75f548fc56fc.png "スクリーンショット 2016-05-25 1.24.44.png")
_Quad_

インデックスバッファーと頂点バッファーのメモリ量がそれっぽくなっているので、間違っていなそうです。


# 考察
結局DisplayObjectである限り、座標変換計算やデータの取りまとめに処理時間がかかり、ボトルネックになっているようですね。GPU側の処理の差が見えてこない。おおむね予想した通りではありますが。。

三角形ごとに１つのDisplayObjectとせず、たくさんの三角形を扱うDisplayObjectを作るとかなり速くなるのではないでしょうか。まあそれを汎用的にやっているのが、[starling.display.MeshBatch](https://github.com/Gamua/Starling-Framework/blob/master/starling/src/starling/display/MeshBatch.as)クラスな訳ですが、使う用途を限定して、三角形以外のMeshを受けつけない・全体を拡大縮小回転させない、真面目にbounds計算しないなどの制限の元に処理の最適化を行うと、使えるものができそうです。
具体的な用途としてはシューティングゲームの弾幕とかですかね。(ほぼほぼパーティクルシステムぽい実装になる気もします。)

今回Traiangleクラス作成で得た知識も生きそうなので、そのうちやってみようと思います。