三角形のポリゴンの各頂点に、赤、緑、青の各色を設定して描画する。
#include <d3dx9.h> #pragma comment(lib,"d3d9.lib") #pragma comment(lib,"d3dx9.lib") #define MYWNDTITLE "DX9_Basis1" #define MYWNDCLASS "CLASS_DX9_Basis1" #define WIDTH 320 // 画面の横のサイズ #define HEIGHT 240 // 画面の縦のサイズ struct LVERTEX // 頂点フォーマット構造体 { D3DXVECTOR3 v; // 頂点座標 D3DCOLOR c; // 頂点色 }; #define FVF_LVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE) // 頂点フォーマットの定義 // メッシュの各頂点のデータ形式を定義する。 // D3DXVECTOR3 v; が D3DFVF_XYZ に、D3DCOLOR c; が D3DFVF_DIFFUSE に対応する。 // D3DFVF_XYZ と D3DFVF_DIFFUSE の順番は逆にしても良いが、v と c は順番が決まっている。 // 頂点フォーマット構造体の順番は、頂点座標(float ×3)、RHW(float)、 // 頂点の重み(float ×1〜3)、頂点法線(float ×3)、頂点のポイントサイズ(float)、 // ディフューズ色(DWORD)、スペキュラ色(DWORD)、テクスチャ座標1〜8(float ×1〜4) // となっており、使いたいものだけ選択する。 // ここでは、頂点座標とディフューズ色だけ使用した。 LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pD3DDev = NULL; D3DPRESENT_PARAMETERS g_d3dpp; // 初期設定 HRESULT Initialize(HWND hWnd) { // Direct3D9 を作成 g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); ZeroMemory( &g_d3dpp, sizeof(g_d3dpp) ); g_d3dpp.Windowed = TRUE; // TRUE:ウィンドウモード, FALSE:フルスクリーンモード g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // D3DSWAPEFFECT_DISCARD が最も高速に描画されるらしい g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // バックバッファのフォーマット g_d3dpp.EnableAutoDepthStencil = TRUE; g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // EnableAutoDepthStencil は、Z 座標を使用する場合には必ず、TRUE にする。 // AutoDepthStencilFormat に D3DFMT_D16 を設定すると、 // バックバッファの各ピクセル(画素)に Z 座標用の 16 bit のメモリ領域が確保される。 // つまり、WIDTH * HEIGHT * 16 ビットのメモリ領域が確保される。 // PresentationInterval に D3DPRESENT_INTERVAL_IMMEDIATE を設定すると、 // ディスプレイのリフレッシュレートに同期せずに描画されるようになる。 // 実際の描画は、リフレッシュレート(1秒間に60回描画)以上の速度にはならないのだが、 // Direct3D のサンプルでは、これを採用しているから、内部的には数百 FPS 以上出ている。 // D3D9Device を作成 g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &g_d3dpp, &g_pD3DDev ); // カリング設定 g_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); // カリングは、ポリゴンの片面と両面のどちらを描画するかを設定する。 // 通常、描画のオーバーヘッドを減らすために、片面のみを描画する。 // D3DCULL_NONE : 両面を描画する。 // D3DCULL_CW, D3DCULL_CCW : 頂点の並びが右回りか左回りの面のみを描画する。 // 何も描画されない場合、一度、両面を描画してみる。 // 裏面が表示されていると思った場合は、逆面に設定する。 // Zバッファ有効化(描画に Z 座標が適用される) g_pD3DDev->SetRenderState(D3DRS_ZENABLE, TRUE); // ライト無効化 g_pD3DDev->LightEnable(0, false); g_pD3DDev->SetRenderState(D3DRS_LIGHTING, false); // 頂点フォーマットの定義に法線ベクトルを入れない場合は、ライトは無効にしなくてはならない。 // その場合は、必ず、頂点フォーマットの定義に頂点色を入れなくてはならない。 // 頂点フォーマット設定 g_pD3DDev->SetFVF(FVF_LVERTEX); D3DXMATRIX matView; // ビュー行列を作成する D3DXMatrixLookAtLH(&matView,&D3DXVECTOR3(0,0,-2.5f),&D3DXVECTOR3(0,0,0),&D3DXVECTOR3(0,1,0)); // 最初の引数は受け取る行列、2つ目は視点の座標、 // 3つ目は注視点の座標、4つ目はモデルの上方向のベクトル // ビュー行列設定 g_pD3DDev->SetTransform(D3DTS_VIEW,&matView); D3DXMATRIX matProj; // プロジェクション行列を作成する D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,(float)WIDTH/HEIGHT,0.01f,10.0f); // 最初の引数は受け取る行列、2つ目は視野で通常は45度、3つ目は縦横比、 // 4つ目は視点に最も近い Z 座標、5つ目は視点から最も遠い Z 座標 // プロジェクション行列設定 g_pD3DDev->SetTransform(D3DTS_PROJECTION,&matProj); return S_OK; }// Initialize // 終了処理 void Cleanup() { // Direct3D オブジェクトを解放 if(g_pD3DDev){ g_pD3DDev->Release(); g_pD3DDev = NULL; } if(g_pD3D){ g_pD3D->Release(); g_pD3D = NULL; } }// Cleanup // 描画 void Draw() { LVERTEX lv[3]; // 三角形は頂点が3つ // バックバッファを第3引数の色(この場合は黒)で塗りつぶし、Z 座標を総て 0 に設定する g_pD3DDev->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0,0),1.0f,0); // 描画開始 g_pD3DDev->BeginScene(); lv[0].v.x = -0.5f; // X 座標 lv[0].v.y = 0.5f; // Y 座標 lv[0].v.z = 0; // Z 座標 lv[0].c = D3DCOLOR_ARGB(255,255,0,0); // 色(透明度、赤、緑、青)、この場合は、不透明の赤色 lv[1].v.x = 0.5f; lv[1].v.y = 0.5f; lv[1].v.z = 0; lv[1].c = D3DCOLOR_ARGB(255,0,255,0); lv[2].v.x = 0; lv[2].v.y = -0.5f; lv[2].v.z = 0; lv[2].c = D3DCOLOR_ARGB(255,0,0,255); // ポリゴンの描画 g_pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,1,lv,sizeof(LVERTEX)); // 第2引数は、プリミティブの数である。 // プリミティブとは、三角形のポリゴンの事であり、多角形は三角形ポリゴンを組み合わせて作成する。 // 例えば、四角形の場合は、三角形を2つ組み合わせるので、プリミティブ数は、2 となる。 // 第1引数の D3DPT_TRIANGLEFAN は組み合わせ方である。 // 描画終了 g_pD3DDev->EndScene(); // バックバッファとフロントバッファを交換する g_pD3DDev->Present(NULL,NULL,NULL,NULL); }// Draw LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_CREATE: Initialize(hWnd); // 初期設定 break; case WM_PAINT: Draw(); // オブジェクトの描画 break; case WM_KEYDOWN: switch ( wParam ) { case VK_ESCAPE: // [ESC] キーが押されると終了 SendMessage(hWnd, WM_CLOSE, 0, 0); break; } break; case WM_CLOSE: DestroyWindow(hWnd); Cleanup(); // 終了処理 PostQuitMessage(0); break; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return 0; }// WndProc int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nCmdShow) { WNDCLASSEX wc; HWND hWnd; ZeroMemory(&wc, sizeof(wc)); wc.cbSize = sizeof(WNDCLASSEX); wc.lpfnWndProc = (WNDPROC)WndProc; wc.hInstance = hInst; wc.hIcon = LoadIcon(hInst,IDI_WINLOGO); wc.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszClassName = MYWNDCLASS; if(RegisterClassEx(&wc) == 0) return 0; hWnd = CreateWindowEx(0, MYWNDCLASS, MYWNDTITLE, WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, WIDTH, HEIGHT, NULL, NULL, hInst, NULL); MSG msg; while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }// WinMain |
長方形メッシュの各頂点に、赤、黄、緑、青の各色を設定し、テクスチャーを貼り付けて描画する。
#include <d3dx9.h> #pragma comment(lib,"d3d9.lib") #pragma comment(lib,"d3dx9.lib") #define MYWNDTITLE "DX9_Basis2" #define MYWNDCLASS "CLASS_DX9_Basis2" #define WIDTH 320 #define HEIGHT 240 struct LVERTEX { D3DXVECTOR3 v; // 頂点座標 D3DCOLOR c; // 頂点色 float tu,tv; // テクスチャー座標 }; #define FVF_LVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1) // D3DXVECTOR3 v; が D3DFVF_XYZ に、D3DCOLOR c; が D3DFVF_DIFFUSE に、 // float tu,tv; が D3DFVF_TEX1 に対応する。 LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pD3DDev = NULL; D3DPRESENT_PARAMETERS g_d3dpp; LPDIRECT3DTEXTURE9 g_pTex = NULL; // テクスチャー // 初期設定 HRESULT Initialize(HWND hWnd) { ここまでは、上のサンプルに同じ // カレント ディレクトリーを実行ファイルのディレクトリーに設定 char path[MAX_PATH]; GetModuleFileName(NULL,path,sizeof(path)); char *p = strrchr(path, '\\'); if(p){ strcpy(p, ""); SetCurrentDirectory(path); } // テクスチャーの読み込み D3DXCreateTextureFromFile(g_pD3DDev, "tex1.png", &g_pTex); return S_OK; }// Initialize // 終了処理 void Cleanup() { // テクスチャーを解放 if(g_pTex){ g_pTex->Release(); g_pTex = NULL; } // Direct3D オブジェクトを解放 if(g_pD3DDev){ g_pD3DDev->Release(); g_pD3DDev = NULL; } if(g_pD3D){ g_pD3D->Release(); g_pD3D = NULL; } }// Cleanup // 描画 void Draw() { LVERTEX lv[4]; // 長方形は頂点が4つ g_pD3DDev->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0,0),1.0f,0); g_pD3DDev->BeginScene(); lv[0].v.x = -0.5f; // X 座標 lv[0].v.y = 0.5f; // Y 座標 lv[0].v.z = 0; // Z 座標 lv[0].c = D3DCOLOR_ARGB(255,255,0,0); // 色(赤) lv[0].tu = 0; // テクスチャーの X 座標(比率で表す。1.0が100%) lv[0].tv = 0; // テクスチャーの Y 座標(比率で表す。1.0が100%) lv[1].v.x = 0.5f; lv[1].v.y = 0.5f; lv[1].v.z = 0; lv[1].c = D3DCOLOR_ARGB(255,255,255,0); lv[1].tu = 1; lv[1].tv = 0; lv[2].v.x = 0.5f; lv[2].v.y = -0.5f; lv[2].v.z = 0; lv[2].c = D3DCOLOR_ARGB(255,0,255,0); lv[2].tu = 1; lv[2].tv = 1; lv[3].v.x = -0.5f; lv[3].v.y = -0.5f; lv[3].v.z = 0; lv[3].c = D3DCOLOR_ARGB(255,0,0,255); lv[3].tu = 0; lv[3].tv = 1; if(g_pTex) g_pD3DDev->SetTexture(0, g_pTex); // テクスチャーを適用 g_pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,lv,sizeof(LVERTEX)); // 四角形なのでプリミティブ数は 2 つ g_pD3DDev->EndScene(); g_pD3DDev->SetTexture(0, NULL); // テクスチャーの解除(描画後は解除する) g_pD3DDev->Present(NULL,NULL,NULL,NULL); }// Draw LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 上のサンプルに同じ }// WndProc int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nCmdShow) { 上のサンプルに同じ }// WinMain |
上のサンプルに更に法線ベクトルを追加し、ライトを有効化する
ライトを使う場合は、頂点法線ベクトルが必要である。 #include <d3dx9.h> #pragma comment(lib,"d3d9.lib") #pragma comment(lib,"d3dx9.lib") #define MYWNDTITLE "DX9_Basis3" #define MYWNDCLASS "CLASS_DX9_Basis3" #define WIDTH 320 #define HEIGHT 240 struct LVERTEX { D3DXVECTOR3 v; // 頂点座標 D3DXVECTOR3 n; // 法線ベクトル D3DCOLOR c; // 頂点色 float tu,tv; // テクスチャー座標 }; #define FVF_LVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1) // D3DXVECTOR3 v; が D3DFVF_XYZ に、D3DXVECTOR3 n; が D3DFVF_NORMAL に、 // D3DCOLOR c; が D3DFVF_DIFFUSE に、float tu,tv; が D3DFVF_TEX1 に対応する。 LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pD3DDev = NULL; D3DPRESENT_PARAMETERS g_d3dpp; LPDIRECT3DTEXTURE9 g_pTex = NULL; // テクスチャー // 照明設定 void Set_Light() { D3DXVECTOR3 vecDir; D3DLIGHT9 light; ZeroMemory( &light, sizeof(D3DLIGHT9) ); light.Type = D3DLIGHT_DIRECTIONAL; // ライトの種類(ここでは、平行光線) light.Diffuse.r = 1.0f; // ライトの色 light.Diffuse.g = 1.0f; light.Diffuse.b = 1.0f; vecDir = D3DXVECTOR3(0.866025f,-0.5f,0.5f); // ライトの方向を示すベクトル // ベクトルの正規化 D3DXVec3Normalize((D3DXVECTOR3*)&light.Direction, &vecDir); g_pD3DDev->SetLight(0, &light); g_pD3DDev->LightEnable(0, TRUE); g_pD3DDev->SetRenderState(D3DRS_AMBIENT, 0x00909090); // 画面全体の明るさ }// Set_Light // マテリアル設定(メッシュの質感設定) void Set_Material() { D3DMATERIAL9 mtrl; ZeroMemory(&mtrl, sizeof(D3DMATERIAL9)); mtrl.Diffuse.a = 1.0f; // メッシュの色 mtrl.Diffuse.r = 1.0; mtrl.Diffuse.g = 1.0; mtrl.Diffuse.b = 1.0; mtrl.Ambient = mtrl.Diffuse; // メッシュ全体の明るさも色と同じ g_pD3DDev->SetMaterial(&mtrl); }// Set_Material // 初期設定 HRESULT Initialize(HWND hWnd) { ここまでは上のサンプルに同じ // 頂点データにに法線ベクトルを加える場合は、 // 照明とマテリアルの両方を設定しなくてはならない // 照明設定 Set_Light(); // マテリアル設定 Set_Material(); return S_OK; }// Initialize // 終了処理 void Cleanup() { 上のサンプルに同じ }// Cleanup // 描画 void Draw() { LVERTEX lv[4]; g_pD3DDev->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0,0),1.0f,0); g_pD3DDev->BeginScene(); lv[0].v.x = -0.5f; // X 座標 lv[0].v.y = 0.5f; // Y 座標 lv[0].v.z = 0; // Z 座標 lv[0].n.x = 0; // 法線ベクトルの X 成分 lv[0].n.y = 0; // 法線ベクトルの Y 成分 lv[0].n.z = -1.0f; // 法線ベクトルの Z 成分 lv[0].c = D3DCOLOR_ARGB(255,255,0,0); // 色(赤) lv[0].tu = 0; // テクスチャーの X 座標 lv[0].tv = 0; // テクスチャーの Y 座標 lv[1].v.x = 0.5f; lv[1].v.y = 0.5f; lv[1].v.z = 0; lv[1].n.x = 0; lv[1].n.y = 0; lv[1].n.z = -1.0f; lv[1].c = D3DCOLOR_ARGB(255,255,255,0); lv[1].tu = 1; lv[1].tv = 0; lv[2].v.x = 0.5f; lv[2].v.y = -0.5f; lv[2].v.z = 0; lv[2].n.x = 0; lv[2].n.y = 0; lv[2].n.z = -1.0f; lv[2].c = D3DCOLOR_ARGB(255,0,255,0); lv[2].tu = 1; lv[2].tv = 1; lv[3].v.x = -0.5f; lv[3].v.y = -0.5f; lv[3].v.z = 0; lv[3].n.x = 0; lv[3].n.y = 0; lv[3].n.z = -1.0f; lv[3].c = D3DCOLOR_ARGB(255,0,0,255); lv[3].tu = 0; lv[3].tv = 1; if(g_pTex) g_pD3DDev->SetTexture(0, g_pTex); // テクスチャーを適用 g_pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,lv,sizeof(LVERTEX)); g_pD3DDev->EndScene(); g_pD3DDev->SetTexture(0, NULL); // テクスチャーの解除 g_pD3DDev->Present(NULL,NULL,NULL,NULL); }// Draw LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 上のサンプルに同じ }// WndProc int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nCmdShow) { 上のサンプルに同じ }// WinMain |
#include <d3dx9.h> #pragma comment(lib,"d3d9.lib") #pragma comment(lib,"d3dx9.lib") #define MYWNDTITLE "DX9_Basis4" #define MYWNDCLASS "CLASS_DX9_Basis4" #define WIDTH 320 #define HEIGHT 240 LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pD3DDev = NULL; D3DPRESENT_PARAMETERS g_d3dpp; LPD3DXMESH g_pMeshTea = NULL; // Xメッシュ // 照明設定 void Set_Light() { D3DXVECTOR3 vecDir; D3DLIGHT9 light; ZeroMemory( &light, sizeof(D3DLIGHT9) ); light.Type = D3DLIGHT_DIRECTIONAL; light.Diffuse.r = 1.0f; light.Diffuse.g = 1.0f; light.Diffuse.b = 1.0f; light.Specular = light.Diffuse; // 今回はスペキュラ−色(金属的な反射)を設定 vecDir = D3DXVECTOR3(0.866025f,-0.5f,0.5f); D3DXVec3Normalize((D3DXVECTOR3*)&light.Direction, &vecDir); g_pD3DDev->SetLight(0, &light); g_pD3DDev->LightEnable(0, TRUE); g_pD3DDev->SetRenderState(D3DRS_AMBIENT, 0x00909090); // スペキュラ−色を有効化 g_pD3DDev->SetRenderState(D3DRS_SPECULARENABLE, TRUE); g_pD3DDev->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL); }// Set_Light // マテリアル設定 void Set_Material() { D3DMATERIAL9 mtrl; ZeroMemory(&mtrl, sizeof(D3DMATERIAL9)); mtrl.Diffuse.a = 1.0f; mtrl.Diffuse.r = 0.0; mtrl.Diffuse.g = 0.0; mtrl.Diffuse.b = 1.0; mtrl.Ambient = mtrl.Diffuse; mtrl.Specular.a = 1.0f; // マテリアルにもスペキュラ−色を設定 mtrl.Specular.r = 1.0f; mtrl.Specular.g = 1.0f; mtrl.Specular.b = 1.0f; mtrl.Power = 50; // スペキュラ−色の強度 g_pD3DDev->SetMaterial(&mtrl); }// Set_Material // 初期設定 HRESULT Initialize(HWND hWnd) { // Direct3D9 を作成 g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); ZeroMemory( &g_d3dpp, sizeof(g_d3dpp) ); g_d3dpp.Windowed = TRUE; g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; g_d3dpp.EnableAutoDepthStencil = TRUE; g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // D3D9Device を作成 g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &g_d3dpp, &g_pD3DDev ); // カリング設定 g_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); // Zバッファ有効化 g_pD3DDev->SetRenderState(D3DRS_ZENABLE, TRUE); // Xファイル オブジェクトは頂点フォーマット設定が不要 // ビュー行列設定 D3DXMATRIX matView; D3DXMatrixLookAtLH(&matView,&D3DXVECTOR3(0,0,-5.0f),&D3DXVECTOR3(0,0,0),&D3DXVECTOR3(0,1,0)); g_pD3DDev->SetTransform(D3DTS_VIEW,&matView); // プロジェクション行列設定 D3DXMATRIX matProj; D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,(float)WIDTH/HEIGHT,0.01f,10.0f); g_pD3DDev->SetTransform(D3DTS_PROJECTION,&matProj); // 照明設定 Set_Light(); // マテリアル設定 Set_Material(); // ティーポットの作成 D3DXCreateTeapot(g_pD3DDev, &g_pMeshTea, NULL); return S_OK; }// Initialize // 終了処理 void Cleanup() { // Xメッシュを解放 if(g_pMeshTea){ g_pMeshTea->Release(); g_pMeshTea = NULL; } // Direct3D オブジェクトを解放 if(g_pD3DDev){ g_pD3DDev->Release(); g_pD3DDev = NULL; } if(g_pD3D){ g_pD3D->Release(); g_pD3D = NULL; } }// Cleanup // 描画 void Draw() { g_pD3DDev->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0,0),1.0f,0); g_pD3DDev->BeginScene(); // ワールド行列設定(ティーポットの回転用) static int roll = 0; D3DXMATRIX matWorld; D3DXMatrixRotationY(&matWorld,(float)roll/180*D3DX_PI); g_pD3DDev->SetTransform(D3DTS_WORLD,&matWorld); roll += 5; if(roll >= 360){ roll = 0; } // ティーポットの描画 g_pMeshTea->DrawSubset(0); g_pD3DDev->EndScene(); g_pD3DDev->Present(NULL,NULL,NULL,NULL); }// Draw LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_CREATE: Initialize(hWnd); // 初期設定 SetTimer(hWnd,1,100,NULL); // タイマー設定 break; case WM_TIMER: Draw(); // オブジェクトの描画 break; case WM_KEYDOWN: switch ( wParam ) { case VK_ESCAPE: // [ESC] キーが押されると終了 SendMessage(hWnd, WM_CLOSE, 0, 0); break; } break; case WM_CLOSE: KillTimer(hWnd,1); DestroyWindow(hWnd); Cleanup(); // 終了処理 PostQuitMessage(0); break; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return 0; }// WndProc int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nCmdShow) { 上のサンプルに同じ }// WinMain |
DrawPrimitiveUP() を使うよりもメッシュで最適化してから、DrawSubset() する方が高速に描画できる
#include <d3dx9.h> #pragma comment(lib,"d3d9.lib") #pragma comment(lib,"d3dx9.lib") #define MYWNDTITLE "DX9_Basis5" #define MYWNDCLASS "CLASS_DX9_Basis5" #define WIDTH 320 // 画面の横のサイズ #define HEIGHT 240 // 画面の縦のサイズ LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pD3DDev = NULL; D3DPRESENT_PARAMETERS g_d3dpp; LPD3DXMESH g_pMesh = NULL; // メッシュ LPDIRECT3DTEXTURE9 g_pTex = NULL; // テクスチャー // メッシュ作成 void Create_CubeMesh() { const int v_num = 8; // 頂点数 const int f_num = 12; // 面数 // 頂点座標 D3DXVECTOR3 vtx[v_num] = {D3DXVECTOR3(0.5f,0.5f,-0.5f),D3DXVECTOR3(0.5f,0.5f,0.5f), D3DXVECTOR3(-0.5f,0.5f,0.5f),D3DXVECTOR3(-0.5f,0.5f,-0.5f), D3DXVECTOR3(0.5f,-0.5f,-0.5f),D3DXVECTOR3(0.5f,-0.5f,0.5f), D3DXVECTOR3(-0.5f,-0.5f,0.5f),D3DXVECTOR3(-0.5f,-0.5f,-0.5f)}; // テクスチャ座標 D3DXVECTOR2 tex[v_num] = {D3DXVECTOR2(1,0),D3DXVECTOR2(1,0),D3DXVECTOR2(0,0),D3DXVECTOR2(0,0), D3DXVECTOR2(1,1),D3DXVECTOR2(1,1),D3DXVECTOR2(0,1),D3DXVECTOR2(0,1)}; // 各面を構成する頂点番号 int face[f_num][3] = {{3,2,1},{3,1,0},{0,1,5},{0,5,4},{1,2,6},{1,6,5}, {2,3,7},{2,7,6},{3,0,4},{3,4,7},{4,5,6},{4,6,7}}; BYTE *pBuf1 = NULL; WORD *pBuf2 = NULL; DWORD *pBuf3 = NULL; DWORD dwFVF1 = D3DFVF_XYZ | D3DFVF_TEX1; DWORD dwFVF2 = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1; int i; // メッシュオブジェクト作成 D3DXCreateMeshFVF(f_num, v_num, D3DXMESH_MANAGED, dwFVF1, g_pD3DDev, &g_pMesh); // 頂点情報設定 g_pMesh->LockVertexBuffer(D3DLOCK_DISCARD | D3DLOCK_DONOTWAIT, (LPVOID*)&pBuf1); for(i=0; i<v_num; i++){ memcpy(pBuf1, &vtx[i], sizeof(D3DXVECTOR3)); pBuf1 += sizeof(D3DXVECTOR3); if(dwFVF1 & D3DFVF_TEX1){ memcpy(pBuf1, &tex[i], sizeof(D3DXVECTOR2)); pBuf1 += sizeof(D3DXVECTOR2); } } g_pMesh->UnlockVertexBuffer(); // 面を構成する座標番号の設定 g_pMesh->LockIndexBuffer(D3DLOCK_DISCARD | D3DLOCK_DONOTWAIT, (LPVOID*)&pBuf2); for(i=0; i<f_num; i++){ *pBuf2 ++ = face[i][0]; *pBuf2 ++ = face[i][1]; *pBuf2 ++ = face[i][2]; } g_pMesh->UnlockIndexBuffer(); // 属性バッファ設定 g_pMesh->LockAttributeBuffer(D3DLOCK_DISCARD | D3DLOCK_DONOTWAIT, &pBuf3); for(i=0; i<f_num; i++){ *pBuf3 ++ = 0; } g_pMesh->UnlockAttributeBuffer(); // 属性テーブル設定 D3DXATTRIBUTERANGE attr; attr.AttribId = 0; attr.FaceStart = 0; attr.FaceCount = f_num; attr.VertexStart = 0; attr.VertexCount = v_num; g_pMesh->SetAttributeTable(&attr, 1); // 頂点法線追加 LPD3DXMESH pTempMesh = NULL; g_pMesh->CloneMeshFVF(0L, dwFVF2, g_pD3DDev, &pTempMesh); g_pMesh->Release(); g_pMesh = NULL; if(pTempMesh) g_pMesh = pTempMesh; D3DXComputeNormals(g_pMesh, NULL); // メッシュ最適化(描画速度向上) g_pMesh->OptimizeInplace( D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_IGNOREVERTS | D3DXMESHOPT_VERTEXCACHE | D3DXMESHOPT_DEVICEINDEPENDENT, NULL, NULL, NULL, NULL ); }// Create_CubeMesh // 照明設定 void Set_Light() { D3DXVECTOR3 vecDir; D3DLIGHT9 light; ZeroMemory( &light, sizeof(D3DLIGHT9) ); light.Type = D3DLIGHT_DIRECTIONAL; light.Diffuse.r = 1.0f; light.Diffuse.g = 1.0f; light.Diffuse.b = 1.0f; vecDir = D3DXVECTOR3(0.866025f,-0.5f,0.5f); D3DXVec3Normalize((D3DXVECTOR3*)&light.Direction, &vecDir); g_pD3DDev->SetLight(0, &light); g_pD3DDev->LightEnable(0, TRUE); g_pD3DDev->SetRenderState(D3DRS_AMBIENT, 0x00909090); }// Set_Light // マテリアル設定 void Set_Material() { D3DMATERIAL9 mtrl; ZeroMemory(&mtrl, sizeof(D3DMATERIAL9)); mtrl.Diffuse.a = 1.0f; mtrl.Diffuse.r = 1.0; mtrl.Diffuse.g = 1.0; mtrl.Diffuse.b = 1.0; mtrl.Ambient = mtrl.Diffuse; g_pD3DDev->SetMaterial(&mtrl); }// Set_Material // 初期設定 HRESULT Initialize(HWND hWnd) { // Direct3D9 を作成 g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); ZeroMemory( &g_d3dpp, sizeof(g_d3dpp) ); g_d3dpp.Windowed = TRUE; g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; g_d3dpp.EnableAutoDepthStencil = TRUE; g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // D3D9Device を作成 g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &g_d3dpp, &g_pD3DDev ); // カリング設定 g_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); // Zバッファ有効化 g_pD3DDev->SetRenderState(D3DRS_ZENABLE, TRUE); // ビュー行列設定 D3DXMATRIX matView; D3DXMatrixLookAtLH(&matView,&D3DXVECTOR3(0,0,-2.5f),&D3DXVECTOR3(0,0,0),&D3DXVECTOR3(0,1,0)); g_pD3DDev->SetTransform(D3DTS_VIEW,&matView); // プロジェクション行列設定 D3DXMATRIX matProj; D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,(float)WIDTH/HEIGHT,0.01f,10.0f); g_pD3DDev->SetTransform(D3DTS_PROJECTION,&matProj); // メッシュ作成 Create_CubeMesh(); // カレント ディレクトリーを実行ファイルのディレクトリーに設定 char path[MAX_PATH]; GetModuleFileName(NULL,path,sizeof(path)); char *p = strrchr(path, '\\'); if(p){ strcpy(p, ""); SetCurrentDirectory(path); } // テクスチャー設定 D3DXCreateTextureFromFile(g_pD3DDev, "tex1.png", &g_pTex); // 照明設定 Set_Light(); // マテリアル設定 Set_Material(); return S_OK; }// Initialize // 終了処理 void Cleanup() { // メッシュを解放 if(g_pMesh){ g_pMesh->Release(); g_pMesh = NULL; } // テクスチャーを解放 if(g_pTex){ g_pTex->Release(); g_pTex = NULL; } // Direct3D オブジェクトを解放 if(g_pD3DDev){ g_pD3DDev->Release(); g_pD3DDev = NULL; } if(g_pD3D){ g_pD3D->Release(); g_pD3D = NULL; } }// Cleanup // 描画 void Draw() { // 画面クリア g_pD3DDev->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0,0),1.0f,0); // 描画開始 g_pD3DDev->BeginScene(); // テクスチャー適用 if(g_pTex) g_pD3DDev->SetTexture(0, g_pTex); // メッシュ描画 if(g_pMesh) g_pMesh->DrawSubset(0); // Y軸方向回転 static float roll = 0; D3DXMATRIX matRY; D3DXMatrixRotationY(&matRY, roll/180*D3DX_PI); g_pD3DDev->SetTransform(D3DTS_WORLD, &matRY); roll += 1; if(roll >= 360) roll = 0; // 描画終了 g_pD3DDev->EndScene(); // テクスチャー解除 g_pD3DDev->SetTexture(0, NULL); // 画面フリップ g_pD3DDev->Present(NULL,NULL,NULL,NULL); }// Draw LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 上のサンプルに同じ }// WndProc int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nCmdShow) { 上のサンプルに同じ }// WinMain |
メッシュでは、柔軟な頂点フォーマット (FVF) の代わりに宣言子を使う事ができる。
Direct3D10 以降では、宣言子しか使えなくなった。 #include <d3dx9.h> #pragma comment(lib,"d3d9.lib") #pragma comment(lib,"d3dx9.lib") #define MYWNDTITLE "DX9_Basis6" #define MYWNDCLASS "CLASS_DX9_Basis6" #define WIDTH 320 // 画面の横のサイズ #define HEIGHT 240 // 画面の縦のサイズ LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pD3DDev = NULL; D3DPRESENT_PARAMETERS g_d3dpp; LPD3DXMESH g_pMesh = NULL; // メッシュ情報 LPDIRECT3DTEXTURE9 g_pTex = NULL; // テクスチャー // メッシュ作成 void Create_CubeMesh() { const int v_num = 8; // 頂点数 const int f_num = 12; // 面数 // 頂点座標 D3DXVECTOR3 vtx[v_num] = {D3DXVECTOR3(0.5f,0.5f,-0.5f),D3DXVECTOR3(0.5f,0.5f,0.5f), D3DXVECTOR3(-0.5f,0.5f,0.5f),D3DXVECTOR3(-0.5f,0.5f,-0.5f), D3DXVECTOR3(0.5f,-0.5f,-0.5f),D3DXVECTOR3(0.5f,-0.5f,0.5f), D3DXVECTOR3(-0.5f,-0.5f,0.5f),D3DXVECTOR3(-0.5f,-0.5f,-0.5f)}; // テクスチャ座標 D3DXVECTOR2 tex[v_num] = {D3DXVECTOR2(1,0),D3DXVECTOR2(1,0),D3DXVECTOR2(0,0),D3DXVECTOR2(0,0), D3DXVECTOR2(1,1),D3DXVECTOR2(1,1),D3DXVECTOR2(0,1),D3DXVECTOR2(0,1)}; // 各面を構成する頂点番号 int face[f_num][3] = {{3,2,1},{3,1,0},{0,1,5},{0,5,4},{1,2,6},{1,6,5}, {2,3,7},{2,7,6},{3,0,4},{3,4,7},{4,5,6},{4,6,7}}; // 宣言子 const D3DVERTEXELEMENT9 decl[] = { {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END() }; BYTE *pBuf1 = NULL; WORD *pBuf2 = NULL; DWORD *pBuf3 = NULL; DWORD dwFVF1 = D3DFVF_XYZ | D3DFVF_TEX1; int i; // メッシュオブジェクト作成 D3DXCreateMeshFVF(f_num, v_num, D3DXMESH_MANAGED, dwFVF1, g_pD3DDev, &g_pMesh); // 頂点情報設定 g_pMesh->LockVertexBuffer(D3DLOCK_DISCARD | D3DLOCK_DONOTWAIT, (LPVOID*)&pBuf1); for(i=0; i<v_num; i++){ memcpy(pBuf1, &vtx[i], sizeof(D3DXVECTOR3)); pBuf1 += sizeof(D3DXVECTOR3); if(dwFVF1 & D3DFVF_TEX1){ memcpy(pBuf1, &tex[i], sizeof(D3DXVECTOR2)); pBuf1 += sizeof(D3DXVECTOR2); } } g_pMesh->UnlockVertexBuffer(); // 面を構成する座標番号の設定 g_pMesh->LockIndexBuffer(D3DLOCK_DISCARD | D3DLOCK_DONOTWAIT, (LPVOID*)&pBuf2); for(i=0; i<f_num; i++){ *pBuf2 ++ = face[i][0]; *pBuf2 ++ = face[i][1]; *pBuf2 ++ = face[i][2]; } g_pMesh->UnlockIndexBuffer(); // 属性バッファ設定 g_pMesh->LockAttributeBuffer(D3DLOCK_DISCARD | D3DLOCK_DONOTWAIT, &pBuf3); for(i=0; i<f_num; i++){ *pBuf3 ++ = 0; } g_pMesh->UnlockAttributeBuffer(); // 属性テーブル設定 D3DXATTRIBUTERANGE attr; attr.AttribId = 0; attr.FaceStart = 0; attr.FaceCount = f_num; attr.VertexStart = 0; attr.VertexCount = v_num; g_pMesh->SetAttributeTable(&attr, 1); // 頂点法線追加 LPD3DXMESH pTempMesh = NULL; g_pMesh->CloneMesh(NULL, decl, g_pD3DDev, &pTempMesh); g_pMesh->Release(); g_pMesh = NULL; if(pTempMesh) g_pMesh = pTempMesh; D3DXComputeNormals(g_pMesh, NULL); // メッシュ最適化(描画速度向上) g_pMesh->OptimizeInplace( D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_IGNOREVERTS | D3DXMESHOPT_VERTEXCACHE | D3DXMESHOPT_DEVICEINDEPENDENT, NULL, NULL, NULL, NULL ); }// Create_CubeMesh // 照明設定 void Set_Light() { 上のサンプルに同じ }// Set_Light // マテリアル設定 void Set_Material() { 上のサンプルに同じ }// Set_Material // 初期設定 HRESULT Initialize(HWND hWnd) { 上のサンプルに同じ }// Initialize // 終了処理 void Cleanup() { 上のサンプルに同じ }// Cleanup // 描画 void Draw() { 上のサンプルに同じ }// Draw LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 上のサンプルに同じ }// WndProc int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nCmdShow) { 上のサンプルに同じ }// WinMain |
プログラマブルシェーダには、頂点シェーダとピクセルシェーダがあり、
また、それぞれにプログラミング手法として、 アセンブリ言語のような LLSL (Low Level Shader Language)と C言語のような HLSL (High Level Shader Language)とがある。 以下のサンプルでは、HLSLを使っている。 頂点シェーダは、固定機能も使える上に、ピクセルシェーダも合わせると、 頂点単位のライティングやバンプマッピングも使えるようになる。 頂点シェーダは、頂点ごとに透視変換を行うため、行列設定は不要である。 頂点色設定も可能であるため、場合によっては、照明、マテリアル、テクスチャ設定も不要になる。 シェーダの説明は、「DirectX 逆引き大全500の極意」が分かりやすい。 #include <d3dx9.h> #pragma comment(lib,"d3d9.lib") #pragma comment(lib,"d3dx9.lib") #define MYWNDTITLE "DX9_Basis7" #define MYWNDCLASS "CLASS_DX9_Basis7" #define WIDTH 320 // 画面の横のサイズ #define HEIGHT 240 // 画面の縦のサイズ const char g_szEffect[] = "struct VS_IN" "{" "float4 Pos : POSITION;" // 頂点座標 "float3 Normal : NORMAL;" // 頂点法線ベクトル "};" "struct VS_OUT" "{" "float4 Pos : POSITION;" // 頂点座標 "float4 Color : COLOR;" // 頂点色 "};" "float4x4 matWorld;" // ワールド行列 "float4x4 matAll;" // 透視変換行列 "float3 v3Light;" // 照明の向き // 頂点シェーダ関数 "VS_OUT VS(VS_IN In)" "{" "VS_OUT Out;" "float3 Normal;" // 頂点法線をワールド変換 "Normal = normalize(mul(In.Normal, matWorld));" // 頂点座標を透視変換 "Out.Pos = mul(In.Pos, matAll);" // Lambert 照明モデルで頂点色算出 "Out.Color = saturate(dot(Normal, v3Light));" "return Out;" "}" "technique T0" "{" "pass P0" "{" // 関数をコンパイルして頂点シェーダに渡す "VertexShader = compile vs_2_0 VS();" "}" "}"; LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pD3DDev = NULL; D3DPRESENT_PARAMETERS g_d3dpp; LPD3DXMESH g_pMeshTea = NULL; // Xメッシュオブジェクト LPD3DXEFFECT g_pEffect = NULL; // エフェクトオブジェクト D3DXVECTOR3 g_posLook(0,0,-5.0f); // 視点 D3DXVECTOR3 g_posLookAt(0,0,0); // 注視点 D3DXMATRIX g_matProj,g_matView; // 初期設定 HRESULT Initialize(HWND hWnd) { // Direct3D9 作成 g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); ZeroMemory( &g_d3dpp, sizeof(g_d3dpp) ); g_d3dpp.Windowed = TRUE; g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; g_d3dpp.EnableAutoDepthStencil = TRUE; g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // D3D9Device 作成 g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &g_d3dpp, &g_pD3DDev ); // カリング設定 g_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); // Zバッファ有効化 g_pD3DDev->SetRenderState(D3DRS_ZENABLE, TRUE); // ビュー行列作成 D3DXMatrixLookAtLH(&g_matView, &g_posLook, &g_posLookAt, &D3DXVECTOR3(0,1,0)); // プロジェクション行列作成 D3DXMatrixPerspectiveFovLH(&g_matProj, D3DX_PI/4, (float)WIDTH/HEIGHT, 0.01f, 10.0f); // ティーポット作成 D3DXCreateTeapot(g_pD3DDev, &g_pMeshTea, NULL); // エフェクト読み込み D3DXCreateEffect(g_pD3DDev, g_szEffect, strlen(g_szEffect), NULL, NULL, 0, NULL, &g_pEffect, NULL); // テクニック選択 if(g_pEffect){ g_pEffect->SetTechnique("T0"); } return S_OK; }// Initialize // 終了処理 void Cleanup() { // Xメッシュを解放 if(g_pMeshTea){ g_pMeshTea->Release(); g_pMeshTea = NULL; } // エフェクトを解放 if(g_pEffect){ g_pEffect->Release(); g_pEffect = NULL; } // Direct3D オブジェクトを解放 if(g_pD3DDev){ g_pD3DDev->Release(); g_pD3DDev = NULL; } if(g_pD3D){ g_pD3D->Release(); g_pD3D = NULL; } }// Cleanup // 描画 void Draw() { if(!g_pEffect){ return; } g_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0); g_pD3DDev->BeginScene(); // ワールド変換行列作成 static int roll = 0; D3DXMATRIX matWorld; D3DXMatrixRotationY(&matWorld, (float)roll/180*D3DX_PI); // ワールド変換行列を頂点シェーダに送信 g_pEffect->SetMatrix("matWorld", &matWorld); // 透視変換行列を頂点シェーダに送信 g_pEffect->SetMatrix("matAll", &(matWorld * g_matView * g_matProj)); // 照明の方向を頂点シェーダに送信 g_pEffect->SetVector("v3Light", &D3DXVECTOR4(-0.866025f,0.5f,-0.5f,0.0f)); // 回転角度更新 roll += 5; if(roll >= 360){ roll = 0; } // ティーポットの描画 UINT iPassCount; g_pEffect->Begin(&iPassCount, 0); g_pEffect->Pass(0); g_pMeshTea->DrawSubset(0); g_pEffect->End(); // 描画終了 g_pD3DDev->EndScene(); // 画面フリップ g_pD3DDev->Present(NULL, NULL, NULL, NULL); }// Draw LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 上のサンプルに同じ }// WndProc int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nCmdShow) { 上のサンプルに同じ }// WinMain |
頂点シェーダが頂点情報を設定するのに対し、ピクセルシェーダは画素ごとの色値を設定する。
頂点シェーダの実行後、ピクセルシェーダが実行される。 #include <d3dx9.h> #pragma comment(lib,"d3d9.lib") #pragma comment(lib,"d3dx9.lib") #define MYWNDTITLE "DX9_Basis8" #define MYWNDCLASS "CLASS_DX9_Basis8" #define WIDTH 320 // 画面の横のサイズ #define HEIGHT 240 // 画面の縦のサイズ const char g_szEffect[] = "struct VS_IN" // 頂点シェーダ関数入力用構造体 "{" "float4 Pos : POSITION;" // 頂点座標 "float3 Normal : NORMAL;" // 頂点法線ベクトル "float2 Tex : TEXCOORD0;" // テクスチャー座標 "};" "struct VS_OUT" // 頂点シェーダ関数出力用構造体 "{" "float4 Pos : POSITION;" // 頂点座標 "float4 Color : COLOR;" // 頂点色 "float2 Tex : TEXCOORD0;" // テクスチャー座標 "};" "struct PS_IN" // ピクセルシェーダ関数入力用構造体 "{" "float4 Color : COLOR;" // 頂点色 "float2 Tex : TEXCOORD0;" // テクスチャー座標 "};" "float4x4 matWorld;" // ワールド行列 "float4x4 matAll;" // 透視変換行列 "float3 v3Light;" // 照明の向き "texture texMain;" // テクスチャー "sampler MainSampler = sampler_state" "{" "Texture = <texMain>;" "MinFilter = LINEAR;" "MagFilter = LINEAR;" "MipFilter = NONE;" "};" // 頂点シェーダ関数 "VS_OUT VS(VS_IN In)" "{" "VS_OUT Out;" "float3 Normal;" // 頂点法線をワールド変換 "Normal = normalize(mul(In.Normal, matWorld));" // 頂点座標を透視変換 "Out.Pos = mul(In.Pos, matAll);" // Lambert 照明モデルで頂点色算出 "Out.Color = saturate(dot(Normal, v3Light));" // テクスチャー座標 "Out.Tex = In.Tex;" "return Out;" "}" // ピクセルシェーダ関数 "float4 PS(PS_IN In) : COLOR" "{" // 頂点色にテクスチャー色を追加して返す "return (In.Color + tex2D(MainSampler, In.Tex));" "}" "technique T0" "{" "pass P0" "{" // VS関数をコンパイルして頂点シェーダに渡す "VertexShader = compile vs_2_0 VS();" // PS関数をコンパイルしてピクセルシェーダに渡す "PixelShader = compile ps_2_0 PS();" "}" "}"; LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pD3DDev = NULL; D3DPRESENT_PARAMETERS g_d3dpp; LPD3DXMESH g_pMesh = NULL; // Xメッシュオブジェクト LPDIRECT3DTEXTURE9 g_pTex = NULL; // テクスチャー LPD3DXEFFECT g_pEffect = NULL; // エフェクトオブジェクト D3DXVECTOR3 g_posLook(0,0,-2.0f); // 視点 D3DXVECTOR3 g_posLookAt(0,0,0); // 注視点 D3DXMATRIX g_matProj,g_matView; // メッシュ作成 void Create_CubeMesh() { 上のサンプルに同じ }// Create_CubeMesh // 初期設定 HRESULT Initialize(HWND hWnd) { // Direct3D9 作成 g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); ZeroMemory( &g_d3dpp, sizeof(g_d3dpp) ); g_d3dpp.Windowed = TRUE; g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; g_d3dpp.EnableAutoDepthStencil = TRUE; g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // D3D9Device 作成 g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &g_d3dpp, &g_pD3DDev ); // カリング設定 g_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); // Zバッファ有効化 g_pD3DDev->SetRenderState(D3DRS_ZENABLE, TRUE); // ビュー行列作成 D3DXMatrixLookAtLH(&g_matView, &g_posLook, &g_posLookAt, &D3DXVECTOR3(0,1,0)); // プロジェクション行列作成 D3DXMatrixPerspectiveFovLH(&g_matProj, D3DX_PI/4, (float)WIDTH/HEIGHT, 0.01f, 10.0f); // メッシュ作成 Create_CubeMesh(); // エフェクト読み込み D3DXCreateEffect(g_pD3DDev, g_szEffect, strlen(g_szEffect), NULL, NULL, 0, NULL, &g_pEffect, NULL); // テクニック選択 if(g_pEffect){ g_pEffect->SetTechnique("T0"); } // カレント ディレクトリーを実行ファイルのディレクトリーに設定 char path[MAX_PATH]; GetModuleFileName(NULL,path,sizeof(path)); char *p = strrchr(path, '\\'); if(p){ strcpy(p, ""); SetCurrentDirectory(path); } // テクスチャー設定 D3DXCreateTextureFromFile(g_pD3DDev, "tex1.png", &g_pTex); return S_OK; }// Initialize // 終了処理 void Cleanup() { // Xメッシュを解放 if(g_pMesh){ g_pMesh->Release(); g_pMesh = NULL; } // エフェクトを解放 if(g_pEffect){ g_pEffect->Release(); g_pEffect = NULL; } // テクスチャーを解放 if(g_pTex){ g_pTex->Release(); g_pTex = NULL; } // Direct3D オブジェクトを解放 if(g_pD3DDev){ g_pD3DDev->Release(); g_pD3DDev = NULL; } if(g_pD3D){ g_pD3D->Release(); g_pD3D = NULL; } }// Cleanup // 描画 void Draw() { if(!g_pEffect){ return; } g_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0); g_pD3DDev->BeginScene(); // ワールド行列作成 static int roll = 0; D3DXMATRIX matWorld; D3DXMatrixRotationY(&matWorld, (float)roll/180*D3DX_PI); // ワールド変換行列をシェーダに送信 g_pEffect->SetMatrix("matWorld", &matWorld); // 透視変換行列をシェーダに送信 g_pEffect->SetMatrix("matAll", &(matWorld * g_matView * g_matProj)); // 照明の方向をシェーダに送信 g_pEffect->SetVector("v3Light", &D3DXVECTOR4(-0.866025f,0.5f,-0.5f,0)); // テクスチャーをシェーダに送信 g_pEffect->SetTexture("texMain", g_pTex); // 回転角度更新 roll += 5; if(roll >= 360){ roll = 0; } // メッシュ描画 UINT iPassCount; g_pEffect->Begin(&iPassCount, 0); g_pEffect->Pass(0); g_pMesh->DrawSubset(0); g_pEffect->End(); // 描画終了 g_pD3DDev->EndScene(); // 画面フリップ g_pD3DDev->Present(NULL, NULL, NULL, NULL); }// Draw LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 上のサンプルに同じ }// WndProc int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nCmdShow) { 上のサンプルに同じ }// WinMain |
|
|
|
|
|
|
|