DirectX9 VertexShader
「DirectX9 モデルデータ 」のプログラムをバーテックスシェーダーを使って表現してみました。
ますはバーテックスシェーダープログラム、
vsample01.vsh
//c0-c3 ビュー+透視変換マトリックス // //v0 頂点の座標値 //v1 色情報 vs.2.0 dcl_position v0 dcl_color v1 mov oD0,v1 m4x4 oPos,v0,c0
を用意します。
G9lib.cpp
#include "G9lib.h" //ライブラリ登録 #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "d3dx9.lib") G9lib::G9lib(void) { pD3D = NULL; pD3DDevice = NULL; vShader = NULL; gVBuffer = NULL; } G9lib::~G9lib(void) { if (pD3D) { pD3D->Release(); pD3D = NULL; } if (pD3DDevice) { pD3DDevice->Release(); pD3DDevice = NULL; } if( vShader ){ vShader->Release(); vShader = NULL; } if( gVBuffer ){ gVBuffer->Release(); gVBuffer = NULL; } } //------------------------------------------------------------------------------ //■ライブラリ初期化 //------------------------------------------------------------------------------ bool G9lib::Init( HWND hwnd ) { // Direct3Dオブジェクトの取得 pD3D = Direct3DCreate9(D3D_SDK_VERSION); if (pD3D == NULL) { MessageBox( hwnd, L"Direct3Dの初期化に失敗しました、DirectX 9.0がインストールされているか確認してください。",L"Base",MB_OK | MB_ICONSTOP); return FALSE; } // 現在のディスプレイモードを得る D3DDISPLAYMODE dmode; if (FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dmode))) { MessageBox( hwnd, L"ディスプレイモードの取得に失敗しました。",L"Base",MB_OK | MB_ICONSTOP); return FALSE; } // バックサーフェースのフォーマットをコピーして使用する ZeroMemory(&d3dppApp, sizeof(d3dppApp)); d3dppApp.Windowed = TRUE; // ウィンドウモード d3dppApp.SwapEffect = D3DSWAPEFFECT_DISCARD; // 垂直同期でフリップ d3dppApp.BackBufferCount = 1; d3dppApp.BackBufferFormat = dmode.Format; d3dppApp.EnableAutoDepthStencil = TRUE; d3dppApp.AutoDepthStencilFormat= D3DFMT_D16; // デバイスの作成 if (FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dppApp, &pD3DDevice))) { if (FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dppApp, &pD3DDevice))) { MessageBox( hwnd, L"デバイスの作成に失敗しました、画面モードが16ビットあるいは32ビットになっていることを確認してください。",L"Base",MB_OK | MB_ICONSTOP); return FALSE; } } //------------------------------------------------------------------- LPD3DXBUFFER pVS; if (FAILED(D3DXAssembleShaderFromFile( L"vsample01.vsh",NULL,NULL,0,&pVS,NULL))) return FALSE; if(FAILED(pD3DDevice->CreateVertexShader((DWORD*)pVS->GetBufferPointer(),&vShader))) { pVS->Release(); return FALSE; } pVS->Release(); //------------------------------------------------------------------- void *lpVertices; HRESULT hr; //----------------------------------------- // モデル登録 D3DVERTEXCOR vtx[6]={ { -5.0f, 0.0f, 5.0f, 0xff0000ff }, //青の頂点 { 5.0f, 0.0f, 5.0f, 0xffff0000 }, //赤の頂点 { 0.0f, 8.0f, 2.0f, 0xffffffff }, //白の頂点 { 0.0f, 0.0f, -3.0f, 0xff00ff00 }, //緑の頂点 { -5.0f, 0.0f, 5.0f, 0xff0000ff }, //青の頂点 { 5.0f, 0.0f, 5.0f, 0xffff0000 } //赤の頂点 }; hr= pD3DDevice->CreateVertexBuffer(6*sizeof(D3DVERTEXCOR),0,D3DVERTEXCOR::FVF,D3DPOOL_DEFAULT,&gVBuffer,NULL); if (FAILED(hr)) return FALSE; // 頂点バッファのコピー hr= gVBuffer->Lock(0, sizeof(vtx), (LPVOID*)&lpVertices, 0); if (FAILED(hr)) return FALSE; memcpy(lpVertices, vtx, sizeof(vtx)); g_pVB->Unlock(); //------------------------------------------------------------------- return TRUE; } //------------------------------------------------------------------------------ //■ライブラリ開放 //------------------------------------------------------------------------------ void G9lib::Exit( void ) { } //------------------------------------------------------------------------------ //■テスト描画 //------------------------------------------------------------------------------ void G9lib::TestDraw() { D3DXMATRIX matView; D3DXMATRIX matProj; D3DXMATRIX matWorld; pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0, 0); pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ); //片面 pD3DDevice->SetRenderState( D3DRS_LIGHTING,FALSE); //光源無効 pD3DDevice->BeginScene(); //----------------------------------------- //ワールド座標の回転 D3DXMatrixRotationY( &matWorld,timeGetTime()/5000.0f ); // pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld ); //----------------------------------------- //View 座標の設定 D3DXMatrixLookAtLH(&matView,&D3DXVECTOR3(0.0f, -5.0f, 30.0f), // カメラの位置を表す3次元ベクトル &D3DXVECTOR3(0.0f, 0.0f, 0.0f), // カメラの注視点を表す3次元ベクトル &D3DXVECTOR3(0.0f, 1.0f, 0.0f)); // 上方向を表す3次元ベクトル // pD3DDevice->SetTransform( D3DTS_VIEW, &matView ); //----------------------------------------- //透視変換の設定 D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 10.0f, 2000.0f ); // pD3DDevice->SetTransform( D3DTS_PROJECTION, &matProj ); //----------------------------------------- // Z値に関して pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); pD3DDevice->SetVertexShader(vShader); pD3DDevice->SetFVF(D3DVERTEXCOR::FVF); //頂点フォーマット設定 //----------------------------------------- D3DXMATRIX m; D3DXMatrixTranspose(&m,&(matWorld * matView * matProj)); //転置行列 に変換 pD3DDevice->SetVertexShaderConstantF(0,(float*)&m,4); //視点・透視変換 pD3DDevice->SetStreamSource(0,gVBuffer,0,sizeof(D3DVERTEXCOR)); pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,4); //----------------------------------------- // 描画 pD3DDevice->EndScene(); pD3DDevice->Present(NULL, NULL, NULL, NULL); }
この部分でシェーダプログラムを読み込みます。
LPD3DXBUFFER pVS; if (FAILED(D3DXAssembleShaderFromFile( L"vsample01.vsh",NULL,NULL,0,&pVS,NULL))) return FALSE; if(FAILED(pD3DDevice->CreateVertexShader((DWORD*)pVS->GetBufferPointer(),&vShader))){ pVS->Release(); return FALSE; } pVS->Release();
マトリックスの計算はシェーダ内部でやるので、ここでは定義をしないようにします。
// pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld ); : // pD3DDevice->SetTransform( D3DTS_VIEW, &matView ); : // pD3DDevice->SetTransform( D3DTS_PROJECTION, &matProj );
シェーダー使用を定義
pD3DDevice->SetVertexShader(vShader);
シェーダーにマトリックス情報を渡します。渡すマトリックスは転置行列 に変換する必要があるので注意してください。
D3DXMATRIX m; D3DXMatrixTranspose(&m,&(matWorld * matView * matProj)); //転置行列 に変換 pD3DDevice->SetVertexShaderConstantF(0,(float*)&m,4); //視点・透視変換
これで、ヴァーテックスシェーダを使用したプログラムになりました。
ヴァーテックスシェーダーですが m4x4 をdp4に置き換えても同じ結果が得られます。
//c0-c3 ビュー+透視変換マトリックス // //v0 頂点の座標値 //v1 色情報 vs.2.0 dcl_position v0 dcl_color v1 mov oD0,v1 dp4 oPos.x, v0, c0 dp4 oPos.y, v0, c1 dp4 oPos.z, v0, c2 dp4 oPos.w, v0, c3