他のskinningの手法を吟味してみる

現在採用している、ボーン同士の関節部へ両者を補間して出した中間ボーンを追加して作った行列パレットを使う手法は、正確にslerpで補間された中間ボーンのおかげで関節の屈折角度が必ず90度以下に収まり、頂点座標の線形補間によって生じるアーティファクトを綺麗に隠してくれる。

この手法への不満としては関節数、つまり行列パレットのサイズが2倍になるという点で、スキニング処理を頂点シェーダ上で行う場合、例えばvs1.1仕様までのサポートを考えると96個しかレジスタが使えないので、たとえ1ボーンに対して3レジスタしか割り当てないように切り詰めたとしても、最大同時に使えるボーン数はたかだか15。人間の腰胸頭、3間接で両手両足使って15、ギリギリなのである。

また、骨盤と大腿の関節など範囲が広く立体的で、なおかつ大きな角度で曲がる可能性のある部分などではどうしても補間ボーンの存在が明らかに分かる。

関節部を十分綺麗に補間しながら、かつ、使用レジスタ数を減らせる手法がないものか。

憧れの頂点別の回転補間
究極的には複数のボーンの影響を受ける頂点はその頂点ごとに影響するクォータニオン自体を補間して正確に変換後の位置を定めるべきなのだが、これは処理時間をいくらでもかけてよい場合だけだ。しかし現在の頂点シェーダ仕様の限られた命令数の中でコレをやってしまう手法が提案されている。それがdual quaternionを使ったスキニングである。

概要としてはこうだ。クォータニオンはその4変数を単純に線形補間して正規化するだけでも、ある程度の品質の回転補間となる。2つのクォータニオンを混ぜるならシェーダ上の4インストラクション程度で済んでしまう。この長所を利用して回転の補間を頂点ごとに実行することを現実的な速度にまでもってくるわけだ。ところで、回転量のみを表現するクォータニオンだけではスキニングに使うには情報が十分ではない。関節の位置まで頂点をもってくる平行移動が必要なのだ。そこで、クォータニオンにさらにもう4変数情報を加えて位置の移動も表せるようにしたものがdual quaternionである。これを各頂点ごとに簡易な手法で補間値を算出し、頂点を変換するというわけだ。

この手法を用いた場合、ボーンひとつの変換を表すのに必要なレジスタ数は2(float4ふたつ)。96個のレジスタ使えるとして40ボーン程度は余裕をもって使える。なおかつ頂点ごとの回転計算が可能となる。いたれりつくせりに思える。

dual quaternionを使った手法の問題としてまず挙げられるのは当然のことながら処理量の増加である。頂点シェーダのコードは従来の頂点座標ブレンドで42命令のものが51命令にまで増えた。また、dual quaternionを生成する処理がホストプログラムでも追加されることになる。

処理の増加量は個人的な感想としては殆ど問題ないレベルだと感じる。レジスタの使用数の減少と相殺される程度だと思う。残るふたつの低質な回転補間に起因する問題に比べれば。


(1:中間ボーンを用いたスキニング 2:dual quaternion補間によるスキニング 特に違いは見られない。)

nlerpの問題
補間処理を頂点シェーダが実行するのに十分コンパクトなものとするために、クォータニオンの各要素を線形補完して再正規化しただけのnlerpが使われる。http://number-none.com/product/Hacking%20Quaternions/index.html にあるとおり、補間結果はslerpしたのと同じ経路を辿るのだが、その角速度が一定ではなくなってしまう。そのためにわずかにskinning結果に誤差が生じる。しかし、これはブレンドパラメータを上記ページにあるように歪めることである程度改善するに違いない。もうひとつ、nlerpは90度以上の差のあるquaternion同士は期待どおり補間できない。これは自分の見込み違いであった。つまり、任意に動く関節間の屈折角度を90度以内に収めるために相変わらずその間に中間ボーンを設置することが必要なのである。


(1:中間ボーンを使わずdual quaternionによるかなりキツイ屈折角度の補間 少し関節部が膨らんでしまっている 2:従来の中間ボーンを使った頂点座標ブレンド 3:90度以上の差のあるクォータニオン間でのnlerpの失敗で関節が崩壊)

微妙なトレードオフ
結局dual quaternionを使っても1ボーンあたりにはそれに割り当てなくてはならない中間ボーンを含めれば合計4レジスタが必要になる。vs1.1仕様では利用可能ボーンが従来の15から22程度への増加となる。スキニングの品質は向上はしない。むしろもう一手間かけなければ悪化する。もっとドラスティックな改善を期待していたのだが。