ミップマップを使用したテクスチャ フィルタリング (Direct3D 9)

ミップマップは連続したテクスチャで、各テクスチャは同じイメージを徐々に低い解像度で表したものです。 ミップマップ内の各イメージ (レベル) の高さと幅は、前のレベルより 2 つ小さい累乗です。 ミップマップは正方形である必要はありません。

ユーザーに近いオブジェクトには、解像度の高いミップマップ イメージが使用されます。 オブジェクトが遠くに表示されるにつれて、より低い解像度のイメージが使用されます。 ミップマップ処理によってレンダリングしたテクスチャの品質は向上しますが、使用するメモリは増加します。

Direct3D では、付属サーフェスのチェーンとしてミップマップが表現されます。 解像度が最も高いテクスチャはチェーンの先頭にあり、次のレベルのミップマップを添付データとして保有します。 さらに、そのレベルではミップマップ内の次のレベルの添付データを保有し、解像度が最も低いミップマップに至るまで続きます。

以下の各図は、これらのレベルの例を示したものです。 このビットマップ テクスチャは、主観視点の 3D ゲームにおけるコンテナーの警告表示を表しています。 ミップマップとして作成すると、解像度が最も高いテクスチャが先頭になります。 ミップマップ セット内のその後に続く各テクスチャの高さと幅は 2 の累乗ずつ小さくなります。 この場合、解像度が最も高いミップマップは 256 × 256 ピクセルです。 次のテクスチャは 128 × 128 です。 チェーン内の最後のテクスチャは 64 × 64 です。

この表示は、可視範囲から最大の距離にあります。 ユーザーがこの表示から遠く離れたところからゲームを始めた場合、ミップマップ チェーン内の最小のテクスチャ (この場合は 64 x 64 のテクスチャ) が表示されます。

illustration of a 64x64 texture of a danger sign

ユーザーが視点を警告表示に近づけるにつれて、徐々にミップマップ チェーン内の解像度が高いテクスチャが使用されます。 次の図の解像度は 128 x 128 です。

illustration of a 128x128 texture of a danger sign

次の図に示すように、ユーザーの視点が警告表示からの許容最短距離にあるとき、解像度が最も高いテクスチャが使用されます。

illustration of a 256x256 texture of a danger sign

これは、テクスチャの遠近の見え方をシミュレートする際の効率的な方法です。 1 つのテクスチャを多くの解像度でレンダリングするよりも、複数のテクスチャを各解像度で使用する方が時間がかかりません。

Direct3D では、ミップマップ セット内のどのテクスチャが目的とする出力に最も近い解像度であるかを評価し、そのテクセル空間にピクセルをマッピングすることができます。 最終画像の解像度がミップマップ セット内の複数のテクスチャ解像度の間にある場合、Direct3D では、両方のミップマップのテクセルを調べて、そのカラー値をブレンドします。

ミップマップを使用するには、アプリケーションでミップマップのセットを作成する必要があります。 アプリケーションでは、ミップマップ セットを現在のテクスチャ セットの最初のテクスチャとして選択することによって、ミップマップを適用します。 詳細については、「 テクスチャ ブレンド (Direct3D 9)」を参照してください。

次に、Direct3D でテクセルのサンプリングに使用するフィルタリング方法を設定する必要があります。 最も時間がかからないミップマップ フィルタリング方法は、Direct3D で最も近いテクセルを選択する方法です。 これを選択するには、D3DTEXF_POINT 列挙値を使用します。 Direct3D では、D3DTEXF_LINEAR 列挙値を使用すると、より適切なフィルタリング結果を生成することができます。 これによって最も近いミップマップが選択され、テクスチャ内の現在のピクセルがマッピングされる位置の周辺で、テクセルの加重平均が計算されます。

ミップマップ テクスチャは 3D シーンで使用され、シーンのレンダリングに必要な時間が短縮されます。 また、シーンのリアリティも増します。 ただし、多くの場合、大量のメモリを必要とします。

ミップマップのセットの作成

次の例は、アプリケーションで IDirect3DDevice9::CreateTexture メソッドを呼び出して、256x256、128x128、64x64、32x32、16x16 の 5 つのミップマップ レベルのチェーンを構築する方法を示しています。

// This code example assumes that m_d3dDevice is a
// valid pointer to a IDirect3DDevice9 interface

IDirect3DTexture9 * pMipMap;
m_pD3DDevice->CreateTexture(256, 256, 5, 0, D3DFMT_R8G8B8, 
    D3DPOOL_MANAGED, &pMipMap);

IDirect3DDevice9::CreateTexture で受け入れられる最初の 2 つのパラメーターは、最上位のテクスチャのサイズと幅です。 3 番目のパラメーターは、テクスチャ内のレベルの数を指定します。 これを 0 に設定すると、Direct3D はサーフェスのチェーンを作成します。各サーフェスの累乗は、前のサーフェスよりも 2 つ小さく、可能な最小サイズの 1x1 まで小さくなります。 4 番目のパラメーターは、このリソースの使用法を指定します。この場合、リソースの特定の使用法がないことを示すために 0 が指定されます。 5 番目のパラメーターは、テクスチャのサーフェス形式を指定します。 このパラメーターには、 D3DFORMAT 列挙型の値を使用します。 6 番目のパラメーターは、作成されたリソースを配置するメモリ クラスを示す D3DPOOL 列挙型のメンバーを指定します。 動的テクスチャを使用している場合を除き、D3DPOOL_MANAGEDをお勧めします。 最後のパラメーターは、 IDirect3DTexture9 インターフェイスへのポインターのアドレスを受け取ります。

Note

ミップマップ チェーン内の各サーフェスには、チェーン内の前のサーフェスの 2 分の 1 の寸法があります。 最上位のミップマップのサイズが 256 x 128 である場合、第 2 レベルのミップマップのサイズは 128 x 64、第 3 レベルは 64 x 32 というように小さくなり、最終的には 1 x 1 になります。 Levels では、チェーン内のミップマップの幅または高さが 1 より小さくなるようなミップマップ レベルを指定することはできません。 最上位のミップマップ サーフェスが 4 × 2 の単純な場合、Levels の有効最大値は 3 です。 最上位のサイズが 4 × 2 である場合、第 2 レベルのサイズは 2 × 1、第 3 レベルのサイズは 1 × 1 になります。 Levels の値が 3 よりも大きい場合、第 2 レベルのミップマップの高さが小数値になるので、許可されません。

 

ミップマップの選択と表示

IDirect3DDevice9::SetTexture メソッドを呼び出して、現在のテクスチャの一覧の最初のテクスチャとしてミップマップ テクスチャ セットを設定します。 詳細については、「 テクスチャ ブレンド (Direct3D 9)」を参照してください。

アプリケーションでミップマップ テクスチャ セットを選択した後、 D3DTEXTUREFILTERTYPE 列挙型の値を D3DSAMP_MIPFILTER サンプラー状態に割り当てる必要があります。 その後、Direct3D はミップマップ テクスチャ フィルタリングを自動的に実行します。 次のコード例では、ミップマップ テクスチャ フィルタリングの有効化を示します。

m_pD3DDevice->SetTexture(0, pMipMap);
m_pD3DDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);

アプリケーションでは、 IDirect3DTexture9::GetSurfaceLevel メソッドを使用し、取得するミップマップ レベルを指定することで、ミップマップ サーフェスのチェーンを手動で走査することもできます。 次の例では、ミップマップ チェーンを最高解像度から最小解像度まで走査します。

IDirect3DSurface9 * pSurfaceLevel;
for (int iLevel = 0; iLevel < pMipMap->GetLevelCount(); iLevel++)
{
    pMipMap->GetSurfaceLevel(iLevel, &pSurfaceLevel);
    // Process this level
    pSurfaceLevel->Release();
}

アプリケーションでは、ミップマップ チェーンを手動で走査して、ビットマップ データをチェーン内の各サーフェスに読み込む必要があります。 これは通常、チェーンを横断する唯一の理由です。 アプリケーションは、 IDirect3DBaseTexture9::GetLevelCount を呼び出すことによって、ミップマップ内のレベルの数を取得できます。

テクスチャ フィルタリング