次の方法で共有


ミップマップによるテクスチャー フィルタリング (Direct3D 9)

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

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

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

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

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

Danger sign

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

Danger sign

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

Danger sign

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

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

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

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

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

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

次の例は、アプリケーションで IDirect3DDevice9::CreateTexture メソッドを呼び出して、256 × 256、128 × 128、64 × 64、32 × 32、および 16 × 16 という 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 番目のパラメーターでは、テクスチャー内のレベルの数を指定します。これをゼロに設定すると、サーフェスのチェーンが作成されます。各サーフェスは直前のものよりも 2 の累乗ずつ小さくなり、最終的には、有効な最小サイズである 1 x 1 になります。4 番目のパラメーターでは、このリソースの使用方法を指定します。この場合、リソースに特定の使用方法がないことを示す 0 が指定されています。5 番目のパラメーターでは、テクスチャーのサーフェス フォーマットを指定します。このパラメーターには、D3DFORMAT 列挙型の値を使用します。6 番目のパラメーターでは、作成されたリソースを配置するメモリー クラスを示す D3DPOOL 列挙型のメンバーを指定します。動的テクスチャーを使用している場合を除き、D3DPOOL_MANAGED を指定してください。最後のパラメーターでは、IDirect3DTexture9 インターフェイスへのポインターのアドレスを指定します。

    ミップマップ チェーンの各サーフェスのサイズは、チェーン内の直前のサーフェスの半分です。最上位のミップマップのサイズが 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 を呼び出して、ミップマップ内のレベルの数を取得することができます。