#include #include #include #include #include "tex.h" #define RELEASE(x) if(x){x->Release();x=NULL;} #define PAI 3.1415f #define TIMER_BLANK 10 #define SCREEN_FPS 60 #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 #define TEX0_WIDTH 64 #define TEX0_HEIGHT 64 #define PARTICLES 200 static long now_time; 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] ={ {-1.0f, 1.0f, 0, 0.0f, 0.0f}, {-1.0f, -1.0f, 0, 0.0f, 1.0f}, {1.0f, -1.0f, 0, 1.0f, 1.0f}, {1.0, 1.0, 0, 1.0f, 0.0f} }; // ピクセル・シェーダ const char szPS[] = "ps.1.1 \n"\ "tex t0 \n"\ "mul r0, t0, c0 \n"; class A{ private: long t0; int end_t; float dd; float x, y; float dx, dy, dz; float r; float s; public: A(long tn, int x, int y){ end_t = 100; init(tn, x, y); } void init(long tn, int x, int y){ float sita1 = (float)((2.0f * PAI) * ((rand() % 100) / 100.0f)); float sita2 = (float)((PAI) * ((rand() % 100) / 100.0f)); this->x = (float)(x + (rand() % 10) - 5); this->y = (float)(y + (rand() % 10) - 5); dx = (float)cos(sita1); dy = (float)sin(sita1); dz = (float)sin(sita2); t0 = tn; r = (float)(rand() % 90); s = (float)(rand() % 40); this->x -= (s / 2); this->y -= (s / 2); } int isEnable(long tn){ int t = tn - t0; if(t - end_t > 0)return 0; return 1; } float getX(long tn){ int t = tn - t0; if(t - end_t > 0)return -1; return dx * t * dz + x; } float getY(long tn){ int t = tn - t0; if(t - end_t > 0)return -1; return dy * t * dz + y; } float getR(){return this->r;} float getS(){return this->s;} float getC(long tn){ int t = tn - t0; if(t - end_t > 0)return 0; return ((end_t - t) / (float)end_t); } }; void makeTexture(int w, int h){ int x, y; D3DLOCKED_RECT pLockedRect; pTexture->LockRect(0, &pLockedRect, NULL, 0); for(y = 0; y < 64; y++){ for(x = 0; x < 64; x++){ unsigned char *p = (unsigned char *)pLockedRect.pBits + pLockedRect.Pitch * y + x * 4; p[0] = (unsigned char)((255 - tex[64 * y + x]) / 2); // 青 p[1] = (unsigned char)((255 - tex[64 * y + x]) / 2); // 緑 p[2] = (unsigned char)(255 - tex[64 * y + x]); // 赤 p[3] = (unsigned char)(255 - tex[64 * y + x]); // α } } pTexture->UnlockRect(0); } int initD3D(void){ D3DCAPS9 d3dCaps; D3DDISPLAYMODE dsp; DWORD vprocessing = D3DCREATE_HARDWARE_VERTEXPROCESSING; 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, &d3dCaps); if(d3dCaps.MaxVertexShaderConst < 4){ vprocessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING; } else if(d3dCaps.VertexShaderVersion < D3DVS_VERSION(1, 1)){ vprocessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING; } else if(d3dCaps.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; } } pDevice->GetDeviceCaps(&d3dCaps); if((d3dCaps.MaxTextureWidth < TEX0_WIDTH) || (d3dCaps.MaxTextureHeight < TEX0_HEIGHT)){ return false; } D3DXCreateTexture(pDevice, TEX0_WIDTH, TEX0_HEIGHT, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture); makeTexture(TEX0_WIDTH, TEX0_HEIGHT); return 1; } int initRender(void){ float fAspect; D3DVIEWPORT9 vp; D3DXMATRIX mat; LPD3DXBUFFER pCode; 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->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); } /* Timer1 */ void CALLBACK Timer1(UINT wID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2){ now_time++; } LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, UINT wParam, LONG lParam){ static TIMECAPS tc; static unsigned int timer1; switch(msg){ case WM_CREATE: timeGetDevCaps(&tc, sizeof(TIMECAPS)); timeBeginPeriod(tc.wPeriodMin); timer1 = timeSetEvent(TIMER_BLANK, tc.wPeriodMin, (LPTIMECALLBACK)Timer1, 100, TIME_PERIODIC); break; 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: timeKillEvent(timer1); timeEndPeriod(tc.wPeriodMin); PostQuitMessage(0); break; case WM_IME_NOTIFY: // IMEのツールバーを非表示に break; default: return DefWindowProc(hWnd, msg, wParam, lParam); } return 0L; } void putCharactor(float x, float y, float r, float s, float c){ D3DXMATRIX mat, mat2, mat3; D3DXMatrixScaling(&mat, s, s, s); D3DXMatrixRotationZ(&mat2, D3DXToRadian(r)); mat *= mat2; D3DXMatrixTranslation(&mat2, -(float)(SCREEN_WIDTH / 2) + (float)x, (float)(SCREEN_HEIGHT / 2) - (float)y, 0.0f); mat *= mat2; pDevice->SetTransform(D3DTS_WORLD, &mat); D3DXVECTOR4 c0(c + 0.05f, c, c - 0.05f, 1.0f); pDevice->SetPixelShaderConstantF(0, (float *)&c0, 1); pDevice->SetPixelShader(pPS); pDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, ver1, sizeof(LVERTEX)); pDevice->SetPixelShader(NULL); } A *a[PARTICLES]; void start(long t){ int i; srand((unsigned)time(NULL)); for(i = 0; i < PARTICLES; i++){ a[i] = new A(t, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2); } return; } int draw(long t){ int i; for(i = 0; i < PARTICLES; i++){ if(a[i]->isEnable(t) == 1){ putCharactor(a[i]->getX(t), a[i]->getY(t), a[i]->getR(), a[i]->getS(), a[i]->getC(t)); } else{ return 0; } } return 1; } void end(){ int i; for(i = 0; i < PARTICLES; i++){ delete a[i]; } return; } int drawIdle(void){ long time; static int state = 0; time = now_time; // 画面を黒で塗りつぶし pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0, 0); //頂点フォーマットの設定 pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_TEX1); pDevice->SetTexture(0, pTexture); if(SUCCEEDED(pDevice->BeginScene())){ // 描画 switch(state){ case 0: start(time); state = 1; break; case 1: if(!draw(time)){ state = 2; } break; case 2: end(); state = 0; default: break; } 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; }