Leggere in inglese

Condividi tramite


Creazione di superfici di mappe di ambiente cubiche (Direct3D 9)

Si crea una trama della mappa dell'ambiente cubico chiamando il metodo CreateCubeTexture. Le texture della mappa ambientale cubica devono essere quadrate, con dimensioni che sono una potenza di due.

L'esempio di codice seguente illustra come l'applicazione C++ potrebbe creare una semplice mappa di ambiente cubica.

// 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);

Accesso alle facce della mappa ambientale cubica

È possibile spostarsi tra i visi di una mappa di ambiente cubica usando il metodoGetCubeMapSurface.

L'esempio di codice seguente usa getCubeMapSurface per recuperare la superficie della mappa del cubo usata per il viso y positivo (viso 2).

// Init m_pCubeMap to point to an IDirect3DCubeTexture9 interface

LPDIRECT3DSURFACE9 pFace2;
m_pCubeMap->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_Y, 0, &pFace2);

Il primo parametro che GetCubeMapSurface accetta è un valore enumerato D3DCUBEMAP_FACES che descrive la superficie associata che deve essere recuperata dal metodo. Il secondo parametro indica a Direct3D quale livello di una texture del cubo mipmapped ottenere. Il terzo parametro accettato è l'indirizzo dell'interfaccia IDirect3DSurface9, che rappresenta la superficie di trama del cubo restituita. Poiché questa mappa del cubo non è mipmapped, qui viene usato 0.

Nota

Dopo aver chiamato questo metodo, viene aumentato il conteggio dei riferimenti interni nell'interfacciaIDirect3DSurface9. Una volta terminato l'uso di questa superficie, assicurarsi di chiamare il metodoIUnknownsu questa interfaccia IDirect3DSurface9 o potrebbe verificarsi una perdita di memoria.

 

Rendering in mappe dell'ambiente cubico

È possibile copiare immagini nelle singole facce della cubo mappa esattamente come qualsiasi altra texture o oggetto di superficie. La cosa più importante da eseguire prima del rendering in un viso è impostare le matrici di trasformazione in modo che la fotocamera sia posizionata correttamente e punti nella direzione corretta per il viso: avanti (+z), indietro (-z), sinistra (-x), destra (+x), su (+y) o giù (-y).

Nell'esempio di codice C++ seguente viene preparata e impostata una matrice di visualizzazione in base al rendering del viso.

// 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);

Tenere presente che ogni faccia di una mappa di ambiente cubica rappresenta un campo di visualizzazione a 90 gradi. A meno che l'applicazione non richieda un diverso campo di angolo di visualizzazione, ad esempio per effetti speciali, prestare attenzione a impostare la matrice di proiezione di conseguenza.

Questo esempio di codice crea e imposta una matrice di proiezione per il caso più comune.

    // 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 la fotocamera è in posizione e la matrice di proiezione impostata, è possibile eseguire il rendering della scena. Ogni oggetto nella scena deve essere posizionato come si posiziona normalmente. L'esempio di codice seguente, fornito per completezza, descrive questa attività.

        // 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);
}

Si noti la chiamata al metodo SetRenderTarget. Quando si esegue il rendering sulle facce della mappa del cubo, è necessario assegnare la faccia come superficie di rendering corrente di destinazione. Le applicazioni che usano buffer di profondità possono creare in modo esplicito un buffer di profondità per la destinazione di rendering o riassegnare un buffer di profondità esistente alla superficie di destinazione di rendering. L'esempio di codice precedente usa quest'ultimo approccio.

Mapping dell'ambiente cubico