#include #include #include #define RELEASE(x) if(x){x->Release();x=NULL;} #define SCREEN_FPS 60 #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 HINSTANCE g_Inst; HWND g_hWnd; LPCSTR szAppName = "Direct3D"; LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,UINT wParam,LONG lParam); static int bActive = 0; static int bFullScreen = 0; D3DPRESENT_PARAMETERS d3dpp; D3DFORMAT dspfmt; LPDIRECT3D9 pD3D = NULL; LPDIRECT3DDEVICE9 pDevice = NULL; LPDIRECT3DTEXTURE9 pTexture = NULL; // 頂点情報の構造体 typedef struct _D3DLVERTEX_{ float x, y, z; float nx, ny, nz; D3DCOLOR c; float tu0, tv0; }LVERTEX; // 最奥いっぱいに描かれる赤い四角 LVERTEX ver1[4] ={ {-2.0f, 1.5f, 0.5f, 0.0f, 0.0f, -1.0f, 0xFFFF0000, 0.0f, 0.0f}, {-2.0f, -1.5f, 0.5f, 0.0f, 0.0f, -1.0f, 0xFFFF0000, 0.0f, 1.0f}, { 2.0f, -1.5f, 0.5f, 0.0f, 0.0f, -1.0f, 0xFFFF0000, 1.0f, 1.0f}, { 2.0f, 1.5f, 0.5f, 0.0f, 0.0f, -1.0f, 0xFFFF0000, 1.0f, 0.0f} }; // 手前に描かれる緑のテクスチャを貼った四角 LVERTEX ver2[4] ={ {-0.3f, 0.3f, 0.0f, 0.0f, 0.0f, -1.0f, 0xFFFFFFFF, 0.0f, 0.0f}, {-0.3f, -0.3f, 0.0f, 0.0f, 0.0f, -1.0f, 0xFFFFFFFF, 0.0f, 1.0f}, {0.3f, -0.3f, 0.0f, 0.0f, 0.0f, -1.0f, 0xFFFFFFFF, 1.0f, 1.0f}, {0.3f, 0.3f, 0.0f, 0.0f, 0.0f, -1.0f, 0xFFFFFFFF, 1.0f, 0.0f} }; // テクスチャの初期設定 int initTexture(void){ int i, t; D3DLOCKED_RECT pLockedRect; if(FAILED(D3DXCreateTexture(pDevice, 2, 2, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture))){ // or D3DPOOL_SYSTEMMEM return 0; } pTexture->LockRect(0, &pLockedRect, NULL, 0); for(t = 0; t < 2; t++){ for(i = 0; i < 2; i++){ unsigned char *p = (unsigned char *)pLockedRect.pBits + pLockedRect.Pitch * t + i * 4; p[0] = (unsigned char)0; // b p[1] = (unsigned char)255; // g p[2] = (unsigned char)0; // r p[3] = (unsigned char)255; // a } } pTexture->UnlockRect(0); return 1; } // Direct3D の初期化 int initD3D(void){ D3DDISPLAYMODE dsp; pD3D = Direct3DCreate9(D3D_SDK_VERSION); if(pD3D == NULL){ return 0; } // 現在のディスプレイモードを得る if(FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dsp))){ return 0; } dspfmt = dsp.Format; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; //垂直同期でフリップ // フルスクリーン or ウィンドウ if(bFullScreen == 1){ d3dpp.BackBufferFormat = D3DFMT_R5G6B5; d3dpp.Windowed = 0; } else{ d3dpp.BackBufferFormat = dsp.Format; d3dpp.Windowed = 1; } d3dpp.BackBufferCount = 1; d3dpp.BackBufferWidth = SCREEN_WIDTH; d3dpp.BackBufferHeight = SCREEN_HEIGHT; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // T&L HAL if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &pDevice))){ // HAL if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,g_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice))){ // HEL if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, g_hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice))){ return 0; } } } if(initTexture() == 0){ return 0; } return 1; } // Direct3D の後片付け void deinitD3d(void){ RELEASE(pTexture); RELEASE(pDevice); RELEASE(pD3D); } // 視野の初期設定 int initView(void){ float fAspect; D3DVIEWPORT9 vp; D3DXMATRIX mat; pDevice->GetViewport(&vp); fAspect = (float)vp.Width / (float)vp.Height; // Z方向(視点 -1.0 手前 -0.5 中心 0.0 奥 0.5) Y方向の視野角 90度 D3DXMatrixPerspectiveFovLH(&mat, D3DXToRadian(90.0f), fAspect, 0.5f, 1.5f); pDevice->SetTransform(D3DTS_PROJECTION, &mat); D3DXMatrixLookAtLH(&mat, &D3DXVECTOR3(0.0f, 0.0f, -1.0f), &D3DXVECTOR3(0, 0, 0), &D3DXVECTOR3(0, 1, 0)); pDevice->SetTransform(D3DTS_VIEW, &mat); return 1; } // 光源の初期設定 int initLighting(void){ D3DMATERIAL9 mtrl; ZeroMemory(&mtrl, sizeof(D3DMATERIAL9)); mtrl.Diffuse.r = 1.0f; mtrl.Diffuse.g = 1.0f; mtrl.Diffuse.b = 1.0f; mtrl.Diffuse.a = 1.0f; mtrl.Ambient.r = 1.0f; mtrl.Ambient.g = 1.0f; mtrl.Ambient.b = 1.0f; mtrl.Ambient.a = 1.0f; pDevice->SetMaterial(&mtrl); 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; D3DXVECTOR3 vecDir(0.0f, 0.0f, 1.0f); D3DXVec3Normalize(static_cast(&light.Direction), &vecDir); light.Range = 1000.0f; pDevice->SetLight( 0, &light ); pDevice->LightEnable( 0, TRUE ); pDevice->SetRenderState(D3DRS_AMBIENT, 0x00000000); pDevice->SetRenderState(D3DRS_LIGHTING, TRUE); return 1; } // レンダリングに関する初期設定 int initRender(void){ // 視野の初期設定 initView(); // 光源の初期設定 initLighting(); // カリングの設定 pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); // NONE or CW or CCW // Z バッファの設定 pDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL ); // テクスチャの設定 pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_NONE); pDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); // αブレンドの設定 pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); return 1; } // 描画本体 int drawIdle(void){ // 画面を白で塗りつぶし、Zバッファをクリア pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , D3DCOLOR_XRGB(255,255,255), 1.0, 0); //頂点フォーマットの設定 pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1); if(SUCCEEDED(pDevice->BeginScene())){ D3DXMATRIX mat; D3DXMatrixIdentity(&mat); //D3DXMatrixTranslation(&mat, 1.0f, 0.0f, 0.0f); //D3DXMatrixRotationX(&mat, D3DXToRadian(45.0f)); //D3DXMatrixRotationY(&mat, D3DXToRadian(45.0f)); //D3DXMatrixRotationZ(&mat, D3DXToRadian(45.0f)); //D3DXMatrixScaling(&mat, 1.5f, 1.5f, 1.0f); pDevice->SetTransform(D3DTS_WORLD, &mat); pDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, ver1, sizeof(LVERTEX)); pDevice->SetTexture(0, pTexture); pDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, ver2, sizeof(LVERTEX)); pDevice->SetTexture(0, NULL); pDevice->EndScene(); if(FAILED(pDevice->Present(NULL, NULL, NULL, NULL))){ if(FAILED(pDevice->Reset(&d3dpp))){ return 0; } } } return 1; } // ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, UINT wParam, LONG lParam){ switch(msg){ case WM_ACTIVATE: bActive = HIWORD(wParam)?0:1; break; case WM_KEYDOWN: switch(wParam){ case VK_F3: // F3 キーでウィンドウとフルスクリーンを入れ替え bFullScreen = !bFullScreen; if(bFullScreen == 1){ d3dpp.BackBufferFormat = D3DFMT_R5G6B5; d3dpp.Windowed = 0; }else{ d3dpp.BackBufferFormat = dspfmt; d3dpp.Windowed = 1; } if(FAILED(pDevice->Reset(&d3dpp))){ PostMessage(hWnd, WM_CLOSE, 0, 0); return 0L; } initRender(); if(bFullScreen != 1){ DrawMenuBar(g_hWnd); } break; case VK_ESCAPE: PostMessage(hWnd, WM_CLOSE, 0, 0); break; default: break; } break; case WM_DESTROY: PostQuitMessage(0); break; case WM_IME_NOTIFY: // IMEのツールバーを非表示に break; default: return DefWindowProc(hWnd, msg, wParam, lParam); } return 0L; } // メイン int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow){ int result; int cx, cy; WNDCLASS wc; MSG msg; DWORD waittime; // 256色以下のモードで起動不可 HDC dc = GetDC(0); int iBit = GetDeviceCaps(dc, BITSPIXEL); ReleaseDC(0, dc); if(iBit < 15){ MessageBox(0, "256色以下では実行できません", szAppName, MB_ICONSTOP|MB_OK); return 0; } g_Inst=hInst; if(!hPrevInst){ wc.lpszClassName = "Direct3D"; wc.lpfnWndProc = WndProc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.hInstance = hInst; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL,IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszMenuName = NULL; wc.cbClsExtra = 0; wc.cbWndExtra = 0; if(!RegisterClass(&wc)){ return 0; } } cx = SCREEN_WIDTH + GetSystemMetrics(SM_CXDLGFRAME) * 2; cy = SCREEN_HEIGHT + GetSystemMetrics(SM_CYDLGFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION); g_hWnd = CreateWindowEx(0, szAppName, szAppName, WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, cx, cy, (HWND)NULL, (HMENU)NULL, hInst, (LPSTR)NULL); ShowWindow(g_hWnd, nCmdShow); UpdateWindow(g_hWnd); result = initD3D(); if(result == 0){ goto fin; } result = initRender(); if(result == 0){ goto fin; } msg.wParam = 0; while(1){ waittime = GetTickCount(); if(bActive){ if(!drawIdle()){ goto fin; } } else{ WaitMessage(); } do{ while(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)){ if(!GetMessage(&msg, NULL, 0, 0)){ goto fin; } TranslateMessage(&msg); DispatchMessage(&msg); } }while(GetTickCount() < waittime + SCREEN_FPS); } fin: deinitD3d(); return msg.wParam; }