#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); int bActive = 0; int bFullScreen = 0; D3DPRESENT_PARAMETERS d3dpp; D3DFORMAT dspfmt; LPDIRECT3D9 pD3D = NULL; LPDIRECT3DDEVICE9 pDevice = NULL; LPDIRECT3DTEXTURE9 pTexture = NULL; LPDIRECT3DVERTEXBUFFER9 pVerBuf = NULL; LPDIRECT3DINDEXBUFFER9 pIndBuf = NULL; typedef struct _D3DLVERTEX_{ float x, y, z; DWORD color; float tu0, tv0; }LVERTEX; void drawPoint(int x, int y, int r, int g, int b, int a){ D3DLOCKED_RECT pLockedRect; pTexture->LockRect(0, &pLockedRect, NULL, 0); unsigned char *p = (unsigned char *)pLockedRect.pBits + pLockedRect.Pitch * y + x * 4; p[0] = (unsigned char)b; p[1] = (unsigned char)g; p[2] = (unsigned char)r; p[3] = (unsigned char)a; pTexture->UnlockRect(0); } int initD3D(void){ int i, t; D3DDISPLAYMODE dsp; LVERTEX *arVer; WORD *arIdx; pD3D = Direct3DCreate9(D3D_SDK_VERSION); if(pD3D == NULL){ return false; } // 現在のディスプレイモードを得る if(FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dsp))){ return false; } 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.BackBufferWidth = SCREEN_WIDTH; d3dpp.BackBufferHeight = SCREEN_HEIGHT; d3dpp.BackBufferCount = 1; 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 false; } } } // 頂点バッファデータの作成 pDevice->CreateVertexBuffer(sizeof(LVERTEX) * 4, 0, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, D3DPOOL_MANAGED, &pVerBuf, NULL); pVerBuf->Lock(0, 0, (void **)&arVer, 0); arVer[0].x = -2.0f; arVer[0].y = 2.0f; arVer[0].z = 0.0f; arVer[0].color = D3DCOLOR_XRGB(255, 255, 255); arVer[0].tu0 = 0.0f; arVer[0].tv0 = 0.0f; arVer[1].x = -2.0f; arVer[1].y = -2.0f; arVer[1].z = 0.0f; arVer[1].color = D3DCOLOR_XRGB(255, 255, 255); arVer[1].tu0 = 0.0f; arVer[1].tv0 = 1.0f; arVer[2].x = 2.0f; arVer[2].y = -2.0f; arVer[2].z = 0.0f; arVer[2].color = D3DCOLOR_XRGB(255, 255, 255); arVer[2].tu0 = 1.0f; arVer[2].tv0 = 1.0f; arVer[3].x = 2.0f; arVer[3].y = 2.0f; arVer[3].z = 0.0f; arVer[3].color = D3DCOLOR_XRGB(255, 255, 255); arVer[3].tu0 = 1.0f; arVer[3].tv0 = 0.0f; pVerBuf->Unlock(); // インデックスバッファデータの作成 pDevice->CreateIndexBuffer(sizeof(WORD) * 4, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &pIndBuf, NULL); pIndBuf->Lock(0, 0, (void **)&arIdx, 0); arIdx[0] = 0; arIdx[1] = 1; arIdx[2] = 2; arIdx[3] = 3; pIndBuf->Unlock(); D3DXCreateTexture(pDevice, 4, 4, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture); for(t = 0; t < 4; t++){ for(i = 0; i < 4; i++){ if(t == 0 || t == 3 || i == 0 || i == 3){ drawPoint(i, t, 255, 0, 0, 255); } else{ drawPoint(i, t, 0, 0, 255, 100); } } } return 1; } int initRender(void){ float fAspect; D3DVIEWPORT9 vp; D3DXMATRIX mat; pDevice->GetViewport(&vp); fAspect = (float)vp.Width / (float)vp.Height; // Z方向(視点 -240.0 手前 -10.0 中心 0.0 奥 10.0) Y方向の視野角 90度 D3DXMatrixPerspectiveFovLH(&mat, D3DXToRadian(90.0f), fAspect, 230.0f, 250.0f); pDevice->SetTransform(D3DTS_PROJECTION, &mat); D3DXMatrixLookAtLH(&mat, &D3DXVECTOR3(0.0f, 0.0f, -240.0f), &D3DXVECTOR3(0, 0, 0), &D3DXVECTOR3(0, 1, 0)); pDevice->SetTransform(D3DTS_VIEW, &mat); pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); // NONE or CW or CCW pDevice->SetRenderState(D3DRS_LIGHTING, FALSE); pDevice->SetRenderState(D3DRS_ZENABLE, TRUE); 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); // 透過色はZバッファに書き込まない pDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); pDevice->SetRenderState(D3DRS_ALPHAREF, 0); pDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER); return 1; } void deinitD3d(void){ RELEASE(pTexture); RELEASE(pDevice); RELEASE(pD3D); } 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: 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; } if(bFullScreen != 1)DrawMenuBar(g_hWnd); initRender(); 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 drawIdle(void){ D3DXMATRIX mat, mat2; // 画面を黒で塗りつぶし pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0, 0); //頂点フォーマットの設定 pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1); pDevice->SetTexture(0, pTexture); if(SUCCEEDED(pDevice->BeginScene())){ D3DXMatrixIdentity(&mat); D3DXMatrixTranslation(&mat2, -320.0f + 2.0f, 240.0f - 2.0f, 0.0f); mat *= mat2; pDevice->SetTransform(D3DTS_WORLD, &mat); //頂点バッファをセット pDevice->SetStreamSource(0, pVerBuf, 0, sizeof(LVERTEX)); //インデックスバッファをセット pDevice->SetIndices(pIndBuf); //ポリゴンの描画 pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN, 0, 0, 4, 0, 2); pDevice->EndScene(); if(FAILED(pDevice->Present(NULL, NULL, NULL, NULL))){ if(FAILED(pDevice->Reset(&d3dpp))){ return 0; } } } return 1; } 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; }