Platform SDK: DirectX

ジオメトリ ブレンディングについて

DirectX 7.0 の Direct3D 直接モードでは、ジョイント部が滑らかにブレンドされている各ポリゴンを、特にキャラクタをレンダリングすることで、シーンを一層リアルに表現することができる (これらのエフェクトを一般には "スキニング" と呼ぶ)。このエフェクトは、追加の "ワールド" トランスフォーム行列を頂点の単一セットに適用し、その結果生成される複数のトランスフォーム後の頂点間で線形ブレンドを実行してレンダリング用のジオメトリの単一セットを生成することで実現される。次に示すのは、Bend サンプルによってレンダリングされたバナナに基づく画像である。

この画像は、ジオメトリ ブレンディングの処理がどのようなものであるかを示す。1 回のレンダリングの呼び出しで、システムはバナナの頂点を取得し、この頂点に対して回転しないトランスフォームと単純な回転のトランスフォームを 1 回ずつ実行して、その結果 "曲がった" バナナを生成する。システムは、頂点法線 (ライティングが有効な場合) だけでなく頂点位置座標もブレンドする。アプリケーションは 2 つのブレンディング方法に限定されるわけではない。Direct3D は、最大 4 つの異なるワールド行列 (標準ワールド行列の D3DTRANSFORMSTATE_WORLD など) 間でジオメトリをブレンドできる。

[C++]

 :  ライティングが有効になっている場合、頂点法線が、対応するワールドビュー行列の逆行列によってトランスフォームされる。この際、重み付けは、頂点位置座標の計算の場合と同様に行われる。D3DRENDERSTATE_NORMALIZENORMALS レンダリング ステートが TRUE に設定されている場合は、結果の法線ベクトルがシステムによって正規化される。

可動結合部のあるモデルの場合、ジオメトリ ブレンディングを使用せずに部分ごとにレンダリングされることが多い。たとえば、人間の腕の 3D モデルを考える。最も単純にして、腕には身体につながる上腕と手につながる下腕がある。2 本の腕はともに肘につながっており、下腕はこの位置座標で回転する。アプリケーションで腕をレンダリングする場合、上腕と下腕の頂点データは保持され、それぞれに個別のワールド トランスフォーム行列が適用される。次のコードはこのことを示す。

typedef struct _Arm {
D3DVERTEX upper_arm_verts[200];
D3DMATRIX matWorld_Upper;
    
D3DVERTEX lower_arm_verts[200];
D3DMATRIX matWorld_Lower;
} ARM, *LPARM;

ARM MyArm; // これは初期化する必要がある。

腕をレンダリングするには、次のコードで示すように、レンダリングの呼び出しを 2 回実行する。

// 上腕をレンダリングする。
d3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &MyArm.matWorld_Upper );
d3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX, 
MyArm.upper_arm_verts, 200, 0 );

// 下腕をレンダリングして、腕を関節でつなぐワールド行列を更新する。
// 肘でπ/4 ラジアン (45°) ずつ回転するようにする。
MyArm.matWorld_Lower = RotateMyArm(MyArm.matWorld, pi/4);
d3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &MyArm.matWorld_Lower );
d3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX, 
MyArm.lower_arm_verts, 200, 0 );
[Visual Basic]

 :  ライティングが有効になっている場合、頂点法線が、対応するワールドビュー行列の逆行列によってトランスフォームされる。この際、重み付けは、頂点位置座標の計算の場合と同様に行われる。D3DRENDERSTATE_NORMALIZENORMALS レンダリング ステートが TRUE に設定されている場合は、結果の法線ベクトルがシステムによって正規化される。

可動結合部のあるモデルの場合、ジオメトリ ブレンディングを使用せずに部分ごとにレンダリングされることが多い。たとえば、人間の腕の 3D モデルを考える。最も単純にして、腕には身体につながる上腕と手につながる下腕がある。2 本の腕はともに肘につながっており、下腕はこの位置座標で回転する。アプリケーションで腕をレンダリングする場合、上腕と下腕の頂点データは保持され、それぞれに個別のワールド トランスフォーム行列が適用される。次のコードはこのことを示す。

Type Arm
upper_arm_verts(200) As D3DVERTEX
matWorld_Upper As D3DMATRIX
    
lower_arm_verts(200) As D3DVERTEX
matWorld_Lower As D3DMATRIX
End Type

Dim MyArm As Arm ' これは初期化する必要がある。

腕をレンダリングするには、次のコードで示すように、レンダリングの呼び出しを 2 回実行する。

' 上腕をレンダリングする。
Call d3DDevice.SetTransform(D3DTRANSFORMSTATE_WORLD, MyArm.matWorld_Upper)
Call d3DDevice.DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_VERTEX, _
MyArm.upper_arm_verts, 200, 0)

' 下腕をレンダリングして、腕を関節でつなぐワールド行列を更新する。
' 肘でπ/4 ラジアン (45°) ずつ回転するようにする。
MyArm.matWorld_Lower = RotateMyArm(MyArm.matWorld, pi / 4)
Call d3DDevice.SetTransform(D3DTRANSFORMSTATE_WORLD, MyArm.matWorld_Lower)
Call d3DDevice.DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_VERTEX, _
MyArm.lower_arm_verts, 200, 0)

次の画像は、Bend サンプルでレンダリングしたバナナを、このテクニックを使用するために修正したものである。

ブレンドされたジオメトリと、ブレンドされていないジオメトリの違いは明らかである。この例でもその違いははっきり分かる。実際のアプリケーションでは、各モデルを "ジョイント" しても、それほどジョイント部が目立つことはない。しかし、ジョイント部が見苦しく表示されることもある。これは、モデル デザイナにとって今後の課題である。

Direct3D のジオメトリ ブレンディングでは、従来のセグメント モデル シナリオを使用することもできる。ジオメトリ ブレンディングを使用する場合にも負荷がかかる。つまり、分割されている個々のオブジェクトの表示品質を上げるためにレンダリング時にブレンディング計算が行われた末、これが適用される。これらの追加処理による影響を最小限に抑えるために、Direct3D ジオメトリ パイプラインは、可能な限りオーバーヘッドを発生させないでジオメトリをブレンドできるように最適化される。アプリケーションでは Direct3D のジオメトリ ブレンディング サービスを有効に使用することで、パフォーマンスへの深刻な影響を避けながら、キャラクタをより本物らしく表現することができる。