#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; LPDIRECT3DTEXTURE9 pWorkTexture = NULL; //LPDIRECT3DSURFACE9 pWorkDepthStencil = NULL; typedef struct _D3DLVERTEX_{ float x, y, z; float tu0, tv0; }LVERTEX; LVERTEX ver1[4] ={ {-4, 4, 0, 0.0f, 0.0f}, {-4, -4, 0, 0.0f, 1.0f}, { 4, -4, 0, 1.0f, 1.0f}, { 4, 4, 0, 1.0f, 0.0f} }; LVERTEX ver2[4] ={ {-SCREEN_WIDTH , SCREEN_HEIGHT, 0, 0.0f, 0.0f}, {-SCREEN_WIDTH , 0, 0, 0.0f, 1.0f}, {0, 0, 0, 1.0f, 1.0f}, {0, SCREEN_HEIGHT, 0, 1.0f, 0.0f} }; 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; 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 = FALSE; // 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; } } } 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); } } } //pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); //pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); //pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); //pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); //pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); //pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); 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, FALSE); 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); //pDevice->GetDepthStencilSurface(&pWorkDepthStencil); pDevice->CreateTexture(SCREEN_WIDTH, SCREEN_HEIGHT, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pWorkTexture, NULL); pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); return 1; } void deinitD3d(void){ //RELEASE(pWorkDepthStencil); RELEASE(pWorkTexture); 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; } // D3DPOOL_DEFAULT のテクスチャは解放しておくこと RELEASE(pWorkTexture); 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){ LPDIRECT3DSURFACE9 rt; LPDIRECT3DSURFACE9 pBackSurface; D3DXMATRIX mat, mat2; pDevice->GetRenderTarget(0, &pBackSurface); if(SUCCEEDED(pWorkTexture->GetSurfaceLevel(0, &rt))) { pDevice->SetRenderTarget(0, rt); rt->Release(); //pDevice->SetDepthStencilSurface(pWorkDepthStencil); } //頂点フォーマットの設定 pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_TEX1); // 画面を半透明の黒で塗りつぶし pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(127, 0, 0, 0), 1.0, 0); pDevice->SetTexture(0, pTexture); // テクスチャへのレンダリング if(SUCCEEDED(pDevice->BeginScene())){ D3DXMatrixRotationZ(&mat, D3DXToRadian(0.0f)); D3DXMatrixTranslation(&mat2, -320.0f + 4.0f, 240.0f - 4.0f, 0.0f); mat *= mat2; pDevice->SetTransform(D3DTS_WORLD, &mat); pDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, ver1, sizeof(LVERTEX)); D3DXMatrixRotationZ(&mat, D3DXToRadian(0.0f)); D3DXMatrixTranslation(&mat2, 320.0f - 4.0f, -240.0f + 4.0f, 0.0f); mat *= mat2; pDevice->SetTransform(D3DTS_WORLD, &mat); pDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, ver1, sizeof(LVERTEX)); pDevice->EndScene(); } pDevice->SetRenderTarget(0, pBackSurface); // 画面を青で塗りつぶし pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0, 0); //頂点フォーマットの設定 pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_TEX1); pDevice->SetTexture(0, pWorkTexture); if(SUCCEEDED(pDevice->BeginScene())){ D3DXMatrixTranslation(&mat, 320.0f, -240.0f, 0.0f); D3DXMatrixRotationZ(&mat2, D3DXToRadian(20.0f)); mat *= mat2; D3DXMatrixScaling(&mat2, 0.8f, 0.8f, 0.8f); mat *= mat2; pDevice->SetTransform(D3DTS_WORLD, &mat); pDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, ver2, sizeof(LVERTEX)); pDevice->EndScene(); if(FAILED(pDevice->Present(NULL, NULL, NULL, NULL))){ if(FAILED(pDevice->Reset(&d3dpp))){ return 0; } } } pDevice->SetTexture(0, NULL); RELEASE(pBackSurface); 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; }