0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DirectXTK HLSL スキニング 実装編

0
Posted at

https://qiita.com/YKVKDX12/items/cae702c31655f2bd8cce
の続編です

出力されるであろうアニメーション

スクリーンショット 2026-05-12 185906.png
ボーンに紐づいたポリゴンが回転するアニメーションです
画像ではわかりませんが、しばらく回転して、ウェイトの問題があるのか見えなくなります

この記事の構成

スキニングのコアはボーンとメッシュを使った座標変換です
・ボーンとジオメトリ 座標変換の共通点

・HLSLシェーダー スキニングの座標変換 

・DirectXTK側で行う、ボーンの平行移動行列と同じくボーンの回転行列の座標変換処理

の概要

ボーンとジオメトリ 座標変換の共通点(どちらもアフィン変換を使う)

ボーンの座標変換は、親子関係のつながりがあるボーン同士、ルートボーンから動かしたいボーン
までを再帰処理でチェーンのように連鎖する座標変換を行う点以外は、
3Dモデルに施すアフィン変換(拡大縮小/回転/平行移動の行列乗算)と変わりません
image.png

実装のコア抜粋

cbuffer BoneMatrices : register(b0)
{
    float4x4 g_BoneTransforms[64];
};

// 修正: C++側の SceneCB の構造に合わせる
cbuffer TransformUBO : register(b1)
{
    float4x4 g_World;
    float4x4 g_View;
    float4x4 g_Projection;
};

ボーンを操作するには座標変換が必要です
座標変換と言えば、たいていは定数バッファからのバインドですね

PS_INPUT main(VS_INPUT input)

...
 float4 transformedPos = mul(float4(input.pos, 1.0f), g_BoneTransforms[id]);
        totalPosition += transformedPos.xyz * weight;

ボーンを変形するために、入力された頂点

struct VS_INPUT
{
 float3 pos : POSITION;
 float3 norm : NORMAL;
 float2 texCoord : TEXCOORD0;
 uint4 boneIds : TEXCOORD1;
 float4 weights : TEXCOORD2;
};

float3 pos : POSITION;

cbuffer BoneMatrices : register(b0)
{
    float4x4 g_BoneTransforms[64];
};

image.png
このプログラムでの、このアルゴリズムのイメージはこれです(かなり誇張されていますが)
怪人ドクロスケスケ男が折り紙を折ってます

そこに

 totalWeight += weight;

ボーンにウェイトを加算しています。
つまりメッシュをボーンにどのくらい追従させるか?
(簡単に言えば骨に肉がガッチリつくのか、それともほろほろなのか)
を計算します。

float4 worldPos = mul(float4(totalPosition, 1.0f), g_World);
    float4 viewPos = mul(worldPos, g_View);
    output.pos = mul(viewPos, g_Projection);

最後におなじみシーンへの座標変換です
座標変換を知らなければ、こちらで異次元空間にとらわれたパンダを憐れみながら理解しましょう
https://qiita.com/YKVKDX12/items/35392b9eaae784b39bee

DirectXTK側は?

DirectXTKでも下準備の座標変換を行います

Game.cpp
 // 目標への平行移動
          XMFLOAT3 d;
          d.x = target[i].x - orig[i].x;
          d.y = target[i].y - orig[i].y;
          d.z = target[i].z - orig[i].z;

          // 時間応じた回転(各ボーンで異なる速度)
          float angle = elapsedTime * (0.3f + 0.15f * static_cast<float>(i));

          // ピボット周りの回転 + 移動
          XMMATRIX T_negPivot = XMMatrixTranslation(-pivot.x, -pivot.y, -pivot.z);
          XMMATRIX R = XMMatrixRotationZ(angle);
          XMMATRIX T_pivot = XMMatrixTranslation(pivot.x, pivot.y, pivot.z);
          XMMATRIX T_move = XMMatrixTranslation(d.x, d.y, d.z);

          XMMATRIX m = T_move * (T_pivot * R * T_negPivot);

          XMFLOAT4X4 xf;
          XMStoreFloat4x4(&xf, XMMatrixTranspose(m));
          boneTransforms[i] = xf;

フルコード

https://github.com/kantamRobo/DirectXTKAssimp/tree/master/DirectXTK_Skinning

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?