|
|
三角形のポリゴンの各頂点に、赤、緑、青の各色を設定して描画する。
#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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|