Freigeben über


Erstellen kubischer Umgebungskartenoberflächen (Direct3D 9)

Sie erstellen eine kubische Umgebungszuordnungstextur, indem Sie die CreateCubeTexture-Methode aufrufen. Kubische Umgebungszuordnungstexturen müssen quadratisch sein, wobei die Abmessungen eine Stärke von zwei haben.

Das folgende Codebeispiel zeigt, wie Ihre C++-Anwendung eine einfache kubische Umgebungszuordnung erstellen kann.

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

Zugreifen auf kubische Umgebungskartenflächen

Sie können mit der GetCubeMapSurface-Methode zwischen den Gesichtern einer kubischen Umgebungskarte navigieren.

Im folgenden Codebeispiel wird GetCubeMapSurface verwendet, um die Cube-Map-Oberfläche abzurufen, die für die positive y-Face (Face 2) verwendet wird.

// Init m_pCubeMap to point to an IDirect3DCubeTexture9 interface

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

Der erste Parameter, den GetCubeMapSurface akzeptiert, ist ein D3DCUBEMAP_FACES aufgezählter Wert, der die angefügte Oberfläche beschreibt, die die Methode abrufen soll. Der zweite Parameter teilt Direct3D mit, welche Ebene einer mipmapped-Würfeltextur abgerufen werden soll. Der dritte akzeptierte Parameter ist die Adresse der IDirect3DSurface9-Schnittstelle , die die zurückgegebene Cubetexturoberfläche darstellt. Da diese Cubezuordnung nicht mipmapped ist, wird hier 0 verwendet.

Hinweis

Nach dem Aufrufen dieser Methode wird die interne Verweisanzahl auf der IDirect3DSurface9-Schnittstelle erhöht. Wenn Sie mit der Verwendung dieser Oberfläche fertig sind, rufen Sie die IUnknown-Methode auf dieser IDirect3DSurface9-Schnittstelle auf. Andernfalls tritt ein Speicherverlust auf.

 

Rendering in kubischen Umgebungskarten

Sie können Bilder wie jedes andere Textur- oder Oberflächenobjekt in die einzelnen Gesichter der Würfelzuordnung kopieren. Das Wichtigste vor dem Rendern in einem Gesicht ist, die Transformationsmatrizen so festzulegen, dass die Kamera ordnungsgemäß positioniert ist und in die richtige Richtung für dieses Gesicht zeigt: vorwärts (+z), rückwärts (-z), links (-x), rechts (+x), oben (+y) oder nach unten (-y).

Im folgenden C++-Codebeispiel wird eine Ansichtsmatrix entsprechend dem gerenderten Gesicht vorbereitet und festgelegt.

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

Denken Sie daran, dass jedes Gesicht einer kubischen Umgebungskarte ein Sichtfeld von 90 Grad darstellt. Es sei denn, Ihre Anwendung erfordert einen anderen Sichtwinkel – z. B. für Spezialeffekte – legen Sie die Projektionsmatrix entsprechend fest.

In diesem Codebeispiel wird eine Projektionsmatrix für den häufigsten Fall erstellt und festgelegt.

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

Wenn sich die Kamera befindet und die Projektionsmatrix festgelegt ist, können Sie die Szene rendern. Jedes Objekt in der Szene sollte so positioniert werden, wie Sie es normalerweise positionieren würden. Im folgenden Codebeispiel, das aus Gründen der Vollständigkeit bereitgestellt wird, wird diese Aufgabe beschrieben.

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

Beachten Sie den Aufruf der SetRenderTarget-Methode . Beim Rendern in den Würfelzuordnungsflächen müssen Sie das Gesicht als aktuelle Renderzieloberfläche zuweisen. Anwendungen, die Tiefenpuffer verwenden, können explizit einen Tiefenpuffer für das Renderziel erstellen oder der Renderzieloberfläche einen vorhandenen Tiefenpuffer neu zuweisen. Im obigen Codebeispiel wird der letztere Ansatz verwendet.

Kubische Umgebungszuordnung