Создание поверхностей карты кубической среды (Direct3D 9)

Текстура карты кубической среды создается путем вызова метода CreateCubeTexture. Текстуры карты кубической среды должны быть квадратными, размеры которых являются степенью двойки.

В следующем примере кода показано, как приложение 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, какой уровень текстуры кубов mipmapped требуется извлечь. Третий параметр принимает адрес интерфейса IDirect3DSurface9, который представляет собой возвращаемую поверхность кубической текстуры. Поскольку эта карта куба не использует технологию мипмаппинга, здесь используется значение 0.

Заметка

После вызова этого метода увеличивается количество внутренних ссылок на интерфейс IDirect3DSurface9. Когда вы закончите использовать эту поверхность, обязательно вызовите метод IUnknown на этом интерфейсе IDirect3DSurface9 или у вас будет утечка памяти.

 

Отрисовка на кубические карты окружения

Изображения можно скопировать на отдельные лица карты куба так же, как и любой другой объект текстуры или поверхности. Самое важное, что нужно сделать перед отрисовкой на лицевую поверхность, это задать матрицы преобразования, чтобы камера была правильно размещена и направлена в нужную сторону для этой поверхности: вперед (+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. При отрисовке лиц на карте куба необходимо назначить лицо в качестве текущей целевой поверхности отрисовки. Приложения, использующие буфер глубины, могут явно создать буфер глубины для целевого объекта отрисовки или переназначить существующий буфер глубины на поверхность целевого объекта отрисовки. Приведенный выше пример кода использует последний подход.

кубическое отображение среды