创建立方环境地图图面 (Direct3D 9)
通过调用 CreateCubeTexture 方法创建立方环境贴图纹理。 立方体环境贴图纹理必须是正方形的,其维度的幂为 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枚举值,该值描述方法应检索的附加图面。 第二个参数告知 Direct3D 要检索的经过错误应用的多维数据集纹理的哪个级别。 接受的第三个参数是 IDirect3DSurface9 接口的地址,表示返回的多维数据集纹理图面。 由于未应用此多维数据集映射,因此此处使用 0。
注意
调用此方法后, 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 方法的调用。 呈现到多维数据集地图人脸时,必须将人脸指定为当前呈现目标图面。 使用深度缓冲区的应用程序可以为呈现目标显式创建深度缓冲区,或将现有的深度缓冲区重新分配给呈现目标图面。 上面的代码示例使用后一种方法。
相关主题