SetTextureの負荷

DXRubyは読み込んだ画像ファイルをそのままテクスチャとして保存して、描画するときにSetTextureを使って切り替えている。
3Dゲームなら1つのオブジェクトのたくさんのポリゴンにまとめて1つのテクスチャを適用したりするが、2Dの場合は1ポリゴンにつき1枚のスプライトという感じになるから、どんなに頑張っても、完全に1テクスチャにしない限りは、理論的に毎回SetTextureする可能性を否定できない。


基本的にはゲームを作る側、データを用意する側が、この絵は連続で描画する可能性が高いからまとめる、とか、まとまった画像を連続で描画するようなアルゴリズムにしなければならない。
SetTextureがどれほど遅いのかという話なのだが、2枚の画像を用意して、どっちを描画するかはランダムで決定するようにして1000回描画すると、毎回同じ画像を描画する場合に比べて約2msほど余分にかかった。
致命的に遅いというほどでもない。
Rubyで作るゲームなら、それが致命的な影響になるほどキャラを描画するとしたら、Rubyのほうがネックになってゲームにならない。
サンプルシューティングはボスの弾が多いが、あれは全部同じ画像だからSetTextureは負荷にはならず、あれを色んな絵でバラバラにしたところで300個程度だから0.5ms以下、せいぜい3%ぐらいの差にしかならない。
ローエンドPCなら10%ぐらいの差にはなりそうだ。
そう考えると大きい。


テクスチャの切り替えをライブラリ側の工夫で抑えるには、大きなテクスチャを作って、そこに読み込んだ画像をコピーしていくやりかたがある。
自動的に1枚のテクスチャにまとまってくれれば、使う側は意識しないでも最適化されることになり、実行速度は上がる。
しかし画像のサイズや数がマチマチであれば、綺麗に1枚にまとめるのは難しく、テクスチャの画像としてどのサイズまで扱えるのか、というのもあり、結構難しい。
DXRubyではImageオブジェクトがテクスチャを保持するが、image#x/yなどでテクスチャの使う位置を移動できたから、勝手にまとめることができなかった。
リファレンスには書いてないのにサンプルで使っているというとんでもない状態で、DXRuby1.0.3ではこれを廃止してサンプルも使わない形に書き換える予定だ。
それにより、複数のImageオブジェクトが同じ画像の違う部分を参照していたとしても、お互いのImageオブジェクトに干渉することはできなくなる。
つまり、テクスチャがまとまっていても別々でも、ユーザーから見れば関係なくなるということだ。
まあ、そうした場合には、使わなくなった画像を早々に解放して使用メモリを減らそうという努力が効かなくなる可能性はある。
とりあえず、今後のパフォーマンスチューニングの手札の一つとして考えておく価値はあるかもしれない、という感じか。