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