Share via


骨がほしい

2009/4/25 頂点テクスチャを使う方法を追加

骨を増やしたい

キャラクターなどを表示するときによく使われるスキンアニメーション。Creator Club Onlineにサンプルがありますが、指定できるボーン数が59個までとなっています。

このボーン数は微妙な数で、指間接や、顔の表情をコントロールするボーンがあるキャラクター作ると、この数には収まらないことがあります。通常、ゲームプレイ中はそこまでのディテールはカットシーンでもない限り必要ないので、手首から先の部分と、首から上の部分は別モデルとして表示することでボーン数の制限内に収めることはもちろん、必要のないときのアニメーション処理を省くことでパフォーマンス的にも有効な手段です。

とはいえ、この分割作業は面倒なのも事実で、仕事なら仕方がないですが趣味で作るゲームでは楽して作りたいと思うのは当然のことです。

使用できるボーン数を増やすには以下の4つがあります。

  1. float4x3を使う、1ボーンあたりの定数レジスタ使用数:3、最大ボーン数:79
  2. Quaternion,移動情報を使う、1ボーンあたりの定数レジスタ使用数:2、最大ボーン数:118、ただしスケールは使えない
  3. 頂点テクスチャを使う、1ボーンあたりの定数レジスタ使用数:0、最大ボーン数:256、ただしVS3.0限定
  4. vfetchを使う、1ボーンあたりの定数レジスタ使用数:0、最大ボーン数:256、ただしXbox 360限定

今回は最も手軽な1の手法を紹介します。

float4x3を使う

XNAフレームワークのMatrix構造体は4x4の行列で、回転とスケール部分をR、移動部分をTとすると、

mtx

のようになり、キャラクターのボーンに指定する行列、ワールド行列、ビュー行列では一番右側の列は常に同じ値になります。ただしプロジェクション行列では一番右側の部分も使われることに注意してください。

ようするに、キャラクターのボーンに使われる行列では左側の部分、つまり4x3の部分だけが必要で右側の部分の数値を定数レジスタに入れる必要がないということです。

この実装は簡単で、スキンアニメーションサンプル内のSkinnedModel.fxファイル内の三ヶ所を変更するだけです。

元のソースが

 float4x4 Bones[MaxBones];

//...

VS_OUTPUT VertexShader(VS_INPUT input)
{
    // ...
    
    // Blend between the weighted bone matrices.
    float4x4 skinTransform = 0;
    
    //...
    
    // Skin the vertex position.
    float4 position = mul(input.Position,skinTransform);
    

と、なっているところを(//...となっている部分には他のコードが書いてある)以下のように変更するだけです。

 float4x3 Bones[MaxBones];

//...

VS_OUTPUT VertexShader(VS_INPUT input)
{
    // ...
    
    // Blend between the weighted bone matrices.
    float4x3 skinTransform = 0;
    
    //...
    
    // Skin the vertex position.
    float4 position = float4(  mul(input.Position,skinTransform) , 1 ) ;
    

変更部分はfloat4x4をfloat4x3にし、頂点変換部分をfloat4( mul( input.Position, skinTransform), 1)とするだけです。

これで79ボーンまで使えるようになります。この変更をしたときに同ファイル内のMaxBonesの値と、SkinnedModelProcessor.cs内にあるMaxBonesを変更するのを忘れないようにしてください。

ここまで読んで 「エフェクトのパラメータ設定部分はどうするの?」 と思った人もいると思います。

その疑問の答えは 「何も変えなくていい」 です。

EffectParameter.SetValueにMatrixやMatrixの配列を指定した場合、このメソッドは対応するシェーダー側の変数が要求する分だけの値を設定します。今回のようにfloat4x3のときはもちろん、float3x3、float2x2、float4x1の場合でもC#側で指定した行列の該当する部分の値が定数レジスタに設定されるようになっています。

また、行列形の変数の場合、使用する定数レジスタ数はシェーダー側で指定した行列の「列」の数と同じになることに注意してください、float4x3では3個になりますが、float3x4では使用する定数レジスタは4個になります。