プロフィール

Na-7

Author:Na-7
SE(システムエンジニア)として約15年間システム系ソフト会社を勤めあげ、2008年3月退社。現在、ゲーム制作会社設立を目指して活動中。


アクセスカウンター


最新記事


最新コメント


最新トラックバック


月別アーカイブ


カテゴリ


DATE: CATEGORY:スポンサー広告
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
DATE: CATEGORY:三国志軍記開発
UVアニメにデバッグコンポーネント組み込み
UVアニメサンプル改
改修により、インスタンス数の上限が無くなった。タイムルーラーを表示すると、見た目とパフォーマンスが変わる??



◎定数レジスタのデータレイアウト

前回は、頂点座標や回転をシェーダーインスタンス化する所までやりました。UV座標は動的頂点バッファで更新していたので、今回はこれをシェーダーインスタンス化します。

まず最初に考えることは、定数レジスタのデータレイアウトです。

現時点では、定数レジスタ2個でfloat8個分のデータ(Position:3、Scale:1、RotateAxis:3、rotation:1)を渡していますが、実はScaleとrotationは固定値なので、シェーダーに固定値を埋め込んで空きを作れば定数レジスタ2個でUV座標の受け渡しが可能です。

ただ、そのようなサンプルは実際のゲームでは使いにくいので、今回は素直に定数レジスタをもう1つ確保します。ちょっと勿体ない気もしますが、サンプルの最適化だけ進めても本番のゲームが遅かったら意味無いですからね。


で、実際にプログラムしようとしたら…先程の自分は大馬鹿者であることに気付きました。1モデルに4頂点あるので、UVデータも4つ必要ですよね。float8個分の定数レジスタが必要ってこと?



◎アニメ番号を渡す?

それならいっそアニメ番号だけシェーダに渡して、シェーダ側でアニメ番号からUV座標を算出させれば、CPU側の負荷が減るし定数レジスタの使用量も少なくて済むから一石二鳥かも?

ただ、今のままだと頂点番号がわからないので、インスタンス番号の代わりに頂点番号を埋め込む必要がありますね。
シェーダ側のプログラムは複雑化しそうです。

それに、シェーダインスタンス化後の負荷は、CPUとGPUどちらが高いのか不明です。ということは、今の動的頂点バッファ方式より遅くなる可能性もあるわけです。こうして考えると、インスタンス化後のパフォーマンスを測定してから決めた方が良さそうです。



◎定数レジスタ256対応

パフォーマンス測定はメインPCとサブPC両方で行いますが、メインPCはイレギュラーなので、サブPCのデータを重視したいですね。サブPCで測定可能とするために、定数レジスタ256に対応しましょう。

そこで問題になるのは「定数レジスタ数を超えた時の複数回描画をどうやるか?」という点です。

私は最初、インスタンス情報格納配列を予め定数レジスタ数で区切っておくことを考えました。これならインスタンス情報をそのままシェーダに渡せるからです。

しかしGamefest2008デモプログラムを見ると、定数レジスタ格納専用配列を別途用意し、描画前にゲームデータを毎回その配列にコピーしてから描画しています。

なぜそんな2度手間のようなことをやるのかな?と思ったのですが、よく考えると、変に区切られた配列なんて、通常のゲーム内では使いにくくてたまらないですね。



◎startIndexの値

改修を終えて、一度に描画するインスタンス数を100、総インスタンス数を1000と設定したら、100個だけ描画されました。

改めてコードを確認すると、DrawIndexedPrimitivesのstartIndexが0なので、最初の100個を10回表示しているような気がします。しかしデモプログラムを確認すると、こちらも同様でした。あれ?startIndexの値をずらすべきじゃないの?

コードを何度か見比べたら、インスタンス情報を定数レジスタに格納する時の指定を間違えたことに気付いたので修正しました。

シェーダーインスタンス1000枚02   シェーダーインスタンス10000枚

左側は1000枚、右側は10000枚の画像です。
無事に改修できたようですね。

当初の目的は果たしたものの、私の疑問は謎のままです。誰か教えて~!



◎アルファ処理

今回の改修により、インスタンス数に上限が無くなりました。また、サブPCでも測定可能となりました。早速、デバッグコンポーネントを組み込んで測定しましょう。

UVアニメにデバッグコンポーネント組み込み

デバッグコンポーネントを組み込んでfpsやタイムルーラーを表示したら、こんな画面になりました。

何かの影響で画面が崩れたかと思いましたが、よく見ると槍兵が普通にアニメしてます。槍兵背景のアルファ値は最初からセット済だったのですが、それがデバッグコンポーネントの影響で有効化されて、背景が無くなったようですね。

見た目が変わるだけなら問題無いのですが、10000枚でfpsやタイムルーラーを表示すると、59→17fpsまで下がりました。アルファ処理ってそこまで重いのか?!

これでは純粋なシェーダーインスタンスのパフォーマンスがわかりません。しかしゲームではアルファ処理するので、この方が参考になるかもしれません。結局、両方のパターンを測定することにしました。



◎サンプルプロジェクト

プログラム整理が完了したので、HPにサンプルプロジェクトをUPしました。

XNA3.1でUVアニメーション
(シェーダインスタンス&動的頂点バッファ方式)


パフォーマンス測定データやデータ分析等もありますので、興味がある方はご覧ください。



◎次回予告

シェーダーモデル2.0で汎用的に使えるようになり、インスタンス数の上限も無くなりました。10000枚59fpsは我ながら凄いと思います。

しかし、サブPCでは予想以上にパフォーマンスが悪く、メインPCでもアルファ処理を加えるとパフォーマンスが激減しました。さらなる改良が必要かもしれません。


ともあれ3月になったので、次回は「2月の総括と3月の目標」です。

スポンサーサイト

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

コメント

>RotateAxis:3
これ、要りますかね? 自分なら移動にVector3、回転はY軸固定でfloatのみ、UV座標も(兵モデルの)左上頂点のオフセットだけ渡して、頂点データ側に“オフセットUVに加算する量”を埋め込むと思います(ゲームの仕様を勘違いしてたらスミマセン)。

>startIndexが0
で、いいんじゃないでしょうか。(本当は100インスタンスとは言え)1モデルを1度のDraw~()で描画しているだけです。通常のモデルを座標だけ変えて何度か描画するさいも、startIndexは0のままですからそれと同じです。

むしろ、320体と言った場合に、端数の20をうまく表示するようprimitiveCountの方を調節する必要があるんじゃないかと。

>アルファが重い
……勘ですが。ピクセルの座標が重なってる場合、通常「Zバッファの判定をして、既に書かれたポリゴンの方が手前なら今回のものは描画をパスする」ため、その場合はピクセル書き込みが発生せず、多少処理が軽くなるという事実があります。

しかしアルファONの場合はカラーブレンドがある上に、(ステート設定にもよりますが)Zバッファ関係なしに“毎ピクセル”書き込みが発生します。

で、そちらのサンプルは1万ポリゴンですから、相当“座標の重なるピクセル”があると思うんです、ハイ。

コメントありがとうございます

>RotateAxis:3
円柱状ビルボードにしたので、Y軸固定で良いということですね。

>頂点データ側に“オフセットUVに加算する量”を埋め込む
なるほど、その方がスマートですね。とても参考になります。

>startIndexが0
これに関しては、私の疑問点と論点がズレたようなので、何故ズレが発生したのか考えたら、いろいろなことが分かってきました。
(重大なバグも発見しました(^^;)

コメントでは書ききれないので、次回記事で説明させて頂きます。

>アルファが重い
なるほど、それなら納得できますね。
どうもありがとうございました。

コメントの投稿


管理者にだけ表示を許可する

トラックバック


この記事にトラックバックする(FC2ブログユーザー)



copyright © ゲーム制作の舞台裏 all rights reserved.Powered by FC2ブログ
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。