作業の開始 (DirectXMath)
DirectXMath ライブラリは、単精度浮動小数点ベクトル (2D、3D、4D) または行列 (3×3 および 4×4) に対する算術演算と線形代数演算に最適で移植可能なインターフェイスを実装します。 このライブラリでは、整数ベクター操作のサポートが制限されています。 これらの操作は、グラフィックス プログラムによるレンダリングとアニメーションで広く使用されます。 倍精度ベクトル (longs、shorts、バイトを含む) はサポートされず、整数ベクトル演算は制限されています。
ライブラリは、さまざまな Windows プラットフォームで利用できます。 ライブラリには以前は使用できなかった機能が用意されているため、このバージョンは次のライブラリよりも優先されます。
- Xboxmath.h ヘッダーによって提供される Xbox Math ライブラリ
- D3DX 9 DLL によって提供される D3DX 9 ライブラリ
- D3DX 10 DLL を介して提供される D3DX 10 数学ライブラリ
- DirectX SDK と Xbox 360 XDK の xnamath.h ヘッダーによって提供される XNA Math ライブラリ
これらのセクションでは、作業の開始の基本について説明します。
ダウンロード
DirectXMath ライブラリは、Windows SDK に含まれています。 または、 GitHub/Microsoft/DirectXMath からダウンロードすることもできます。 このサイトには、関連するサンプル プロジェクトも含まれています。
Run-Timeシステム要件
DirectXMath ライブラリでは、ベクター操作が使用可能な場合に特殊なプロセッサ命令を使用します。 プログラムで "不明な命令例外" エラーが発生しないようにするには、DirectXMath ライブラリを使用する前に XMVerifyCPUSupport を呼び出してプロセッササポートをチェックします。
DirectXMath ライブラリのランタイム サポートの基本的な要件は次のとおりです。
- Windows (x86/x64) プラットフォームでの既定のコンパイルには、SSE/SSE2 命令のサポートが必要です。
- Windows RT プラットフォームでの既定のコンプリケーションには、ARM-NEON 命令のサポートが必要です。
- _XM_NO_INTRINSICS_を定義 した コンパイルでは、標準の浮動小数点演算のサポートのみが必要です。
注意
XMVerifyCPUSupport を呼び出すときは、DirectXMath.h> を含める前に windows.h を含<めます<>。 これは、windows.h のコンテンツ<を必要とするライブラリ内の唯一の関数であるため、DirectXMath.h を使用<するすべてのモジュールに windows.h>> を含める<必要>はありません。
設計の概要
DirectXMath ライブラリは、主に C++ プログラミング言語をサポートしています。 このライブラリは、ヘッダー ファイル DirectXMath*.inl、DirectXPackedVector.inl、DirectXCollision.inl のインライン ルーチンを使用して実装されます。 この実装では、高パフォーマンスコンパイラの組み込みを使用します。
DirectXMath ライブラリには、次の機能があります。
- SSE/SSE2 組み込みを使用した実装。
- 組み込みのない実装。
- ARM-NEON 組み込みを使用した実装。
ライブラリはヘッダー ファイルを使用して配信されるため、ソース コードを使用して独自のアプリ用にカスタマイズおよび最適化します。
マトリックス規則
DirectXMath では、行主行列、行ベクトル、および事前乗算が使用されます。 ハンドドネスは、使用される関数バージョン (RH と LH) によって決まります。それ以外の場合、関数は左利きまたは右利きのビュー座標で動作します。
参考までに、Direct3D はこれまで、左手座標系、行主行列、行ベクトル、事前乗算を使用してきました。 モダン Direct3D には、左と右の座標に対する厳密な要件はありません。通常、HLSL シェーダーは既定で列メジャー マトリックスを使用します。 詳細については、「 HLSL マトリックスの順序付け 」を参照してください。
基本的な使用方法
DirectXMath ライブラリ関数を使用するには、DirectXMath.h、DirectXPackedVector.h、DirectXColors.h、DirectXCollision.h ヘッダーを含めます。 ヘッダーは、Windows ストア アプリ用 Windows ソフトウェア開発キットに記載されています。
型の使用に関するガイドライン
XMVECTOR 型と XMMATRIX 型は、DirectXMath ライブラリの作業馬です。 すべての操作は、これらの型のデータを使用または生成します。 ライブラリを使用するには、それらの操作が重要です。 ただし、DirectXMath では SIMD 命令セットが使用されるため、これらのデータ型にはいくつかの制限があります。 DirectXMath 関数を適切に使用する場合は、これらの制限を理解することが重要です。
XMVECTOR は SIMD ハードウェア レジスタのプロキシ、XMMATRIX は 4 つの SIMD ハードウェア レジスタの論理グループのプロキシと考える必要があります。 これらの型には、正しく機能するために 16 バイトのアラインメントが必要であることを示す注釈が付いています。 コンパイラは、ローカル変数として使用される場合は、それらをスタックに自動的に正しく配置するか、グローバル変数として使用される場合はデータ セグメントに配置します。 適切な規則を使用すると、関数にパラメーターとして安全に渡すこともできます (詳細については、「 呼び出し規則 」を参照してください)。
ただし、ヒープからの割り当ては複雑です。 そのため、ヒープから割り当てられるクラスまたは構造体のメンバーとして XMVECTOR または XMMATRIX を使用するときは、必ず注意する必要があります。 Windows x64 では、すべてのヒープ割り当ては 16 バイトアラインメントされますが、Windows x86 の場合は 8 バイトアラインメントのみです。 16 バイトのアラインメントを使用してヒープから構造体を割り当てるオプションがあります (「 割り当てを適切に配置する」を参照してください)。 C++ プログラムでは、演算子 new/delete/new[]/delete[] オーバーロード (グローバルまたはクラス固有) を使用して、必要に応じて最適なアラインメントを適用できます。
注意
new/delete をオーバーロードして C++ クラスに直接配置を適用する代わりに、 pImpl イディオムを使用できます。 内部的に Impl クラスが _aligned_malloc 経由で配置されていることを確認した場合は、内部実装内で配置された型を自由に使用できます。 これは、'public' クラスが Windows ランタイム ref クラスである場合、または std::shared_ptr<> で使用することを意図している場合に適したオプションです。そうしないと、慎重な配置が中断される可能性があります。
ただし、多くの場合、クラスまたは構造体で XMVECTOR または XMMATRIX を直接使用しないようにする方が簡単でコンパクトです。 代わりに、XMFLOAT3、XMFLOAT4、XMFLOAT4X3、XMFLOAT4X4 などを構造体のメンバーとして使用します。 さらに、 Vector Loading 関数と Vector Storage 関数を使用して、 データを XMVECTOR または XMMATRIX ローカル変数に効率的に移動し、計算を実行し、結果を格納できます。 また、これらのデータ型の配列に対して直接効率的に動作するストリーミング関数 (XMVector3TransformStream、 XMVector4TransformStream など) もあります。
ベクトルの作成
定数ベクトル
多くの演算では、ベクター計算で定数を使用する必要があり、必要な値を 持つ XMVECTOR を読み込む方法はいくつかあります。
スカラー定数を XMVECTOR のすべての要素に読み込む場合は、 XMVectorReplicate または XMVectorReplicateInt を使用します。
XMVECTOR vFive = XMVectorReplicate( 5.f );
固定値が異なるベクター定数を XMVECTOR として使用する場合は、 XMVECTORF32、 XMVECTORU32、 XMVECTORI32、または XMVECTORU8 構造体を使用します。 これらは、 XMVECTOR 値を渡す任意の場所で直接参照できます。
static const XMVECTORF32 vFactors = { 1.0f, 2.0f, 3.0f, 4.0f };
注意
XMVECTOR で初期化子リストを直接使用しないでください (つまり、XMVECTOR v = { 1.0f, 2.0f, 3.0f, 4.0f })。 このようなコードは非効率的であり、DirectXMath でサポートされているすべてのプラットフォームで移植できるわけではありません。
DirectXMath には、コードで使用できる定義済みのグローバル定数が多数含まれています (g_XMOne、g_XMOne3、g_XMTwo、g_XMOneHalf、g_XMHalfPi、g_XMPiなど)。 DirectXMath.h ヘッダーで XMGLOBALCONST 値を検索します。
一般的な RGB 色 (赤、緑、青、黄など) には、一連のベクター定数があります。 これらのベクター定数の詳細については、「DirectXColors.h」および「DirectX::Colors 名前空間」を参照してください。
変数からのベクトル
1 つのスカラー変数からベクターを作成する場合は、「 XMVectorReplicate 」と「 XMVectorReplicateInt」を参照してください。
XMVECTOR v = XMVectorReplicate( f );
4 つのスカラー変数からベクターを作成する場合は、「 XMVectorSet 」と「 XMVectorSetInt」を参照してください。
XMVECTOR v = XMVectorSet( fx, fy, fz, fw );
ベクトルからのベクトル
特定のコンポーネントを変数に設定して別のベクターからベクターを作成する場合 は、Vector アクセサー関数の使用を検討できます。
XMVECTOR v2 = XMVectorSetW( v1, fw );
1 つのコンポーネントがレプリケートされた別のベクターからベクターを作成する場合は、 XMVectorSplatX、 XMVectorSplatY、 XMVectorSplatZ、 および XMVectorSplatW を使用します。
XMVECTOR vz = XMVectorSplatZ( v );
順序が変更されたコンポーネントを持つ別のベクターまたはベクトルのペアからベクターを作成する場合は、「 XMVectorSwizzle と XMVectorPermute」を参照してください。
XMVECTOR v2 = XMVectorSwizzle<XM_SWIZZLE_Z, XM_SWIZZLE_Y, XM_SWIZZLE_W, XM_SWIZZLE_X>( v1 ); XMVECTOR v3 = XMVectorPermute<XM_PERMUTE_0W, XM_PERMUTE_1X, XM_PERMUTE_0X, XM_PERMUTE_1Z>( v1, v2 );
メモリからのベクトル
- メモリから 1 つの float 値を読み込む方法については、「 XMVectorReplicatePtr、 XMVectorReplicateIntPtr、 XMLoadFloat、 および XMLoadInt」を参照してください。
- float 配列を読み込む一般的な方法は、 XMLoadFloat2、 XMLoadFloat3、 XMLoadFloat4、 XMLoadFloat3x3、 XMLoadFloat4x3、 XMLoadFloat4x4 です。
- DirectXMath には、さまざまなデータ構造と一般的な GPU 形式を処理するための豊富な種類と関連する読み込みとストアが含まれています。 ベクター読み込みとベクター ストアに関するページを参照してください。
ベクトルからのコンポーネントの抽出
SIMD 処理は、データが SIMD レジスタに読み込まれ、結果を抽出する前に完全に処理されるときに最も効率的です。 スカラーフォームとベクターフォーム間の変換は非効率的であるため、必要な場合にのみ行うことをお勧めします。 このため、スカラー値を生成する DirectXMath ライブラリの関数はベクター形式で返され、結果のベクター ( つまり、XMVector2Dot、 XMVector3Length など) にスカラー結果がレプリケートされます。 ただし、スカラー値が必要な場合は、その方法に関するいくつかの選択肢を次に示します。
1 つのスカラー回答が計算される場合は、 Vector アクセサー関数 を使用することが適切です。
float f = XMVectorGetX( v );
ベクターの複数のコンポーネントを抽出する必要がある場合は、ベクターをメモリ構造に格納し、読み取り戻す方法を検討してください。 次に例を示します。
XMFLOAT4A t; XMStoreFloat4A( &t, v ); // t.x, t.y, t.z, and t.w can be individually accessed now
ベクター処理の最も効率的な形式は、メモリ間ストリーミングを使用することです。ここで、入力データはメモリから読み込まれ ( ベクター読み込み関数を使用)、SIMD 形式で完全に処理され、メモリに書き込まれます ( ベクター ストア関数を使用)。
関連トピック