#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; LPDIRECT3DPIXELSHADER9 pPS = NULL; typedef struct _D3DLVERTEX_{ float x, y, z; float tu0, tv0; }LVERTEX; LVERTEX ver1[4] ={ {-2, 2, 0, 0.0f, 0.0f}, {-2, -2, 0, 0.0f, 1.0f}, { 2, -2, 0, 1.0f, 1.0f}, { 2, 2, 0, 1.0f, 0.0f} }; // ピクセル・シェーダ const char szPS[] = "ps.1.1 \n"\ "tex t0 \n"\ "mul r0, t0, c0 \n"; 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; DWORD vprocessing = D3DCREATE_HARDWARE_VERTEXPROCESSING; D3DCAPS9 caps; D3DDISPLAYMODE dsp; pD3D = Direct3DCreate9(D3D_SDK_VERSION); if(pD3D == NULL){ return false; } // 画面のチェック if(FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dsp))){ return false; } // シェーダのチェック pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps); if(caps.MaxVertexShaderConst < 4){ vprocessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING; } else if(caps.VertexShaderVersion < D3DVS_VERSION(1, 1)){ vprocessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING; } else if(caps.PixelShaderVersion < D3DVS_VERSION(1, 1)){ vprocessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING; } 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 or HAL if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, vprocessing, &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, 255, 255, 255); } else{ drawPoint(i, t, 0, 0, 0, 0); } } } return 1; } int initRender(void){ float fAspect; D3DVIEWPORT9 vp; D3DXMATRIX mat; LPD3DXBUFFER pCode; pDevice->GetViewport(&vp); fAspect = (float)vp.Width / (float)vp.Height; // 可視台の設定 D3DXMatrixPerspectiveFovLH(&mat, D3DXToRadian(90.0f), fAspect, 230.0f, 250.0f); pDevice->SetTransform(D3DTS_PROJECTION, &mat); // z方向の -240 の位置から原点から 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); // Zバッファをオフ 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->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); //pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); //pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); // アセンブルシェーダを有効に D3DXAssembleShader(szPS, sizeof(szPS) - 1, NULL, NULL, 0, &pCode, NULL); pDevice->CreatePixelShader((DWORD *)pCode->GetBufferPointer(), &pPS); RELEASE(pCode); return 1; } void deinitD3d(void){ RELEASE(pPS); 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: // break; default: return DefWindowProc(hWnd, msg, wParam, lParam); } return 0L; } int drawIdle(void){ static int r = 0; D3DXMATRIX mat, mat2; r += 1; // 画面のクリア pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0, 0); pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_TEX1); pDevice->SetTexture(0, pTexture); if(SUCCEEDED(pDevice->BeginScene())){ D3DXMatrixIdentity(&mat); // 拡大 D3DXMatrixScaling(&mat2, 10.0f, 10.0f, 10.0f); mat *= mat2; // 回転 D3DXMatrixRotationZ(&mat2, D3DXToRadian((float)r + 20.0f)); mat *= mat2; // 移動 D3DXMatrixTranslation(&mat2, 0.0f - 2.0f, 0.0f + 2.0f, 0.0f); mat *= mat2; pDevice->SetTransform(D3DTS_WORLD, &mat); // シェーダ処理 D3DXVECTOR4 c0(1.0f, 0.0f, 0.0f, 0.1f * (r % 10)); pDevice->SetPixelShaderConstantF(0, (float *)&c0, 1); pDevice->SetPixelShader(pPS); pDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, ver1, sizeof(LVERTEX)); pDevice->SetPixelShader(NULL); 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; }