立方環境マップ サーフェスの作成 (Direct3D 9)
CreateCubeTexture メソッドを呼び出して、3 次環境マップ テクスチャを作成します。 立方環境マップ テクスチャは、2 の累乗を持つ正方形である必要があります。
次のコード例は、C++ アプリケーションで単純な立方環境マップを作成する方法を示しています。
// Init m_d3dDevice to point to an IDirect3DDevice9 interface
LPDIRECT3DCUBETEXTURE9 m_pCubeMap;
m_d3dDevice->CreateCubeTexture(256, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R8G8B8,
D3DPOOL_DEFAULT, &m_pCubeMap);
立方環境マップの顔へのアクセス
GetCubeMapSurface メソッドを使用して、立方環境マップの顔間を移動できます。
次のコード例では 、GetCubeMapSurface を使用して、正の y 面 (顔 2) に使用されるキューブ マップ サーフェスを取得します。
// Init m_pCubeMap to point to an IDirect3DCubeTexture9 interface
LPDIRECT3DSURFACE9 pFace2;
m_pCubeMap->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_Y, 0, &pFace2);
GetCubeMapSurface が受け入れる最初のパラメーターは、メソッドが取得する必要がある添付サーフェスを記述するD3DCUBEMAP_FACES列挙値です。 2 番目のパラメーターは、mipmapped キューブ テクスチャのどのレベルを取得するかを Direct3D に指示します。 受け入れられる 3 番目のパラメーターは、返されたキューブ テクスチャ サーフェスを表す IDirect3DSurface9 インターフェイスのアドレスです。 このキューブ マップは mipmapped ではないので、ここでは 0 が使用されます。
Note
このメソッドを呼び出すと、 IDirect3DSurface9 インターフェイスの内部参照カウントが増加します。 このサーフェスの使用が完了したら、必ずこの IDirect3DSurface9 インターフェイスで IUnknown メソッドを呼び出すか、メモリ リークが発生します。
立方環境マップへのレンダリング
他のテクスチャやサーフェス オブジェクトと同様に、キューブ マップの個々の面に画像をコピーできます。 顔にレンダリングする前に行う最も重要なことは、カメラが正しく配置され、その顔の正しい方向 (前方 (+z)、後方 (-z)、左 (-x)、右 (+x)、上 (+y)、または下 (-y) を指すように変換行列を設定することです。
次の C++ コード例では、レンダリングされる顔に従ってビュー マトリックスを準備および設定します。
// Init pCubeMap to point to an IDirect3DCubeTexture9 interface
// Init d3dDevice to point to an IDirect3DDevice9 interface
void RenderFaces()
{
// Save transformation matrices of the device
D3DXMATRIX matProjSave, matViewSave;
d3dDevice->GetTransform(D3DTS_VIEW, &matViewSave ;
d3dDevice->GetTransform(D3DTS_PROJECTION, &matProjSave);
// Store the current back buffer and z-buffer
LPDIRECT3DSURFACE9 pBackBuffer, pZBuffer;
d3dDevice->GetRenderTarget(&pBackBuffer);
d3dDevice->GetDepthStencilSurface(&pZBuffer);
立方環境マップの各面は、90 度の視野を表します。 アプリケーションで異なる視野 (特殊効果など) が必要な場合を除き、それに応じて投影行列を設定するように注意してください。
このコード例では、最も一般的なケースのプロジェクション マトリックスを作成して設定します。
// Use 90-degree field of view in the projection
D3DMATRIX matProj;
D3DXMatrixPerspectiveFovLH(matProj, D3DX_PI/2, 1.0f, 0.5f, 1000.0f);
d3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);
// Loop through the six faces of the cube map
for(DWORD i=0; i<6; i++)
{
// Standard view that will be overridden below
D3DVECTOR vEnvEyePt = D3DVECTOR(0.0f, 0.0f, 0.0f);
D3DVECTOR vLookatPt, vUpVec;
switch(i)
{
case D3DCUBEMAP_FACE_POSITIVE_X:
vLookatPt = D3DVECTOR(1.0f, 0.0f, 0.0f);
vUpVec = D3DVECTOR(0.0f, 1.0f, 0.0f);
break;
case D3DCUBEMAP_FACE_NEGATIVE_X:
vLookatPt = D3DVECTOR(-1.0f, 0.0f, 0.0f);
vUpVec = D3DVECTOR( 0.0f, 1.0f, 0.0f);
break;
case D3DCUBEMAP_FACE_POSITIVE_Y:
vLookatPt = D3DVECTOR(0.0f, 1.0f, 0.0f);
vUpVec = D3DVECTOR(0.0f, 0.0f,-1.0f);
break;
case D3DCUBEMAP_FACE_NEGATIVE_Y:
vLookatPt = D3DVECTOR(0.0f,-1.0f, 0.0f);
vUpVec = D3DVECTOR(0.0f, 0.0f, 1.0f);
break;
case D3DCUBEMAP_FACE_POSITIVE_Z:
vLookatPt = D3DVECTOR( 0.0f, 0.0f, 1.0f);
vUpVec = D3DVECTOR( 0.0f, 1.0f, 0.0f);
break;
case D3DCUBEMAP_FACE_NEGATIVE_Z:
vLookatPt = D3DVECTOR(0.0f, 0.0f,-1.0f);
vUpVec = D3DVECTOR(0.0f, 1.0f, 0.0f);
break;
}
D3DMATRIX matView;
D3DXMatrixLookAtLH(matView, vEnvEyePt, vLookatPt, vUpVec);
d3dDevice->SetTransform(D3DTS_VIEW, &matView);
カメラが位置にあり、プロジェクション マトリックス セットが設定されている場合は、シーンをレンダリングできます。 シーン内の各オブジェクトは、通常と同じように配置する必要があります。 完全のために提供される次のコード例では、このタスクの概要を示します。
// Get pointer to surface in order to render to it
LPDIRECT3DSURFACE9 pFace;
pCubeMap->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0, &pFace);
d3dDevice->SetRenderTarget (pFace , pZBuffer);
SAFE_RELEASE(pFace);
d3dDevice->BeginScene();
// Render scene here
...
d3dDevice->EndScene();
}
// Change the render target back to the main back buffer.
d3dDevice->SetRenderTarget(pBackBuffer, pZBuffer);
SAFE_RELEASE(pBackBuffer);
SAFE_RELEASE(pZBuffer);
// Restore the original transformation matrices
d3dDevice->SetTransform(D3DTS_VIEW, &matViewSave);
d3dDevice->SetTransform(D3DTS_PROJECTION, &matProjSave);
}
SetRenderTarget メソッドの呼び出しに注意してください。 キューブ マップの面にレンダリングする場合は、その面を現在のレンダー ターゲット サーフェスとして割り当てる必要があります。 深度バッファーを使用するアプリケーションでは、レンダー ターゲットの深度バッファーを明示的に作成するか、既存の深度バッファーをレンダー ターゲット サーフェスに再割り当てできます。 上記のコード サンプルでは、後者のアプローチを使用しています。
関連トピック