#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 ver[4] ={ {-0.1f, 0.1f, 0.0f, 0.0f, 0.0f, -1.0f, 0xFFFFFFFF, 0.0f, 0.0f}, {-0.1f, -0.1f, 0.0f, 0.0f, 0.0f, -1.0f, 0xFFFFFFFF, 0.0f, 1.0f}, {0.1f, -0.1f, 0.0f, 0.0f, 0.0f, -1.0f, 0xFFFFFFFF, 1.0f, 1.0f}, {0.1f, 0.1f, 0.0f, 0.0f, 0.0f, -1.0f, 0xFFFFFFFF, 1.0f, 0.0f} }; // テクスチャの初期設定 int initTexture(void){ int i, t; D3DLOCKED_RECT pLockedRect; unsigned char tex[8][8] = { {0, 0, 0, 1, 1, 0, 0, 0}, {0, 0, 1, 2, 2, 1, 0, 0}, {0, 1, 4, 8, 8, 4, 1, 0}, {1, 2, 8, 8, 8, 8, 2, 1}, {1, 2, 8, 8, 8, 8, 2, 1}, {0, 1, 4, 8, 8, 4, 1, 0}, {0, 0, 1, 2, 2, 1, 0, 0}, {0, 0, 0, 1, 1, 0, 0, 0} }; if(FAILED(D3DXCreateTexture(pDevice, 8, 8, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture))){ // or D3DPOOL_SYSTEMMEM return 0; } pTexture->LockRect(0, &pLockedRect, NULL, 0); for(t = 0; t < 8; t++){ for(i = 0; i < 8; i++){ unsigned char *p = (unsigned char *)pLockedRect.pBits + pLockedRect.Pitch * t + i * 4; p[0] = (unsigned char)100; // b p[1] = (unsigned char)120; // g p[2] = (unsigned char)250; // r p[3] = (unsigned char)tex[t][i]; // a } } pTexture->UnlockRect(0); return 1; } class particle{ private: float x; float y; float z; float dx; float dy; float dz; public: particle() : x(0.0f), y(0.0f), z(0.0f){}; void init(){x = 0.0f; y = 0.0f; z = 0.0f;} void init(const float &dx, const float &dy, const float &dz){this->dx = dx; this->dy = dy; this->dz = dz;init();} void move(){x += dx; y += dy; z += dz;} const float &getX() const {return x;} const float &getY() const {return y;} const float &getZ() const {return z;} void setX(const float &x){this->x = x;} void setY(const float &y){this->y = y;} void setZ(const float &z){this->z = z;} }; class particles{ int p_count; particle *p; float x; float y; float z; public: enum{num_p = 1024}; particles(): p_count(0){}; void initParticles(){p = new particle[num_p];} void deinitParticles(){delete [] p;} void startParticles(const float &x, const float &y, const float &z){ int i; float ra, rb, d1; p_count = 0; this->x = x; this->y = y; this->z = z; for(i = 0; i < num_p; i++){ ra = (rand() % 360) * 0.0174; rb = (rand() % 360) * 0.0174; d1 = (rand() % 100) * 0.0005 + 0.005; p[i].init((float)sin(ra) * d1, (float)cos(ra) * d1, (float)cos(rb) * d1); } } void startParticlesRandPos(){ startParticles((rand() % 1000) * 0.001f - 0.5f , (rand() % 1000) * 0.001f - 0.5f, (rand() % 1000) * 0.001f - 0.5f); } void move(){ int i; p_count++; for(i = 0; i < num_p; i++){ p[i].move(); } } const float &getX() const {return x;} const float &getY() const {return y;} const float &getZ() const {return z;} int getP_count() const {return p_count;} const particle &getP(const int n) const {return p[n];} }; class Objects{ particles *ps; public: enum{num_ps = 4}; void init(){ int i; ps = new particles[num_ps]; for(i = 0; i < num_ps; i++){ ps[i].initParticles(); } } const particles &getPs(const int n) const {return ps[n];} void startParticles(const int n){ps[n].startParticlesRandPos();} void move(){ int i; for(i = 0; i < num_ps; i++){ ps[i].move(); } } void deinit(){ int i; for(i = 0; i < num_ps; i++){ ps[i].deinitParticles(); } delete [] ps; ps = NULL; } }; // 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_ONE); return 1; } // 描画本体 int drawIdle(const Objects &objs){ // 画面を白で塗りつぶし、Zバッファをクリア pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , D3DCOLOR_XRGB(0,0,0), 1.0, 0); //頂点フォーマットの設定 pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1); if(SUCCEEDED(pDevice->BeginScene())){ D3DXMATRIX mat, mat2; D3DXMatrixIdentity(&mat); pDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); int i, t; for(t = 0; t < Objects::num_ps; t++){ const particles &ps = objs.getPs(t); for(i = 0; i < particles::num_p; i++){ const particle &p = ps.getP(i); D3DXMatrixTranslation(&mat, ps.getX() + p.getX(), ps.getY() + p.getY(), ps.getZ() + p.getZ()); //D3DXMatrixRotationX(&mat, D3DXToRadian(45.0f)); //D3DXMatrixRotationY(&mat, D3DXToRadian(45.0f)); D3DXMatrixRotationZ(&mat2, D3DXToRadian(15.0f)); //D3DXMatrixScaling(&mat2, 1.5f, 1.5f, 1.0f); mat *= mat2; pDevice->SetTransform(D3DTS_WORLD, &mat); pDevice->SetTexture(0, pTexture); pDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, ver, sizeof(LVERTEX)); pDevice->SetTexture(0, NULL); } } pDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); 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); Objects objs; result = initD3D(); if(result == 0){ goto fin; } result = initRender(); if(result == 0){ goto fin; } objs.init(); objs.startParticles(0); objs.startParticles(1); objs.startParticles(2); objs.startParticles(3); msg.wParam = 0; while(1){ waittime = GetTickCount(); if(bActive){ static int count = 0; objs.move(); if(count % 50 == 0){ objs.startParticles(0); } else if(count % 57 == 0){ objs.startParticles(1); } else if(count % 66 == 0){ objs.startParticles(2); } else if(count % 71 == 0){ objs.startParticles(3); } count++; if(!drawIdle(objs)){ 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: objs.deinit(); deinitD3d(); return msg.wParam; }