Partilhar via


Criando superfícies de mapa de ambiente cúbico (Direct3D 9)

Você cria uma textura de mapa de ambiente cúbico chamando o CreateCubeTexture método. As texturas do mapa de 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 faces do mapa do ambiente cúbico

Você pode navegar entre faces de um mapa de ambiente cúbico usando o métodoGetCubeMapSurface.

O exemplo de código a seguir utiliza GetCubeMapSurface para recuperar a superfície do mapa cúbico utilizada 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 D3DCUBEMAP_FACES valor enumerado 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 deve ser recuperado. O terceiro parâmetro aceito é o endereço da interfaceIDirect3DSurface9, representando a superfície de textura do cubo retornada. Como este mapa cúbico não é mipmapped, 0 é usado aqui.

Observação

Depois de chamar esse método, a contagem de referência interna na interfaceIDirect3DSurface9 doé aumentada. Quando terminar de utilizar esta superfície, certifique-se de chamar o método IUnknown nesta interface IDirect3DSurface9, ou terá um vazamento de memória.

 

Renderização em mapas de ambiente cúbico

Você pode copiar imagens para as faces individuais do mapa do cubo 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 a face que está sendo renderizada.

// 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, cada face de um mapa de ambiente cúbico representa um campo de visão de 90 graus. A menos que sua aplicação exija um ângulo de campo de visão diferente - para efeitos especiais, por exemplo - tenha o cuidado de definir a matriz de projeção de acordo.

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 está na posição e a matriz de projeção definida, você pode renderizar a cena. Cada objeto na cena deve ser posicionado como você normalmente os posicionaria. O exemplo de código a seguir, fornecido para completude, 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);
}

Note a chamada para o método SetRenderTarget. Ao renderizar para as faces do mapa do cubo, você deve atribuir a face 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.

Mapeamento de Ambiente Cúbico