円筒にテクスチャを貼り付けて描画する

VertexBuffer は描画処理のためにビデオボード上などに確保される高速のメモリ領域です。
DirectX の CreateVertexBuffer で領域を確保して、生成した円筒にテクスチャを貼り付けて回転しながら描画します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

Main Program

  1. VertexBuffer に割り当てる頂点データの形式です。
    D3DXVECTOR3 は、三次元空間ベクトルで float x,y,z; の要素を持っています。
    D3DCOLOR は、一次反射色(光源によって影響される色)の設定です。
    tu,tv でポリゴンに貼り付けるテクスチャ座標を指定します。
        #define D3DFVF_VERTEXTXT (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
        struct VERTEXTXT
        {
            D3DXVECTOR3 position; // The position
            D3DCOLOR    color;    // The color
            FLOAT       tu, tv;   // The texture coordinates
        };
        
  2. KAKU は多角形の設定で (KAKU-1) 角形の筒を生成します。
    *myd3d は MyD3D Object Class の定義です。
    g_pVB には割り当てた VertexBuffer のポインタを格納します。
    g_pTexture にはテクスチャに使用する画像を格納します。
        #define   KAKU      20
        // Global variables
        MyD3D                   *myd3d      = NULL;     // MyD3D Object Class
        LPDIRECT3DDEVICE9       g_pDEV      = NULL;     // Our rendering device
        LPDIRECT3DVERTEXBUFFER9 g_pVB       = NULL;     // Buffer to hold vertices
        LPDIRECT3DTEXTURE9      g_pTexture  = NULL;     // Our texture
        
  3. MyD3D Object をインスタンス化して、インターフェースを取得します。
    InitGeometry() で Vertex Buffer に多角形の筒を生成します。
        HRESULT InitDevices(HWND hWnd)
        {
            myd3d= new MyD3D(hWnd);
            myd3d->InitD3D(&g_pDEV);
            if (FAILED(InitGeometry()))     return FALSE;
            myd3d->SetMaterial();
            myd3d->SetLight();
            g_pDEV->SetRenderState(D3DRS_AMBIENT,0x00808080);
            g_pDEV->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
            return S_OK;
        }
        
  4. InitGeometry() 関数です。
    D3DXCreateTextureFromFile() でテクスチャを入力します。
    画像ファイル("ayu.jpg")は適当なものを調達してきて下さい。
    CreateVertexBuffer() で VertexBuffer を作成します。
    Lock() で領域をロックして VertexBuffer へのポインタを取得します。
    VertexBuffer に TRIANGLESTRIP(一辺を共有する連続三角形)の形式に合わせて、多角形の筒の座標を登録します。
    tu, tv にテクスチャ座標を設定します。
    Unlock() で VertexBuffer のロックを解除します。
        HRESULT InitGeometry()
        {   VERTEXTXT* pVertices;
    
            if (FAILED(D3DXCreateTextureFromFile(g_pDEV,"ayu.jpg",&g_pTexture)))   return E_FAIL;
            if (FAILED(g_pDEV->CreateVertexBuffer(KAKU*2*sizeof(VERTEXTXT),0,D3DFVF_VERTEXTXT,
                       D3DPOOL_DEFAULT,&g_pVB,NULL)))           return E_FAIL;
            if (FAILED(g_pVB->Lock(0,0,(void**)&pVertices,0)))  return E_FAIL;
            for(DWORD i=0; i<KAKU; i++)
            {   FLOAT theta = (2*D3DX_PI*i)/(KAKU-1);
                pVertices[2*i+0].position = D3DXVECTOR3( sinf(theta),-1.0f, cosf(theta) );
                pVertices[2*i+0].color    = 0xffffffff;
                pVertices[2*i+0].tu       = ((FLOAT)i)/(KAKU-1);
                pVertices[2*i+0].tv       = 1.0f;
                pVertices[2*i+1].position = D3DXVECTOR3( sinf(theta), 1.0f, cosf(theta) );
                pVertices[2*i+1].color    = 0xff808080;
                pVertices[2*i+1].tu       = ((FLOAT)i)/(KAKU-1);
                pVertices[2*i+1].tv       = 0.0f;
            }
            g_pVB->Unlock();
            return S_OK;
        }
        
  5. 多角形の筒を描画します。
    SetupMatrices() でマテリアルを設定します。
    SetTexture() でテクスチャを設定します。
    SetStreamSource() でレンダリングソースとして VertexBuffer を設定します。
    DrawPrimitive() でレンダリングします。
        VOID Render()
        {
            g_pDEV->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0,255),1.0f,0);
            g_pDEV->BeginScene();
            SetupMatrices();
            g_pDEV->SetTexture(0, g_pTexture);
            g_pDEV->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_MODULATE);
            g_pDEV->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
            g_pDEV->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
            g_pDEV->SetTextureStageState(0, D3DTSS_ALPHAOP,   D3DTOP_DISABLE);
            g_pDEV->SetStreamSource(0,g_pVB,0,sizeof(VERTEXTXT));
            g_pDEV->SetFVF(D3DFVF_VERTEXTXT);
            g_pDEV->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2*KAKU-2);
            g_pDEV->EndScene();
            g_pDEV->Present(NULL,NULL,NULL,NULL);
        }
        
  6. マテリアルの設定です。
    X軸とY軸の周期をずらせて回転し、多角形を様々な角度から描画しています。
        VOID SetupMatrices()
        {   D3DXMATRIX matWorld,matw;
            D3DXMATRIX matView;
            D3DXMATRIX matProj;
    
            D3DXMatrixScaling(&matWorld,1.0f,1.0f,1.0f);
            D3DXMatrixRotationX(&matw, timeGetTime()/1000.0f);
            D3DXMatrixMultiply(&matWorld, &matWorld, &matw);
            D3DXMatrixRotationY(&matw, timeGetTime()/700.0f);
            D3DXMatrixMultiply(&matWorld, &matWorld, &matw);
            g_pDEV->SetTransform(D3DTS_WORLD, &matWorld);
    
            D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0.0f,3.0f,-5.0f),
                               &D3DXVECTOR3(0.0f,0.0f,0.0f), &D3DXVECTOR3(0.0f,1.0f,0.0f));
            g_pDEV->SetTransform(D3DTS_VIEW, &matView);
            D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f);
            g_pDEV->SetTransform(D3DTS_PROJECTION, &matProj);
        }
        

【課題】

円筒を利用して360度見渡せる背景を描画してみましょう。
テクスチャを貼り付けた円筒の中にカメラを置いて回転しながら描画します。
背景に使用する画像は、右端から左端につながるような360度見渡せる画像を用意して下さい。

超初心者の方のために全ソースコードを掲載します。 (^_^;)
全ソースコード

前田稔(Maeda Minoru)の超初心者のプログラム入門

超初心者のプログラム入門(DirectX9 game program)

超初心者のプログラム入門(DirectX10 game program)