Microsoft DirectX 8.0 (C++)

キューブ環境マップへのレンダリング

キューブ マップの個々のサーフェスへは、その他のテクスチャやサーフェス オブジェクトと同じように画像をコピーすることができる。このレンダリングを行う前に実行する最も大切なことは、カメラを正しく配置し、そのサーフェスに対して正しい方向を向くようにトランスフォーム行列を設定することである。正しい方向とは、前方 (+z)、後方 (-z)、左 (-x)、右 (+x)、上方 (+y)、または下方 (-y) である。

次の C++ コードは、レンダリングするサーフェスに応じてビュー行列を用意して設定する。

/*
* この例では、pCubeMap は IDirect3DCubeTexture8 インターフェイスへの有効なポインタであり、
* d3dDevice は IDirect3DDevice8 インターフェイスへの
* 有効なポインタである。
 */
void RenderFaces()
{
    // デバイスのトランスフォーム行列を保存する。
    D3DXMATRIX matProjSave, matViewSave;
    d3dDevice->GetTransform( D3DTS_VIEW,       &matViewSave );
    d3dDevice->GetTransform( D3DTS_PROJECTION, &matProjSave );

    // 現在のバック バッファと z バッファを格納する。
    LPDIRECT3DSURFACE8 pBackBuffer, pZBuffer;
    d3dDevice->GetRenderTarget( &pBackBuffer );
    d3dDevice->GetDepthStencilSurface( &pZBuffer );

キューブ環境マップの各サーフェスには 90°の視野が含まれることを思い出すこと。アプリケーションで特殊効果などのために視野の角度を変更しない限り、この角度に応じて射影行列を設定するよう注意が必要である。

次のコードは、最も一般的に使用する射影行列を作成および設定する。

    // 90°の視野を射影に使用する。
    D3DMATRIX matProj;
    D3DXMatrixPerspectiveFovLH( matProj, D3DX_PI/2, 1.0f, 0.5f, 1000.0f );
    d3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );

    // キューブ マップの 6 つのサーフェスに対してループ処理を実行する。
    for( DWORD i=0; i<6; i++ )
    {
        // 以下のように、標準ビューをオーバーライドする。
        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 );

カメラを正しく配置し、射影行列を設定すると、シーンをレンダリングできる。シーンの各オブジェクトは、通常配置するとおりに配置する。次のコードでは、処理全体がわかるように、このタスクの概略を示す。

        //レンダリングするサーフェスへのポインタを取得する。
        LPDIRECT3DSURFACE8 pFace;
        pCubeMap->GetCubeMapSurface( (D3DCUBEMAP_FACES)i, 0, &pFace );
        d3dDevice->SetRenderTarget ( pFace , pZBuffer );
        pFace->Release();

        d3dDevice->BeginScene();
        // ここで、シーンをレンダリングする。
        d3dDevice->EndScene();
    }

    // レンダリング ターゲットをメイン バック バッファに戻す。
    d3dDevice->SetRenderTarget( pBackBuffer, pZBuffer );
    pBackBuffer->Release();
    pZBuffer->Release();

    // 元のトランスフォーム行列をリストアする。
    d3dDevice->SetTransform( D3DTS_VIEW,       &matViewSave );
    d3dDevice->SetTransform( D3DTS_PROJECTION, &matProjSave );
}

IDirect3DDevice8::SetRenderTarget メソッドの呼び出しには注意すること。キューブ マップ サーフェスにレンダリングするときは、そのサーフェスをカレント レンダリング ターゲット サーフェスとして割り当てる必要がある。深度バッファを使用するアプリケーションでは、そのレンダリング ターゲットに明示的に深度バッファを作成したり、既存の深度バッファをレンダリング ターゲット サーフェスに再割り当てすることができる。上のコードでは、後者の方法を使用している。