印刷用ページ       送信     
クリックして評価とフィードバックをお寄せください
MSDN
MSDN ライブラリ
テクニカルドキュメント
Direct X
 DirectX 頂点バッファ
DirectX 頂点バッファ

Microsoft Corporation

頂点バッファ

DirectX Developer Center Home Page に戻る

cpp.jpg vbuffer.cpp DirectX 7.0 SDK の頂点バッファ サンプルコード(日本語コメント)

頂点バッファ

本節では、Direct3D アプリケーションにおいて頂点バッファを理解し使用するために必要な概念を説明する。取り上げる項目は、次のとおり。

頂点バッファとは何か?

IDirect3DVertexBuffer7インターフェイスが示す頂点バッファとは、頂点データを含む単なるメモリバッファである。頂点バッファには、トランスフォームされた頂点または未トランスフォームの頂点、ライティングされた頂点またはライティングされない頂点など、IDirect3DDevice7インターフェイスの頂点バッファ レンダリング メソッドを使用してレンダリング可能なあらゆる種類の頂点を入れることができる。頂点バッファ内の頂点を処理して、トランスフォーム、ライティング、クリッピング フラグの生成などの操作を行う (トランスフォームは常に行われる)。

頂点バッファは柔軟なので、トランスフォームされたジオメトリを再使用するための理想的なステージ ポイントとなる。1 つの頂点バッファを作成、トランスフォーム、クリップして、挿入されたレンダリング状態が変化しても、シーン内にモデルを必要な数だけ再トランスフォームしないでレンダリングできる。これは、マルチ テクスチャを使用するモデルのレンダリングにおいて非常に有用である。ジオメトリを一度トランスフォームすれば、要求されたテクスチャの変更に合わせてレンダリングステートの変更を間に挿入して、必要に応じてその一部をレンダリングできる。頂点を処理した後で変更したレンダリング状態は、次に頂点を処理するときに有効になる。詳細については、「頂点の処理」を参照すること。

頂点バッファのジオメトリを最適化すれば、頂点操作とレンダリングについて最高のパフォーマンスを得ることができる。「頂点バッファの最適化」を参照すること。

注意 内部的には、頂点バッファは、メモリ管理サービス用に DirectDrawSurface オブジェクトを使用する。その結果、頂点バッファ メモリにアクセスするセマンティクスは、DirectDrawSurface オブジェクトのセマンティクスに類似する。 実際に IDirect3DVertexBuffer7::Lock メソッドは、 IDirectDrawSurface7::Lock メソッドと同じフラグを受け付ける。詳細については、「頂点バッファの内容へのアクセス」 を参照すること。

頂点バッファの記述

頂点バッファをその機能について記述する。頂点バッファは、システム メモリ内にだけ存在できるのか、書き込み操作だけに使用されるのか、頂点バッファが含むことができる頂点の種類と数、頂点バッファが作成されてから最適化されたかどうかなどを記述する。これらの特性はすべて D3DVERTEXBUFFERDESC 構造体の中に保持される。

頂点バッファ記述は、システムがどのように頂点バッファを作成するかを指定し、既存のバッファがどのようにして作成されたかをアプリケーションに知らせる (また、最適化されたかどうかを知らせる)。新しい頂点バッファを作成するには、完全な記述を指定しなければならない。また、空の記述構造体を渡すと、以前作成した頂点バッファの機能がシステムにより記入される。こうしたタスクの詳細については、「頂点バッファの作成」「頂点バッファ記述の取得」を参照すること。

ほとんどの DirectX 構造体に共通の dwSize メンバは、構造体バージョンの識別に使用されるため、構造体がメソッドで使用される前に、構造体のサイズを設定しなければならない。dwCaps 構造体メンバは、一般能力フラグを含む。D3DVBCAPS_SYSTEMMEMORY フラグは、システムが頂点バッファをシステム メモリ内に作成すべき (または既に作成済み) であることを示す。アプリケーションがソフトウェア レンダリング デバイスを使用する場合は、明示的にシステム メモリ頂点バッファを作成すること。そうでない場合は、フラグを省略して、システムに最良の位置を判断させるとよい。明示的なシステム メモリ頂点バッファの詳細については、「デバイスの種類と頂点処理の要求事項」を参照すること。

dwCaps に D3DVBCAPS_WRITEONLY フラグを指定すると、頂点バッファ メモリが書き込み操作だけに使用されるという意味をシステムに伝達する。これによりドライバは、処理とレンダリングをできるだけ高速にする最良のメモリ位置に頂点データを自由に配置する。このフラグを使用する頂点バッファからの読み出しでは、メモリ アクセス時間が非常に低速になることがある。D3DVBCAPS_WRITEONLY フラグを使用しない場合、一部の処理とレンダリングの速度を犠牲にするが、読み出し操作が非効率的になる位置にドライバがデータを置くことは少なくなる。フラグを何も指定しないと、アプリケーションは頂点バッファ内でデータの読み出し操作と書き込み両方の操作を行うものと見なされる。

注意: D3DVBCAPS_OPTIMIZED フラグは、頂点バッファの作成中には使用されない。システムは、頂点バッファを最適化するときにこの能力を設定する。

最後の 2 つの D3DVERTEXBUFFERDESC 構造体メンバは、他の能力を記述する。dwFVF メンバには、バッファが含むことができる頂点の種類を指定するフレキシブル頂点フォーマット フラグの組合せが含まれる。頂点バッファの容量は、頂点バッファが含むことができる頂点の合計数によって測定され、dwNumVertices メンバに与えられる。

デバイスの種類と頂点処理の要求事項

トランスフォームやライティングを含む頂点処理にかかる時間は、頂点バッファがメモリ上のどこにあり、どのタイプのレンダリング デバイスが使われるかに大きく左右される。アプリケーションは、頂点バッファを作成する際にメモリの配置を制御する。D3DVBCAPS_SYSTEMMEMORY 能力フラグが頂点バッファ記述の中でセットされている場合、頂点バッファはシステム メモリ内に作成される。この機能が使用されない場合は、デバイスドライバが頂点バッファの配置に最適なメモリ(ドライバ オプティマル メモリと呼ばれる)を決定する。ドライバ オプティマル メモリはローカルのビデオ メモリ、非ローカルのビデオ メモリ、システム メモリのいずれにも配置可能である。

Direct3D は IDirect3DDevice7::DrawPrimitiveVB メソッドや、 IDirect3DDevice7::DrawIndexedPrimitiveVB メソッド、 IDirect3DVertexBuffer7::ProcessVertices メソッドを呼び出したときに頂点処理操作を適用する。これらの操作には、トランスフォームやライティングが含まれる。これらの呼び出しにかかる時間は、バッファのメモリ内の配置や、その配置が使用するデバイスのタイプ(ハードウェアまたはソフトウェア)に対して最適かどうかに左右される。

頂点バッファのメモリ上の配置(システムまたはドライバによる最適化)を決定する際に留意すべき点は、テクスチャと同じである。テクスチャの場合、ハードウェアによるラスタライズでは、テクスチャがドライバ オプティマル メモリに配置されているときに、より高速に処理され、ソフトウェアによるラスタライズでは、システム メモリにテクスチャを配置した方が速く処理される。同様に、頂点の処理(トランスフォームやライティングを含む)をハードウェアで行う場合は頂点バッファをドライバ オプティマル メモリ上に置いた方がよく、ソフトウェアで頂点処理を行う場合はシステム メモリ上に頂点バッファを置いた方がよい。

注: ProcessVertices メソッドによる頂点の処理は、常にソフトウェアで行われるため、転送元頂点バッファは常にシステム メモリに置く必要がある。転送先頂点バッファは、ドライバ オプティマル メモリに配置してもよい。ただし、この場合はアプリケーションによって直接ロックしたり、読み込んだりしてはいけない。また、ProcessVertices への呼び出しの際にクリッピングが要求される場合もこの方法は使えない(頂点バッファのレンダリング メソッドが呼ばれたときに頂点バッファからの読み出しを行う必要があるため)。

アプリケーションが独自の頂点処理を実行する(トランスフォーム、ライティング、クリッピングが行われた頂点を頂点バッファ レンダリング メソッドに渡す)場合、アプリケーションはドライバ オプティマル メモリ上に配置された頂点バッファに直接頂点を書き込むことができる。このテクニックによって、後の冗長なコピー操作を防ぐことができる。しかし、このテクニックは、アプリケーションが頂点バッファからデータを読み戻す場合には使えないことに留意されたい。ホストによるドライバ オプティマル メモリからの読み込み操作は、非常に遅いからである。そのため、処理中に読み出す必要がある場合や、バッファに不規則にデータを書き込む場合は、システム メモリ上に頂点バッファを配置した方がよい。

Direct3D の頂点処理機能を (トランスフォームされていない頂点を頂点バッファ レンダリング メソッドに渡すことによって)使う場合、デバイスのタイプによって、処理がハードウェアで行われるかソフトウェアで行われるかが決まる。デバイスが TnLHAL デバイス( IID_IDirect3DTnLHALDevice ) の場合は、頂点処理がハードウェアで行われるため、処理を高速に行うために頂点バッファはドライバ オプティマル メモリ上に作成されるべきである。デバイスがHALデバイス( IID_IDirect3DHALDevice )の場合は、頂点処理がソフトウェアで行われるため、頂点バッファはシステムメモリ上に作成されるべきである。RGB デバイス ( IID_IDirect3DRGBDevice ) でレンダリングを行う場合、すべての頂点バッファはシステム メモリ上に作成すべきである。

次の C++ スタイルの擬似コードは頂点バッファを作成し、処理する際に適用すべきロジックをまとめたものである。


            if (ソフトウェアでラスタライズする)
                システム メモリ頂点バッファ (D3DVBCAPS_SYSTEMMEMORY) を使う
            else if (アプリケーションで頂点処理を行う)
                if (アプリケーションは読み込みを行わず、不規則な書き込みも行わない)
                    ドライバ オプティマル頂点バッファを使う
                else
                    システム メモリ頂点バッファ (D3DVBCAPS_SYSTEMMEMORY) を使う
            else // Direct3D 頂点処理
                if (TnLHAL デバイス)
                    ドライバ オプティマル頂点バッファを使う
                else if (HAL デバイス)
                    システムメモリ頂点バッファ(D3DVBCAPS_SYSTEMMEMORY) 
          

を使う頂点バッファの使用

以下のトピックにより、アプリケーションが頂点バッファを使用して動作するときに実行する、一般的なタスクを説明する。

頂点バッファの作成

次の図は C++ で1つの頂点バッファを作成するのに必要なステップを示す。

vertex1.gif

注意 「Direct3D へのアクセス」で述べたように、DirectDraw コンポーネントは 2 つの COM オブジェクトを含んでいる。最新のオブジェクト( DirectDraw7 と呼ばれるもので、DirectDrawCreateEx 関数を呼び出すことによって作成される)は IDirect3D7 インターフェイスを公開する唯一のオブジェクトである。また、IDirect3DVertexBuffer7 インターフェイスを公開する頂点バッファを生成できる唯一のオブジェクトでもある。この方法で作成された Direct3Ddevice オブジェクトは従来の Direct3D インターフェイスを公開しない。従来の Direct3D の方式を必要とするアプリケーションは、DirectDrawCreate メソッドを使って DirectDraw オブジェクトを作成し、必要とされる旧式のオブジェクトを作らなければならない。

4 つのパラメータを受け取る IDirect3D7::CreateVertexBuffer メソッドを呼び出して頂点バッファ オブジェクトを作成する。第 1 パラメータは、必要な頂点フォーマット、バッファ サイズ、および一般機能を記述する D3DVERTEXBUFFERDESC 構造体のアドレスである。これらの機能については、「頂点バッファの記述」で説明した。通常は、頂点バッファ用に最良のメモリ位置 (システム メモリまたはディスプレイ メモリ) をシステムが自動的に判断する。ただし、ソフトウェア デバイスは、明示的なシステム メモリ頂点バッファのみ使用できる。詳細については、「デバイスの種類と頂点バッファ処理の要求事項」を参照すること。

CreateVertexBuffer が受け取る第 2 パラメータは、呼び出しに成功したとき頂点バッファ オブジェクトの新しい IDirect3DVertexBuffer7 インターフェイスを指すポインタが設定される変数のアドレスである。第 3 パラメータは、表示領域の外に存在する頂点のクリッピング情報を (クリップ フラグ形式で) 含む能力を頂点バッファに与えるかどうかを指定する。「クリッピング可能」頂点バッファを作成するにはこのパラメータを 0 に設定し、クリップ フラグを含むことができない頂点バッファを作成するには D3DDP_DONOTCLIP フラグを含める。D3DDP_DONOTCLIP フラグが適用できるのは、トランスフォームされた頂点を頂点バッファに含めるよう指示した場合である ( D3DFVF_XYZRHW フラグを記述構造体の dwFVF メンバに含める)。未トランスフォームの頂点 (D3DFVF_XYZ フラグ) をバッファに含めるよう指示した場合、CreateVertexBuffer メソッドは D3DDP_DONOTCLIP フラグを無視する。クリッピング フラグは追加メモリを占有するため、クリッピング可能頂点バッファは、クリッピング フラグを含むことができない頂点バッファよりわずかに大きくなる。リソースは頂点バッファが作成されるとき割り当てられるため、クリッピング可能頂点バッファは先に要求しておかなければならない。

注意: クリップ フラグを含むことができる頂点バッファを作成しても、必ずしも頂点の処理中にクリップ フラグを生成するよう要求したり、レンダリング中にクリップ フラグを適用するよう要求しなくてもよい。各頂点バッファ レンダリング メソッドは、D3DDP_DONOTCLIP フラグを受け取ると、レンダリング時にクリッピングをバイパスする。また、IDirect3DVertexBuffer7::ProcessVertices メソッドは D3DVOP_CLIP フラグを受け付けるが、指定しないと、頂点の処理中にシステムがクリップ フラグを生成することを防止できる。

クリップ サポートなしで作成された頂点バッファに対してクリップ フラグを生成する方法はない。無理に生成しようとして、IDirect3DVertexBuffer7::ProcessVertices メソッドを使用すると、デバッグ ビルドの場合は失敗し、D3DERR_INVALIDVERTEXFORMAT が返される。クリップ フラグを含まないトランスフォーム頂点バッファからレンダリングするとき、レンダリング メソッドはクリッピングの要求を無視する。

CreateVertexBuffer が受け取る最後のパラメータは、将来の COM 集約機能との互換性のために用意されている。現在、集約はサポートされていないので、このパラメータは NULL にセットしなければならない。

次の例は、頂点バッファの作成がC++のコードではどのようになるかを示す。


                /*
                 * この例で、変数 g_lpD3D は、Direct3D オブジェクトが示す
                 * IDirect3D7 インターフェイスのアドレス、g_vbVertexBuffer
                 *はLPD3DVERTEXBUFFER7型の変数である。
                 * 変数 fIsAHardwareDevice は BOOL 変数であり、
                 * アプリケーションの初期化で設定されるものとする。
                 *この例では、g_lpD3DはDirect3Dオブジェクトによって公開
                 *されたIDirect3D7インターフェイスのアドレス、g_vbVertexBufferは
                 * LPD3DVERTEXBUFFER7型の変数、fIsAHardwareDeviceはアプリケーションの
                 *初期化時に設定されるBOOL型の変数である。
                 */
                D3DVERTEXBUFFERDESC vbdesc;
                ZeroMemory(&vbdesc, sizeof(D3DVERTEXBUFFERDESC));
                vbdesc.dwSize= sizeof(D3DVERTEXBUFFERDESC);
                vbdesc.dwCaps        = 0L;
                vbdesc.dwFVF         = D3DFVF_VERTEX;
                vbdesc.dwNumVertices = NUM_FLAG_VERTICES;
                //ハードウェア デバイスでない場合は頂点バッファを
                // システム メモリに作成
                if( !fIsAHardwareDevice )
                    vbdesc.dwCaps |= D3DVBCAPS_SYSTEMMEMORY;
                // クリッピング可能な頂点の作成
                if(FAILED(g_lpD3D->CreateVertexBuffer(&vbdesc,
                                                      &g_pvbVertexBuffer, 0L,
                                                      NULL)))
                    return E_FAIL;
          

頂点バッファの内容へのアクセス

頂点バッファ オブジェクトを使うと、頂点データに割り当てられたメモリにアプリケーションから直接アクセスできる。 IDirect3DVertexBuffer7::Lock メソッドを呼び出して頂点バッファ メモリを指すポインタを取得し、次に必要に応じてメモリにアクセスし、新しい頂点データをバッファに設定したり、既に設定されているデータを読み出したりする。

IDirect3DVertexBuffer7::Lock メソッドは 3 つのパラメータを受け取る。第 1 パラメータ dwFlags は、メモリをどのようにロックするかをシステムに伝え、アプリケーションがバッファ内でどのようにデータにアクセスするかというヒントをシステムに与える (読み出し専用または書き込み専用のヒントを与えると、ドライバは要求されたアクセス種別に最良のパフォーマンスを与えるようにメモリをロックできる。ヒントは必須ではないが、状況によってはメモリ アクセスのパフォーマンスを改善できる)。頂点バッファは DirectDrawSurface オブジェクトを使用して頂点データを格納するため、IDirect3DVertexBuffer7::Lock が受け取るフラグは IDirectDrawSurface7::Lock メソッドが受け取るフラグと同一であり、結果も同一である。

Lock メソッドが受け取る第 2 パラメータ lplpData は、LPVOID 変数のアドレスで、呼び出しが成功した場合は、頂点バッファ メモリを指す有効なポインタが設定される。最後のパラメータ lpdwSize は、呼び出しが返された後、lplpData が指すバッファのバイト単位でのサイズが設定される変数のアドレスである。アプリケーションがバッファ サイズの情報を必要としない場合は、lpdwSize に NULL を設定できる。

パフォーマンスの注意: アプリケーションが頂点バッファ メモリから読み出すだけの場合は、DDLOCK_READONLY フラグを使用すること。このフラグを含めると、Direct3D が内部手順を最適化するので効率が上がる。ただし、メモリへのアクセスは読み出し専用になる。DDLOCK_READONLY フラグでロックしたメモリに書き込むことは可能であるが、予期せぬ結果になることがある。また、D3DVBCAPS_WRITEONLY フラグで作成した頂点バッファから読み出そうとすると、バッファを読み出し専用にロックした場合でも極端に低速になることがある。

C++では、頂点バッファに割り当てられたメモリに直接アクセスできる。この場合は、割り当てられたメモリに正しくアクセスするように注意を払う必要がある。さもなければ、そのメモリを不正にレンダリングしてしまうことになる。配置されたバッファ内のある頂点を別の場所に移動する場合は、アプリケーションが使用する頂点フォーマットのストライドを使用することが望ましい。頂点バッファ メモリ自体は、フレキシブル頂点フォーマットで指定された頂点の単純な配列である。アプリケーションが従来からの頂点構造体を使用している場合、D3DVERTEX、D3DLVERTEX、および D3DTLVERTEX のストライドは、単純にバイト単位の構造体のサイズである。従来からのフォーマットとは違う頂点フォーマットを使用している場合は、定義した任意の頂点フォーマット構造体のストライドを使用する。頂点バッファ記述に含まれるフレキシブル頂点フォーマット フラグを検証して、実行時の各頂点のストライドを計算できる。次の表は、各頂点コンポーネントのサイズを示す。

頂点フォーマットフラグ

サイズ

D3DFVF_DIFFUSE

sizeof(DWORD)

D3DFVF_NORMAL

sizeof(float) × 3

D3DFVF_SPECULAR

sizeof(DWORD)

D3DFVF_TEXn

sizeof(float) × 2 × n

D3DFVF_XYZ

sizeof(float) × 3

D3DFVF_XYZRHW

sizeof(float) × 4

頂点フォーマットに存在するテクスチャ座標の数は、D3DFVF_TEXn フラグで記述される (n は 0 から 8 までの値)。頂点フォーマットのテクスチャ座標セットは、float 変数 2 個分の空間を占めるため、その数のテクスチャ座標に要求されるメモリを計算するには、テクスチャ座標セットの数にテクスチャ座標 1 セットのサイズを乗ずる。

特定の頂点にアクセスするには、合計頂点ストライドを使用して、メモリ ポインタを必要なだけインクリメントまたはデクリメントする。

頂点の処理

頂点バッファ内の頂点を処理するには、デバイスに対して現在のトランスフォーム行列を適用する。オプションで、ライティング、クリップ フラグの生成、および範囲の更新などの頂点操作も適用できる。IDirect3DVertexBuffer7 インターフェイスは、頂点を処理するために IDirect3DVertexBuffer7::ProcessVertices メソッドを開示する。転送元バッファではなく転送先頂点バッファの ProcessVertices メソッドを呼び出して、頂点を転送元頂点バッファから転送先頂点バッファに処理する。このメソッドが受け取る 7 つのパラメータには、実行する操作、転送元頂点バッファの IDirect3DVertexBuffer7 インターフェイスの位置、頂点操作を行うレンダリング デバイス、およびメソッドのターゲットとなる頂点の位置と数を記述する。呼び出しの後、転送先バッファには処理された頂点データが設定されるが、転送元バッファは変化しない。

注意: ProcessVertices メソッドによる頂点の処理は、常にソフトウェアで行われることに注意してください。

頂点の処理を準備するときは、第 1 パラメータ dwVertexOp に行いたい頂点操作を設定する。D3DVOP_TRANSFORM フラグは必ず含めなければならず、含めないとメソッドは失敗する。残りの操作はオプションである。頂点の処理に、頂点のライティング、クリップ フラグの生成、範囲の更新など、オプションのフラグはどのような組合せでも含めることができる。

第 2 パラメータ dwDestIndex と第 3 パラメータ dwCount は、頂点が置かれる転送先バッファのインデックスと、処理されて転送先バッファ内に置かれる頂点の合計数を表わす。第 4 パラメータ lpSrcBuffer は、転送元頂点を含む IDirect3DVertexBuffer7 頂点バッファ オブジェクトのアドレスに設定する。dwSrcIndex は、メソッドが頂点の処理を開始する最初のインデックスを指定する (処理される転送元頂点の合計数は dwCount パラメータにより示される)。lpD3DDevice パラメータには、頂点を処理するレンダリング デバイスの IDirect3DDevice7 インターフェイスのアドレスを設定する。

最後のパラメータ dwFlags は、このメソッドの特殊な処理オプションを決定する。このパラメータを 0 に設定すると、デフォルトの頂点処理が行われ、D3DPV_DONOTCOPYDATA に設定するといくつかの状況下で最適化処理が行われる。dwFlags を 0 に設定した場合、頂点操作によって影響を受けない転送先頂点バッファの頂点フォーマットのコンポーネントは、転送元頂点バッファからコピーされるか(転送元バッファにある場合)または 0 にセットされる。しかし、D3DPV_DONOTCOPYDATA を使った場合はProcessVertices メソッドへの呼び出しの際に計算されない転送先バッファの頂点フォーマットの頂点コンポーネントはすべてそのまま残される。頂点をライティングせずに、トランスフォームする目的でProcessVertices メソッドを呼び出した場合( D3DVOP_TRANSFORM 頂点処理を単独使用)を想像してみよう。転送先頂点バッファがD3DFVF_TLVERTEX 頂点フォーマットを使用している場合、D3DPV_DONOTCOPYDATA フラグを指定することによってシステムは転送先バッファの拡散、反射、テクスチャ座標のコンポーネントを無視するようになる。その結果、処理とデータ転送のオーバーヘッドは軽くなる -- 目的は単なる頂点のトランスフォームであるため、これでよい。D3DPV_DONOTCOPYDATA を使わなければ、アプリケーションでは使用する必要がないにもかかわらず、システムはライティングやテクスチャ座標のコンポーネントを転送先バッファの頂点にコピーする。D3DPV_DONOTCOPYDATA フラグを使えば頂点の処理に必要とされるシステム動作を大幅に削減できる。ProcessVertices を使用するアプリケーションでは、静的頂点コンポーネントを直接転送先頂点バッファに直接コピーすることができ、システムによる転送元バッファから転送先バッファへのコピーは不要である。

互換性のある頂点フォーマットを使用する頂点バッファを作成するように注意すること。少なくとも、転送元バッファは未トランスフォームの頂点を含み (バッファ記述の頂点フォーマットに D3DFVF_XYZ フラグを使用)、転送先バッファはトランスフォームされた頂点を含むものとする ( D3DFVF_XYZRHW フラグを使用)。ライティングまたはクリッピング サービスのために、転送元と転送先の頂点フォーマットは適切なフィールドを含むことが要求される。たとえば、頂点フォーマットに頂点法線を含めていない場合は、頂点のライティングを要求しないこと。同様に、クリッピング機能なしで作成された転送先頂点バッファに、システムがクリップ フラグを生成するよう要求することはできない。互換性のないバッファで操作を行おうとすると、デバッグ ビルドの場合、失敗する。

転送元または転送先の頂点バッファがロックされているときは、頂点を処理することはできない。

頂点バッファの最適化

頂点バッファを最適化すると、システムはバッファの内容を修正し、頂点の処理またはレンダリングのパフォーマンスが良好になる。頂点がどのように最適化されるかは、プラットフォーム固有であり、変更されることがある。このため、最適化された頂点バッファの内容をロックしたり、アクセスすることはできない。

ソフトウェア、ハードウェアの両デバイスのパフォーマンスは、最適化された頂点バッファの恩恵を受ける。頂点バッファの最適化は、頂点処理がハードウェアで行われるかまたはソフトウェアで行われるかによって異なる。D3DVBCAPS_SYSTEMMEMORY フラグを使って作成された頂点バッファは、ソフトウェアによる頂点処理の目的にのみ最適化され、IDirect3DVertexBuffer7::ProcessVertices メソッドまたは( TnLHAL ではなく)HAL デバイスでの頂点バッファ レンダリング メソッドのみが使用できる。D3DVBCAPS_SYSTEMMEMORY フラグを使わずに作成された頂点バッファ(ドライバ オプティマル メモリを使用)はハードウェアによる頂点処理用に最適化され、TnLHAL デバイスでのレンダリング メソッドのみが使用できる。最適化された頂点バッファはIDirect3DVertexBuffer7::ProcessVertices や IDirect3DVertexBuffer7::ProcessVerticesStrided メソッドの転送先バッファとして使用することはできない。

IDirect3DVertexBuffer7::Optimize メソッドを呼び出して頂点バッファを最適化する。頂点バッファを最適化すると、頂点操作とレンダリングのパフォーマンスが改善される。IDirect3DVertexBuffer7::Optimize メソッドは 2 つのパラメータを受け取るが、そのうち 1 つだけが使用される。lpD3DDevice パラメータに頂点を最適化するデバイスのアドレスを設定し、最後のパラメータに 0 を設定する。ロックされた頂点バッファは、アンロックするまで最適化できない。

頂点を最適化されたフォーマットに保つことによりパフォーマンスを改善できる。ただし、最適化された頂点バッファは、スタティック ジオメトリだけに使用する。頂点バッファを一度最適化すると、最適化された内容を変更するためにロックすることはできないからである。頂点バッファを最適化した場合、IDirect3DVertexBuffer7::ProcessVertices メソッドと頂点バッファ レンダリング メソッドだけで使用できる。

頂点バッファからのレンダリング

「レンダリング」で説明したように、レンダリング デバイスは、頂点バッファからプリミティブをレンダリングするメソッドを提供する。これらのメソッドは、他のほとんどのレンダリング メソッドに非常によく似た動作をするが、少し違うパラメータを使用して、頂点バッファ オブジェクトに対応する。

次のトピックでは、一般的なレンダリング状態を紹介し、頂点バッファ レンダリング メソッドの呼び出しに特有の問題について説明する。

頂点バッファ レンダリングについて

アプリケーションが頂点を頂点バッファからレンダリングする一般的なステートは 2 つある。最も基本的なレベルで、2 つのステートは、「レンダリング時」に頂点バッファ内にある頂点の種類によって分けられる。しかし、間接的には、アプリケーションの使用する手順が、いつ頂点操作とレンダリング操作を実行するかを決定する。次の図表で、未トランスフォーム頂点バッファからのレンダリング処理を説明する。 

Dd188510.vertex2(ja-jp,MSDN.10).gif

 上記の図に示すように、IDirect3DDevice7::DrawPrimitiveVB メソッドと IDirect3DDevice7::DrawIndexedPrimitiveVB メソッドには未トランスフォーム頂点バッファからのレンダリングの機能がある。この場合、レンダリング メソッドを呼び出すたびに、システムは頂点操作とレンダリング操作を行う。この方法を使用しても、従来の DrawPrimitive レンダリング メソッド以上に改善されたパフォーマンスは得られないが、状況によってはより便利である。次の図に示すように、可能であればトランスフォームされた頂点データを再使用して、パフォーマンスを最適化できる。 

Dd188510.vertex3(ja-jp,MSDN.10).gif

この場合、アプリケーションは 2 つの頂点バッファを作成する。1 つは未トランスフォームのジオメトリ用で、もう 1 つはトランスフォームされたジオメトリ用である。IDirect3DVertexBuffer7::ProcessVertices が呼び出されたとき、第 2 バッファはトランスフォームされた頂点データを取得する。ProcessVertices メソッドは、転送元バッファ内の頂点を読み出し、要求された頂点操作を行い、結果を転送先バッファに入れる。未トランスフォームの頂点をレンダリングするように、トランスフォームされた頂点に対して同じレンダリング メソッドを呼び出すことができる。ただし、未トランスフォームの頂点と異なり、Direct3D は頂点バッファ内のデータがトランスフォームされていることを自動的に検出して、直ちにラスタライズされるよう転送する。不必要なトランスフォームを省略して、パフォーマンスのオーバーヘッドは最小に保たれる。

注意 IDirect3DVertexBuffer7 インターフェイスはストライドされた頂点を転送先頂点バッファに送るための新しいメソッド IDirect3DVertexBuffer7::ProcessVerticesStrided を提供する。

頂点バッファの内容を最適化すると、パフォーマンスをさらに向上できる。詳細については、「頂点バッファの最適化」を参照すること。

頂点バッファ レンダリング メソッドの呼び出し

IDirect3DDevice7::DrawPrimitiveVB メソッドは、IDirect3DDevice7::DrawPrimitive メソッドに対応する。同じように、DrawPrimitiveVB メソッドも、頂点が頂点バッファ内に順序どおりに現れると見なす。

DrawPrimitiveVB メソッドは 5 つのパラメータを受け取る。d3dptPrimitiveType パラメータには、D3DPRIMITIVETYPE 列挙型メンバの 1 つを使用して、レンダリングするプリミティブの種類を設定する。第 2 パラメータ lpd3dVertexBuffer には、頂点を含む頂点バッファのアドレスを指定し、次に、dwStartVertex パラメータと dwNumVertices パラメータに、レンダリングする第 1 頂点と頂点の合計数を示す値を設定する。頂点バッファに含まれるすべての頂点をレンダリングする必要はないが、プリミティブの種類に応じた適切な数の頂点を使用しなければならない ( D3DPRIMITIVETYPE の参照情報に記述)。最後のパラメータ dwFlags は、レンダリングの動作を決定する。このフラグは他のレンダリング メソッドで使用されるフラグと同一である。レンダリング中にフラグを設定して、ライティングとクリッピングを有効にしたり、クリップ範囲を更新したりすることができる。

IDirect3DDevice7::DrawIndexedPrimitiveVB メソッドは、頂点バッファの頂点にインデックスを付けて、プリミティブをレンダリングする。最初の 2 つのパラメータは、DrawPrimitiveVB メソッドのパラメータと同一である。第3および第4 パラメータはバッファ内の最初の頂点のインデックスとレンダリングすべき頂点の総数である。第5パラメータlpwIndices には、レンダリングする頂点にアクセスするためにメソッドが使用する WORD インデックスの正しい順序で並べられた配列のアドレスを設定し、第 6 パラメータ dwIndexCount には、配列に含まれるインデックス値の数を設定する。dwFlags パラメータは、DrawPrimitiveVB メソッドの対応するパラメータと同一である。

バッファ内の頂点フォーマットに頂点法線が含まれていない場合は、頂点バッファ レンダリング メソッドにライティングを要求することはできない。また、 D3DDP_DONOTCLIP フラグを使用して作成された、トランスフォームされた頂点バッファからのレンダリングを行う場合、レンダリング メソッドに頂点のクリップを要求することはできない (これは、未トランスフォームの頂点バッファに対しては要求できる。レンダリング時にシステムがクリッピング可能なバッファを作成するからである)。利用できないサービスを要求しても、デバッグ ビルドでメソッドが失敗する原因になることはないが、サービスは適用されない。

ハードウェア アクセラレーション デバイスとは異なり、ソフトウェア デバイスは D3DVBCAPS_SYSTEMMEMORY フラグで作成された頂点バッファからのレンダリングだけが可能である。詳細については、頂点バッファ記述の取得

アプリケーションでは、しばしば、実行時に既存の頂点バッファについての情報を取得することが必要になる。この取得は、Direct3D では、IDirect3DVertexBuffer7::GetVertexBufferDesc メソッドにより可能である。このメソッドは、現在の記述を取得する任意の頂点バッファの IDirect3DVertexBuffer7 インターフェイスを使用して呼び出す。

GetVertexBufferDesc メソッドが受け取るパラメータは 1 つだけである。適切に初期化された D3DVERTEXBUFFERDESC 構造体のアドレスである。構造体を初期化するには、dwSize メンバを構造体のバイト単位のサイズに設定し、残りのメンバは 0 に設定する。メソッドが返ると、頂点バッファ機能、バッファ内の頂点フォーマット、バッファが含むことができる頂点の合計数についての情報が構造体に設定されている。

注意: 頂点バッファを最適化すると、D3DVBCAPS_OPTIMIZED 能力フラグがD3DVERTEXBUFFERDESC 構造体のdwCaps メンバに設定される。このフラグが設定されると、頂点バッファはロックできなくなる。最適化された頂点の内容を利用できるのはレンダリング メソッドと 頂点バッファ処理メソッド(IDirect3DVertexBuffer7::ProcessVertices および IDirect3DVertexBuffer7::ProcessVerticesStrided)だけである。

一般的な情報については、「頂点バッファの記述」を参照すること。

© 2009 Microsoft Corporation. All rights reserved. 使用条件 | 商標 | プライバシー
Page view tracker