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

六角形の筒にバナナの皮のテクスチャを貼り付けて専用の Shader で描画します。

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

プログラムの概要

  1. テクスチャを貼り付けるシェーダを用意します。
  2. 頂点シェーダのソースコード(texture.vsh)を入力してシェーダを作成します。
  3. Vertex Buffer を割り当てて、テクスチャを貼り付けた六角形の筒を生成します。
  4. 頂点シェーダを使って六角形の筒を描画します。
  5. このプログラムは、ハードウエアがシェーダの機能をサポートしていなければ動きません。
    またシェーダ機能をサポートしているデバイスを選択することも重要です。
  6. プログラムの作成手順としては、汎用のシェーダで動くことを確認してから専用のシェーダを使って下さい。

プログラムの説明

  1. #include と #define と DirectX オブジェクトの定義です。
    g_pTex はバナナの皮の Texture Object です。
    g_Shader が Vertex Shader です。
    VERTEXTXT の tu,tv がテクスチャ座標です。
        /************************************************/
        /*  多角形の筒にテクスチャを貼り付る   前田 稔  */
        /************************************************/
        #define     NAME      "Shader Texture"
        #include    "MyD3D.h"
    
        // Global variables
        MyD3D                   *myd3d   = NULL;        // MyD3D Object Class
        LPDIRECT3DDEVICE9       g_pDEV   = NULL;
        LPDIRECT3DVERTEXSHADER9 g_Shader = NULL;
        LPDIRECT3DVERTEXBUFFER9 g_pVB    = NULL;
        LPDIRECT3DTEXTURE9      g_pTex   = NULL;
        D3DXMATRIX              g_View;
        D3DXMATRIX              g_Proj;
        bool                    g_bActive  = false;
    
        #define D3DFVF_VERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
        struct VERTEXTXT
        {
            D3DXVECTOR3 position;
            D3DCOLOR    color;
            FLOAT       tu, tv;
        };
        
  2. 頂点シェーダの作成です。
    texture.vsh をアセンブルして Shader を作成します。
        HRESULT InitVertexShader()
        {   LPD3DXBUFFER pVS;
    
            if (FAILED(D3DXAssembleShaderFromFile("texture.vsh",NULL,NULL,0,&pVS,NULL)))    return E_FAIL;
            if (FAILED(g_pDEV->CreateVertexShader((DWORD*)pVS->GetBufferPointer(),&g_Shader)))
            {   pVS->Release();  return E_FAIL;  }
            pVS->Release();
            return S_OK;
        }
        
  3. VertexBuffer に Texture を張った六角形の筒を生成します。
    詳細は VertexBuffer に多角形の筒を設定して描画する を参照して下さい。
    HRESULT InitGeometry()
  4. デバイス/モード等の初期化です。
    MyDx3d Object Class をインスタンス化して、デバイスを取得します。
    InitDevices(HWND hWnd)
  5. 取得したオブジェクトを開放します。
    g_pDEV は MyDx3d Object Class の Constructor で開放されます。
        VOID Cleanup()
        {
            SAFE_RELEASE(g_Shader);
            SAFE_RELEASE(g_pTex);
            SAFE_RELEASE(g_pVB);
            SAFE_DELETE(mydx3d);
        }
        
  6. SetupMatrices() でマテリアルを設定します。
    時刻を取得して Rotate() でY軸を基点にして View 座標を回転しています。
        VOID SetupMatrices()
        {   D3DXVECTOR3     v(0.0f, 3.0f,-5.0f);
    
            //View 座標の回転
            mydx3d->Rotate(&v,&D3DXVECTOR3(0,0,0),timeGetTime()/50.0f,1);
            D3DXMatrixLookAtLH(&g_View,(D3DXVECTOR3*)&v,&D3DXVECTOR3(0,0,0),&D3DXVECTOR3(0,1,0));
            D3DXMatrixPerspectiveFovLH(&g_Proj,D3DX_PI/4,800.0f/600.0f,1.0f,100.0f);
        }
        
  7. 六角形の筒を描画する関数です。
    SetTexture() でテクスチャを設定します。
    SetVertexShader() でカクタムシェーダを設定します。
    SetVertexShaderConstantF(0,(float*)&m,4) で透視変換マトリックスを0番~3番のレジスタに設定します。
    SetStreamSource() で VertexBuffer のデータを Shader に渡します。
    DrawIndexedPrimitive() でカクタムシェーダを使って六角形の筒を描画します。
        //描画処理
        VOID Render()
        {
            if (!g_pDEV || !g_bActive)  return;
            g_pDEV->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0,255),1.0f,0);
            g_pDEV->SetTexture(0,g_pTex);
            g_pDEV->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE );    //カリングの設定
    
            //☆専用の Shader を使って描画
            g_pDEV->BeginScene();
            SetupMatrices();
            g_pDEV->SetVertexShader(g_Shader);              //シェーダの設定
            D3DXMATRIX  m;
            D3DXMatrixMultiply(&m,&g_View,&g_Proj);         //視点座標変換+透視変換を頂点シェーダで行う
            D3DXMatrixTranspose(&m,&m);                     //セットするのは転置行列
            g_pDEV->SetVertexShaderConstantF(0,(float*)&m,4); //視点・透視変換
    
            g_pDEV->SetStreamSource(0,g_pVB,0,sizeof(VERTEXTXT));
            g_pDEV->SetFVF(D3DFVF_VERTEX);                  //頂点フォーマット設定
            g_pDEV->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2*KAKU-2);
            g_pDEV->EndScene();
            g_pDEV->Present(NULL,NULL,NULL,NULL);
        }
        
  8. MsgProc(), WinMain() はいつもと同じです。
    InitDevices() でデバイスの設定と初期化を行います。
    Render() でレンダリングを行います。
    Cleanup() で全てのオブジェクトとリソースを開放します。

頂点シェーダ(Texture.vsh) のソースコードです。

m4x4 oPos,v0,c0 でビューと透視変換マトリックスを設定します。
mov oT0,v2 で Texture 座標を設定します。
vs_2_0              // バージョン2.0の頂点シェーダを使う

dcl_position0 v0    // 頂点の位置0をv0レジスタにマッピングする
dcl_texcoord0 v2    // テクスチャ座標0をv2レジスタに関連付ける

m4x4 oPos, v0, c0   // v0とc0~c3行列を掛け合わせて、oPosに出力する
mov oT0, v2         // oT0レジスタに、テクスチャ座標を出力する

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

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

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