テクスチャ リソースの作成 (Direct3D 10)

テクスチャ リソースは、データの構造化されたコレクションです。 通常、カラー値はテクスチャに格納され、入力と出力の両方のさまざまな段階で パイプライン によるレンダリング中にアクセスされます。 テクスチャを作成し、その使用方法を定義することは、Direct3D 10 で興味深い見た目のシーンをレンダリングする上で重要な部分です。

通常、テクスチャには色情報が含まれていますが、異なる DXGI_FORMAT を使用してテクスチャを作成すると、さまざまな種類のデータを格納できます。 このデータは、従来以外の方法で Direct3D 10 パイプラインで利用できます。

すべてのテクスチャには、消費するメモリの量と、そのメモリに含まれるテクセルの数に制限があります。 これらの制限は、 リソース定数によって指定されます。

ファイルからテクスチャを作成する

注意

D3DX ユーティリティ ライブラリは、Windows 8では非推奨であり、Windows ストア アプリではサポートされていません。

 

Direct3D 10 でテクスチャを作成する場合は、 ビューも作成する必要があります。 ビューは、レンダリング中にテクスチャにアクセスする方法をデバイスに指示するオブジェクトです。 テクスチャにアクセスする最も一般的な方法は、シェーダーを使用してテクスチャから読み取 方法です。 シェーダー リソース ビューは、レンダリング中にテクスチャから読み取る方法をシェーダーに指示します。 テクスチャが使用するビューの種類は、作成時に指定する必要があります。

テクスチャの作成と初期データの読み込みは、テクスチャとビューを個別に作成するか、テクスチャとビューの両方を同時に作成するという 2 つの方法で行うことができます。 API には両方の手法が用意されているため、ニーズに適したものを選択できます。

テクスチャとビューを個別に作成する

テクスチャを作成する最も簡単な方法は、イメージ ファイルからテクスチャを読み込む方法です。 テクスチャを作成するには、1 つの構造体を入力し、テクスチャの名前を D3DX10CreateTextureFromFile に指定します。

ID3D10Device *pDevice = NULL;
// Initialize D3D10 device...

D3DX10_IMAGE_LOAD_INFO loadInfo;
ZeroMemory( &loadInfo, sizeof(D3DX10_IMAGE_LOAD_INFO) );
loadInfo.BindFlags = D3D10_BIND_SHADER_RESOURCE;

ID3D10Resource *pTexture = NULL;
D3DX10CreateTextureFromFile( pDevice, L"sample.bmp", &loadInfo, NULL, &pTexture, NULL );

D3DX 関数 D3DX10CreateTextureFromFile は 3 つのことを行います。最初に、Direct3D 10 テクスチャ オブジェクトを作成します。次に、入力画像ファイルを読み取ります。3 つ目は、テクスチャ オブジェクトにイメージ データを格納します。 上記のサンプルでは、BMPファイルが読み込まれますが、関数はさまざまな種類のファイルを読み込むことができます。

バインド フラグは、テクスチャがシェーダー リソースとして作成されることを示します。これにより、レンダリング中にシェーダー ステージがテクスチャから読み取ることができます。

上記の例では、すべての読み込みパラメーターが指定されているわけではありません。 実際には、D3DX が入力イメージに基づいて適切な値を選択できるため、読み込みパラメーターをゼロにするだけで役立つことがよくあります。 入力イメージでテクスチャが作成されるすべてのパラメーターを決定する場合は、次のように loadInfo パラメーターに NULL を指定するだけです。

D3DX10CreateTextureFromFile( pDevice, L"sample.bmp", NULL, NULL, &pTexture, NULL );

読み込み情報に NULL を 指定することは、単純でありながら強力なショートカットです。

テクスチャが作成されたので、テクスチャをシェーダーへの入力としてバインドできるように、シェーダー リソース ビューを作成する必要があります。 D3DX10CreateTextureFromFile は、テクスチャへのポインターではなく、リソースへのポインターを返すので、読み込まれたリソースの正確な種類を決定する必要があります。その後、CreateShaderResourceView を使用してシェーダー リソース ビューを作成できます。

D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc;
D3D10_RESOURCE_DIMENSION type;
pTexture->GetType( &type );
switch( type )
{
    case D3D10_RESOURCE_DIMENSION_BUFFER:
    //...
    break;
    case D3D10_RESOURCE_DIMENSION_TEXTURE1D:
    //...
    break;
    case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
    {
        D3D10_TEXTURE2D_DESC desc;
        ID3D10Texture2D *pTexture2D = (ID3D10Texture2D*)pTexture;
        pTexture2D->GetDesc( &desc );
        
        srvDesc.Format = desc.Format;
        srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
        srvDesc.Texture2D.MipLevels = desc.MipLevels;
        srvDesc.Texture2D.MostDetailedMip = desc.MipLevels -1;

    }
    break;
    case D3D10_RESOURCE_DIMENSION_TEXTURE3D:
    //...
    break;
    default:
    //...
    break;
}

ID3D10ShaderResourceView *pSRView = NULL;
pDevice->CreateShaderResourceView( pTexture, &srvDesc, &pSRView );

上記のサンプルでは 2D シェーダー リソース ビューが作成されますが、他のシェーダー リソース ビューの種類を作成するコードは非常によく似ています。 すべてのシェーダー ステージで、このテクスチャを入力として使用できるようになりました。

D3DX10CreateTextureFromFileCreateShaderResourceView を使用してテクスチャを作成し、関連付けられたビューを使用して、シェーダー ステージにバインドするテクスチャを準備する 1 つの方法です。 これを行うもう 1 つの方法は、テクスチャとそのビューの両方を同時に作成する方法です。これについては、次のセクションで説明します。

テクスチャとビューを同時に作成する

Direct3D 10 では、実行時にテクスチャから読み取るためにテクスチャとシェーダー リソース ビューの両方が必要です。 テクスチャとシェーダー リソース ビューの作成はこのような一般的なタスクであるため、 D3DX は D3DX10CreateShaderResourceViewFromFile を提供します。

D3DX10_IMAGE_LOAD_INFO loadInfo;
ZeroMemory( &loadInfo, sizeof(D3DX10_IMAGE_LOAD_INFO) );
loadInfo.BindFlags = D3D10_BIND_SHADER_RESOURCE;
loadInfo.Format = DXGI_FORMAT_BC1_UNORM;

ID3D10ShaderResourceView *pSRView = NULL;
D3DX10CreateShaderResourceViewFromFile( pDevice, L"sample.bmp", &loadInfo, NULL, &pSRView, NULL );

単一の D3DX 呼び出しでは、テクスチャとシェーダー リソース ビューの両方が作成されます。 loadInfo パラメーターの機能は変更されません。これを使用してテクスチャの作成方法をカスタマイズしたり、loadInfo パラメーターに NULL を指定して入力ファイルから必要なパラメーターを派生させたりすることができます。

D3DX10CreateShaderResourceViewFromFile 関数によって返される ID3D10ShaderResourceView オブジェクトを後で使用して、必要に応じて元の ID3D10Resource インターフェイスを取得できます。 これを行うには、 GetResource メソッドを呼び出します。

D3DX は、テクスチャとシェーダー リソース ビューを対等として作成する 1 つの関数を提供します。テクスチャを作成し、アプリケーションのニーズに最も適したビューを作成する方法を決定するのはあなた次第です。

テクスチャとそのシェーダー リソース ビューを作成する方法がわかったら、次のセクションでは、シェーダーを使用してそのテクスチャからサンプリング (読み取り) する方法を示します。

空のテクスチャの作成

場合によっては、アプリケーションでテクスチャを作成し、テクスチャに格納するデータを計算したり、グラフィックス パイプライン を使用してこのテクスチャにレンダリングしたり、その結果を後で他の処理で使用したりする必要があります。 これらのテクスチャは、作成時にテクスチャに対して指定された 使用法 の種類に応じて、グラフィックス パイプラインまたはアプリケーション自体によって更新できます。

テクスチャへのレンダリング

実行時にデータを格納する空のテクスチャを作成する最も一般的なケースは、アプリケーションがテクスチャにレンダリングし、その後のパスでレンダリング操作の結果を使用する場合です。 この目的で作成されたテクスチャでは、既定の 使用法を指定する必要があります。

次のコード サンプルでは、パイプラインがレンダリングし、その後シェーダーへの入力として使用できる空のテクスチャを作成 します

// Create the render target texture
D3D10_TEXTURE2D_DESC desc;
ZeroMemory( &desc, sizeof(desc) );
desc.Width = 256;
desc.Height = 256;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
desc.SampleDesc.Count = 1;
desc.Usage = D3D10_USAGE_DEFAULT;
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;

ID3D10Texture2D *pRenderTarget = NULL;
pDevice->CreateTexture2D( &desc, NULL, &pRenderTarget );

テクスチャを作成するには、テクスチャに含まれるプロパティに関する情報をアプリケーションで指定する必要があります。 テクセル内のテクスチャの幅と高さは 256 に設定されます。 このレンダー ターゲットでは、必要なミップマップ レベルが 1 つだけです。 配列サイズが 1 に設定されるように、1 つのレンダー ターゲットのみが必要です。 各テクセルには、非常に正確な情報を格納するために使用できる 4 つの 32 ビット浮動小数点値が含まれています ( DXGI_FORMATを参照)。 ピクセルごとに 1 つのサンプルが必要なすべてです。 これにより、メモリ内でのレンダー ターゲットの配置が最も効率的になるため、使用量は既定値に設定されます。 最後に、テクスチャがレンダー ターゲットとしてバインドされ、シェーダー リソースが異なる時点でバインドされるという事実が指定されます。

テクスチャをパイプラインに直接レンダリングするためにバインドすることはできません。次のコード サンプルに示すように、レンダー ターゲット ビューを使用します。

D3D10_RENDER_TARGET_VIEW_DESC rtDesc;
rtDesc.Format = desc.Format;
rtDesc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D;
rtDesc.Texture2D.MipSlice = 0;

ID3D10RenderTargetView *pRenderTargetView = NULL;
pDevice->CreateRenderTargetView( pRenderTarget, &rtDesc, &pRenderTargetView );

レンダー ターゲット ビューの形式は、単に元のテクスチャの形式に設定されます。 リソース内の情報は 2D テクスチャとして解釈する必要があり、レンダー ターゲットの最初のミップマップ レベルのみを使用する必要があります。

レンダー ターゲットをパイプラインへの出力にバインドできるようにレンダー ターゲット ビューを作成する方法と同様に、レンダー ターゲットを入力としてパイプラインにバインドできるようにシェーダー リソース ビューを作成する必要があります。 次のコード サンプルは、これを示しています。

// Create the shader-resource view
D3D10_SHADER_RESOURCE_VIEW_DESC srDesc;
srDesc.Format = desc.Format;
srDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
srDesc.Texture2D.MostDetailedMip = 0;
srDesc.Texture2D.MipLevels = 1;

ID3D10ShaderResourceView *pShaderResView = NULL;
pDevice->CreateShaderResourceView( pRenderTarget, &srDesc, &pShaderResView );

シェーダー リソース ビューの説明のパラメーターは、レンダー ターゲット ビューの説明と非常によく似ていますが、同じ理由で選択されました。

テクスチャを手動で塗りつぶす

アプリケーションでは、実行時に値を計算し、手動でテクスチャに入れてから、後のレンダリング操作でグラフィックス パイプライン でこのテクスチャを使用するようにしたい場合があります。 これを行うには、CPU が基になるメモリにアクセスできるように、アプリケーションで空のテクスチャを作成する必要があります。 これを行うには、動的テクスチャを作成し、特定のメソッドを呼び出して基になるメモリにアクセスします。 これを実行する方法を次のコード例に示します。

D3D10_TEXTURE2D_DESC desc;
desc.Width = 256;
desc.Height = 256;
desc.MipLevels = desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D10_USAGE_DYNAMIC;
desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
ID3D10Texture2D *pTexture = NULL;
pd3dDevice->CreateTexture2D( &desc, NULL, &pTexture );

この形式はピクセルあたり 32 ビットに設定され、各コンポーネントは 8 ビットで定義されます。 使用法パラメーターは dynamic に設定され、バインド フラグはシェーダーによってアクセスされるテクスチャを指定するように設定されます。 テクスチャの説明の残りの部分は、レンダー ターゲットの作成と似ています。

Map を呼び出すと、アプリケーションはテクスチャの基になるメモリにアクセスできます。 取得されたポインターは、テクスチャにデータを塗りつぶすために使用されます。 これは、次のコード サンプルで確認できます。

D3D10_MAPPED_TEXTURE2D mappedTex;
pTexture->Map( D3D10CalcSubresource(0, 0, 1), D3D10_MAP_WRITE_DISCARD, 0, &mappedTex );

UCHAR* pTexels = (UCHAR*)mappedTex.pData;
for( UINT row = 0; row < desc.Height; row++ )
{
    UINT rowStart = row * mappedTex.RowPitch;
    for( UINT col = 0; col < desc.Width; col++ )
    {
        UINT colStart = col * 4;
        pTexels[rowStart + colStart + 0] = 255; // Red
        pTexels[rowStart + colStart + 1] = 128; // Green
        pTexels[rowStart + colStart + 2] = 64;  // Blue
        pTexels[rowStart + colStart + 3] = 32;  // Alpha
    }
}

pTexture->Unmap( D3D10CalcSubresource(0, 0, 1) );

複数のレンダーターゲット

一度に最大 8 つのレンダー ターゲット ビューをパイプラインにバインドできます ( OMSetRenderTargets を使用)。 各ピクセル (またはマルチサンプリングが有効な場合は各サンプル) について、ブレンドはレンダー ターゲット ビューごとに個別に行われます。 BlendEnable と RenderTargetWriteMask の 2 つのブレンド状態変数は 8 の配列であり、各配列メンバーはレンダー ターゲット ビューに対応します。 複数のレンダー ターゲットを使用する場合、各レンダー ターゲットは同じ リソースの種類 (バッファー、1D テクスチャ、2D テクスチャ配列など) であり、同じディメンション (幅、高さ、3D テクスチャの深さ、テクスチャ配列の配列サイズ) を持つ必要があります。 レンダー ターゲットがマルチサンプリングされている場合は、ピクセルあたりのサンプル数がすべて同じである必要があります。

アクティブなレンダー ターゲットの数に関係なく、アクティブな深度ステンシル バッファーは 1 つだけです。 レンダー ターゲットとしてテクスチャ配列を使用する場合、すべてのビュー ディメンションが一致する必要があります。 レンダー ターゲットは、同じテクスチャ形式である必要はありません。

リソース (Direct3D 10)