Criando superfícies de mapa de ambiente cúbico (Direct3D 9)
Você cria uma textura de mapa de ambiente cúbico chamando o método CreateCubeTexture . As texturas do mapa do ambiente cúbico devem ser quadradas, com dimensões que são uma potência de dois.
O exemplo de código a seguir mostra como seu aplicativo C++ pode criar um mapa de ambiente cúbico simples.
// 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);
Acessando rostos do mapa do ambiente cúbico
Você pode navegar entre rostos de um mapa de ambiente cúbico usando o método GetCubeMapSurface .
O exemplo de código a seguir usa GetCubeMapSurface para recuperar a superfície de mapa de cubo usada para a face y positiva (face 2).
// Init m_pCubeMap to point to an IDirect3DCubeTexture9 interface
LPDIRECT3DSURFACE9 pFace2;
m_pCubeMap->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_Y, 0, &pFace2);
O primeiro parâmetro que GetCubeMapSurface aceita é um valor enumerado D3DCUBEMAP_FACES que descreve a superfície anexada que o método deve recuperar. O segundo parâmetro informa ao Direct3D qual nível de uma textura de cubo mipmapped recuperar. O terceiro parâmetro aceito é o endereço da interface IDirect3DSurface9 , representando a superfície de textura de cubo retornada. Como este mapa de cubo não é mipmapped, 0 é usado aqui.
Observação
Depois de chamar esse método, a contagem de referência interna na interface IDirect3DSurface9 é aumentada. Quando terminar de usar essa superfície, chame o método IUnknown nessa interface IDirect3DSurface9 ou você terá um vazamento de memória.
Renderizando para mapas de ambiente cúbico
Você pode copiar imagens para os rostos individuais do mapa de cubo, assim como faria com qualquer outro objeto de textura ou superfície. A coisa mais importante a fazer antes de renderizar para um rosto é definir as matrizes de transformação para que a câmera seja posicionada corretamente e aponte na direção adequada para esse rosto: para frente (+z), para trás (-z), esquerda (-x), direita (+x), para cima (+y) ou para baixo (-y).
O exemplo de código C++ a seguir prepara e define uma matriz de exibição de acordo com o rosto que está sendo renderizado.
// 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);
Lembre-se de que cada face de um mapa de ambiente cúbico representa um campo de exibição de 90 graus. A menos que seu aplicativo exija um campo diferente de ângulo de exibição – para efeitos especiais, por exemplo – tome cuidado para definir a matriz de projeção adequadamente.
Este exemplo de código cria e define uma matriz de projeção para o caso mais comum.
// 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);
Quando a câmera estiver em posição e o conjunto de matrizes de projeção, você poderá renderizar a cena. Cada objeto na cena deve ser posicionado como você normalmente os posicionaria. O exemplo de código a seguir, fornecido para integridade, descreve essa tarefa.
// 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);
}
Observe a chamada para o método SetRenderTarget . Ao renderizar para as faces do mapa de cubo, você deve atribuir o rosto como a superfície de destino de renderização atual. Os aplicativos que usam buffers de profundidade podem criar explicitamente um buffer de profundidade para o destino de renderização ou reatribuir um buffer de profundidade existente à superfície de destino de renderização. O exemplo de código acima usa a última abordagem.
Tópicos relacionados