頂点テクスチャでスキンアニメーション

2010/09/17 追記: XNA Game Studio 4.0用のサンプルをhttp://higeneko.net/hinikeni/sample/xna40/TexSkinningSample.zipにアップしました。詳細は「サンプルコードをXNA 4.0向けに更新」を見てください。 2009/06/25 追記: XNA GS 3.1用のサンプルを http://higeneko.net/hinikeni/sample/xna31/TexSkinningSample.zipにアップしました。 頂点テクスチャでスキンアニメーション、その2:頂点テクスチャでスキンアニメーション 今回は頂点テクスチャを使ったスキンアニメーションの実装方法を紹介します。 XNA Game Studio 3.0で動作するサンプルを用意しました。基本的にSkinned Modelサンプルと同じ使い方です。 http://higeneko.net/hinikeni/sample/TexSkinningSample.zip 今回のサンプルは前々回の「クォータニオンでスキンアニメーション」のサンプルプログラムに以下の変更を加えたものです。 AnimationPlayerの変更 頂点テクスチャの生成 シェーダーの変更 頂点テクスチャフォーマットを決める まずは、頂点テクスチャにどのようにボーンデータを格納するか決めます。ボーンの回転部分のクォータニオンはVector4と同じフォーマットなのでSurfaceFormat.Vector4が使えます。平行移動にはVector3を使っていますが、頂点テクスチャのフォーマットにはVector3が無いのでちょっともったいないですがSurfaceFormat.Vector4を使用します。 今回のサンプルでは、回転部分と平行移動部分を2つの頂点テクスチャに別々に格納しています。ひとつのテクセルにひとつのボーン情報を格納しているので、頂点テクスチャのサイズは横がボーン数、縦が1となっています。 頂点テクスチャのサンプラーは4つしかないので、2つの頂点テクスチャを使うのが厳しい場合は以下のように、2つのテクセルにひとつのボーン情報をまとめて格納するといいでしょう。この場合、頂点テクスチャのサイズは横がボーン数×2、縦が1となります。 頂点テクスチャが使うメモリサイズを節約するという観点では前者の回転部分と平行移動部分を別々の頂点テクスチャで持つほうが有利です。これはクォータニオンの4要素の値の範囲は-1~+1なので、SurfaceFormat.Vector4の代わりにSurfaceFormat.HalfVector4やSurfaceFormat.NormalizedShort4を使うことでメモリ使用量を半分にすることができるからです。また、通常のキャラクターアニメーションでは平行移動部分も大きな値を使用しないのでSurfaceFormat.HalfVector4を使って更にメモリ使用量を減らすこともできるでしょう。 AnimationPlayerの変更 機能的には前々回のサンプルとまったく同じなのですが、頂点テクスチャへの格納フォーマットがVector4に変わったので、それに合わせてSkinTranslationsの型もVector3[]からVector4[]に変更します。 頂点テクスチャの生成 まずは、使用する頂点テクスチャ(ボーン用の頂点テクスチャなので、ボーンテクスチャと呼びます)の宣言をします。フレーム毎にボーン情報をボーンテクスチャへ書き込むわけですが、「GPUはいつ描画するのか?」で解説したように、同じテクスチャに続けて書き込むとGPUの処理とバッティングしてしまうということに注意が必要です。 そこで、それぞれ複数の頂点テクスチャを生成して切り替えながら使う必要があります。この実装は非常に単純でTexture2Dの配列と、現在使用するテクスチャのインデックスを用意するだけでいいのですが、使用する頂点テクスチャが増えてくると余計な変数が増えてきて、コードの可読性が低くなり、ミスも起きやすくなってしまいます。そういった理由から、ここでは複数のテクスチャを切り替える機能をもったFlipTexture2Dというクラスを作ります。 FlipTexture2DクラスはTexture2Dと同様のコンストラクタを持ち、内部で複数のテクスチャを作り、Flipメソッドで使うテクスチャを切り替え、Textureプロパティで現在のテクスチャを返すようになっています。 // ボーン情報を格納するテクスチャ FlipTexture2D rotationTexture; // ボーンの回転部分を格納するテクスチャ FlipTexture2D translationTexture; // ボーンの平行移動部分を格納するテクスチャ ボーンテクスチャの生成は前述のように、横がボーン数、縦が1のサイズのテクスチャを作ります。ここでTextureUsageをTextureUsage.Linearを指定していることに注意してください。通常のテクスチャはピクセルシェーダー内でフェッチされることを前提としており、その用途に適しているTextureUsage.Tilingを使用するようになっています。TextureUsage.Noneを設定しても、テクスチャサイズがタイリングに適している場合は自動的にタイリングを使うようになっています。 通常のレンダリング時には極力タイリングを使うべきですが、SetDataを呼び出したときに通常のフォーマットからタイリングフォーマットへの変換がCPUによって行われます。 今回はボーンテクスチャとして使用するので、タイリングを使う必要がないこと、SetData時にタイリングフォーマット変換に掛かる時間を節約したいという二点の理由から、TextureUsage.Linearを指定します。 // 頂点テクスチャの生成 int width = animationPlayer.GetSkinRotations().Length;…

2

頂点テクスチャってなに?

頂点テクスチャでスキンアニメーション、その1:頂点テクスチャってなに? 前回紹介したクォータニオンを使ったスキンアニメーションの実装方法はシェーダーモデル2.0では最も多くのボーン数を使うことができる手法です。この手法を使うことでオリジナルのスキンアニメーションサンプルでは59個だった最大ボーン数が、二倍近い117個になりました。   もっと多くのボーン数を使える手法はないのでしょうか?   残念ながら、シェーダーモデル2.0ではここが限界ですが、シェーダーモデル3.0から追加された機能を使うことで更に多くのボーンを使うことができます。 使う機能とは以下の二つです。 頂点テクスチャ 浮動小数点テクスチャ 頂点テクスチャは、その名のとおり頂点シェーダー内でテクスチャデータをフェッチ(読み込み)できる機能です。発表当時(2004年)のデモでは波のシミュレーションをピクセルシェーダーで行い、その結果を頂点テクスチャとして使うことで、立体的な波を表現していました。 また、XNA GSE 1.0のXNA Fieldデモではマルチスレッドでリアルタイムにフラクタル生成した結果を頂点テクスチャとして使用して地形モデルを表示していました。 実際のゲームでも、バーチャファイター5では水面と雪原、フォグなどの表現で頂点テクスチャは使われています。 頂点テクスチャの特徴としては 頂点シェーダー内で最大4種類のテクスチャをフェッチできる 任意のテクスチャ座標から複数回の読み込みができる 浮動小数点テクスチャと組み合わせることでさまざまなデータを扱うことができる 定数レジスタに比べて大量のデータを扱うことができる が、あります。 普段、テクスチャというと色情報が入った画像を使いますが、0-255の範囲の数値として扱うことで色以外の情報を格納するのにも使えます。これに加えてシェーダーモデル3.0から採用された浮動小数点テクスチャを使うことで、色以外の情報を格納するのが更に容易になりました。 また、頂点テクスチャの読み込みはピクセルシェーダー内でのテクスチャの読み込みと同様に自由にテクスチャ座標を指定することができ、複数回読み込むことができます。 これらの特徴を利用して、画像情報以外のデータを入れたテクスチャから自由にデータを読み込むことで頂点テクスチャを定数レジスタの変わりとして使うことができます。定数レジスタ数が256だったのに対して、頂点テクスチャでは大量のデータを格納することができます。例えば2,048×2,048のテクスチャは定数レジスタ数に換算すると400万という膨大な数のデータを格納することができます。 このように頂点テクスチャは非常に魅力的な機能ですが、弱点もあります。 対応しているGPUはまだ少ない、対応していても動作が遅いものが少なくない 浮動小数点テクスチャではフィルタリングが使えないものが殆ど テクスチャに格納できる要素数が1,2,4と限定されている 頂点テクスチャは最近のGPUでは当たり前のようについている機能ですが、まだ対応していないGPUの数も多く、ピクセルシェーダー内でテクスチャフェッチをするのに比べて速度的に劣る場合が多いです。 また、頂点テクスチャで使用されるテクスチャはその性質上、浮動小数点テクスチャを使うことが多いのですが、Direct X 9.0世代の殆どのGPUでは浮動小数点テクスチャに対してのバイリニアなどのフィルタリングができないものが殆どです。しかも、できないだけなら良いのですが、テクスチャフィルタを設定した状態でフェッチするとでたらめな数値を返してきたりするので、正しいフィルタリング設定をせずに頂点テクスチャを使ってしまい、自分のプログラムが正しく動作しているかどうかを時間を掛けて調べたあげく、見つけた原因が単純にフィルタリング設定のミスだったなんてことがあります。 頂点バッファで使われる代表的な型といえばVector3ですが、残念ながら頂点テクスチャではVector3は使えません。浮動小数点型で使えるのはSingle、Vector2、そしてVector4だけです。これはテクスチャのテクセルサイズには16ビット、32ビット、64ビット、そして128ビットの組み合わせしか指定できないのが原因です。 頂点テクスチャを使おう 以上のように、頂点テクスチャは魅力的な機能なのですが、使えるGPUの少なさから今まではおまけ的な機能として使われることが殆どでした。ですが、最近では使えるGPUの数も増えてきたので有効活用するケースも増えてきました。特にXbox 360やPS3はどちらも頂点テクスチャをサポートしていて、使っていると思われるタイトルも見かけるようになりました。 次回は、この頂点テクスチャを使ったスキンアニメーションの実装例を紹介します。

1

Gamefest Japan 2008 デモプログラム

2010/9/17 追記: XNA Game Studio 4.0のサンプルをhttp://higeneko.net/hinikeni/sample/xna40/GamefestJapan2008Demo.zipにアップしました。変更点は「サンプルコードをXNA 4.0向けに更新」に書いてあります。 2010/05/16 追記: マテリアルバッチ描画時のDrawIndexedPrimitiveメソッドへの引数設定が間違っていたのを修正しました。 2009/06/25 追記: XNA GS 3.1用のサンプルを http://higeneko.net/hinikeni/sample/xna31/GamefestJapan2008Demo.zipにアップしました 2008/12/26 追記: デモプログラムの更新、キーボード入力で操作できるようになりました。 やっと終わりました 今年の9月に行われたGamefest Japan 2008のプレゼンテーション資料が先月公開されました。 http://msdn.microsoft.com/ja-jp/xna/cc723908.aspx 私も僭越ながら2つのセッションを担当させて頂き、そのプレゼンテーション資料も公開されています。XNA Game Studioでのゲーム開発においてのパフォーマンス改善について戦略的手法と実践的な手法、主にシステムレベルでの最適化の効果の程を紹介させていただきました。 http://download.microsoft.com/download/0/4/2/04291420-033b-4f46-b87d-de64a2dc6bac/X5.zip 本当はプレゼン時にサンプルプログラムの配布したかったのですが、本業の方のXNA Framework作業の方が佳境の最中で、その合間に書いたコードだったので非常に汚いコードであったのと、先月のXNA Game Studio 3.0のリリースまでその忙しさが続いたので、なかなか公開することができませんでした。っていうか、コメントを追加するのは当然として、他にも3.0対応にしたり、再利用可能なコンポーネントを使いやすく書き換えたりして、発表時のコードよりも4,000行近く増えてしまったのも、今まで時間が掛かった原因でした。 ともかく、なんとか人に見せられる程度の体裁は整えたので、デモプログラムを公開します。 http://higeneko.net/hinikeni/sample/GamefestJapan2008Demo.zip 解凍したフォルダの中には以下の3つのソリューションファイルがあるので、好きなソリューションファイルを使ってください。いずれのプロジェクトを開くのにもXNA Game Studio 3.0が必要です。また、Windowsで実行するにはシェーダーモデル2.0以上のビデオカードが必須になります。 DemoWin.sln Windows用のソリューションファイル DemoXbox.sln Xbox 360用のソリューションファイル Demo.sln Windows/Xbox 360の両方のプロジェクトが入ったソリューションファイル フォントは私がプログラムする時に使っている等幅フォントのConsolasを使用しています。Consolasフォントが無い場合はビルドエラーになるので、以下のURLからConsolasフォントをダウンロードするか、フォント名を変更するようにしてください。 https://www.microsoft.com/downloads/details.aspx?familyid=22e69ae4-7e40-4807-8a86-b3d36fab68d3&displaylang=en このサンプルプロジェクトのコード、アセットは非商用、商用に関わらず、自由に使ってかまいません。ただし、一部のコードはクリエータークラブオンラインのMesh Instancingのコードを流用、または変更しているので、それらのコードのライセンスについては付属されるMicrosoft Permissive License.rtfに沿います。 http://creators.xna.com/en-US/sample/meshinstancing で、お約束ですが、このサンプルコードやアセットを使用したことで発生したいかなる問題にも当方は責任を負いません。…

9