注:1:一般使用多个窗口,都觉得对应一个device比较好做,但是这样一来,texture,vertex....在不同device之间不能共享,造成很大的浪费. 2: SetViewport是个重点.#include "windows.h" #include "d3d9.h" #include "d3dx9.h" #ifdef _DEBUG #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "d3dx9d.lib") #else #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "d3dx9.lib") #endif HINSTANCE g_3DhInst; ATOM g_3DWinClass; HWND g_3DWindow=0; HWND g_3DFocusWindow=0; DWORD g_3DWindowStyleWin; DWORD g_3DWindowStyleFullScreen; DWORD g_3DWindowStyleExWin; DWORD g_3DWindowStyleExFullScreen; D3DPRESENT_PARAMETERS g_d3dpp; LPDIRECT3D9 g_pD3D=0; LPDIRECT3DDEVICE9 g_pDev=0; bool g_bResetDevice = false; char g_strWinClass[] = "QuickDX9"; char g_strWinTitle[] = "TestApp"; LRESULT WINAPI TestWinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (msg==WM_CLOSE) { PostQuitMessage(0); } else if (msg==WM_SIZE) { g_bResetDevice = true; } else if (msg==WM_KEYDOWN && wParam == VK_ESCAPE) { PostQuitMessage(0); } return DefWindowProc(hWnd, msg, wParam, lParam); } bool RegisterWin() { WNDCLASSEX wndclass; memset(&wndclass, 0, sizeof(wndclass)); wndclass.cbSize = sizeof(WNDCLASSEX); wndclass.style = CS_OWNDC; wndclass.lpfnWndProc = TestWinProc; wndclass.hInstance = g_3DhInst; wndclass.lpszClassName = g_strWinClass; g_3DWinClass = RegisterClassEx(&wndclass); return g_3DWinClass != 0; } bool CreateWin() { RECT rc; g_3DWindowStyleFullScreen = g_3DWindowStyleWin = WS_OVERLAPPEDWINDOW | WS_VISIBLE; g_3DWindowStyleExFullScreen = g_3DWindowStyleExWin = WS_EX_OVERLAPPEDWINDOW; rc.left = 0; rc.top = 0; rc.right = 800; rc.bottom = 600; AdjustWindowRectEx(&rc, g_3DWindowStyleWin, false, g_3DWindowStyleExWin); g_3DFocusWindow = CreateWindowEx(g_3DWindowStyleExWin, g_strWinClass, g_strWinTitle, g_3DWindowStyleWin, 0, 0, rc.right - rc.left, rc.bottom - rc.top, 0, 0, g_3DhInst, 0); g_3DWindow = g_3DFocusWindow; return g_3DWindow != 0; } bool MsgPump() { MSG msg; static bool exit = false; if (exit) return false; while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { exit = true; return false; } TranslateMessage(&msg); DispatchMessage(&msg); } return true; } void Cleanup() { if (g_pDev) g_pDev->Release(); if (g_pD3D) g_pD3D->Release(); if (g_3DWindow) DestroyWindow(g_3DWindow); } bool CreateD3D() { g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); return g_pD3D != 0; }
bool CreateDevice() { RECT rc; GetClientRect(g_3DWindow, &rc); memset(&g_d3dpp, 0, sizeof(g_d3dpp)); g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; g_d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; g_d3dpp.EnableAutoDepthStencil = true; g_d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8; g_d3dpp.hDeviceWindow = g_3DWindow; g_d3dpp.BackBufferWidth = rc.right - rc.left; g_d3dpp.BackBufferHeight = rc.bottom - rc.top; g_d3dpp.BackBufferCount = 1; g_d3dpp.Windowed = true; g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE ; if (FAILED(g_pD3D->CreateDevice(0, D3DDEVTYPE_HAL, g_3DFocusWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &g_d3dpp, &g_pDev))) return false; return true; } void TestPreReset(); bool TestPostReset(); bool ResetDevice() { TestPreReset(); if (FAILED(g_pDev->Reset(&g_d3dpp))) return false; return TestPostReset(); } bool TestDevice() { HRESULT hr = g_pDev->TestCooperativeLevel(); if (hr == D3DERR_DEVICENOTRESET || (hr == S_OK && g_bResetDevice)) { g_bResetDevice = false; if (!ResetDevice()) return false; } else if (hr == D3DERR_DEVICELOST) return false; return true; } HWND g_swapwnd = 0; LPDIRECT3DSWAPCHAIN9 g_pSwap = 0; D3DPRESENT_PARAMETERS g_scparam; LPDIRECT3DSURFACE9 g_pSwapDepthSurf = 0; LPDIRECT3DSURFACE9 g_pSwapRenderSurf = 0; LPDIRECT3DSURFACE9 g_pDevDepthSurf = 0; LPDIRECT3DSURFACE9 g_pDevRenderSurf = 0; bool TestSetup() { RECT rc; rc.left = 0; rc.top = 0; rc.right = 400; rc.bottom = 400; AdjustWindowRectEx(&rc, g_3DWindowStyleWin, false, g_3DWindowStyleExWin); g_swapwnd = CreateWindowEx(g_3DWindowStyleExWin, g_strWinClass, "ChainWnd", g_3DWindowStyleWin, 800, 0, rc.right - rc.left, rc.bottom - rc.top, 0, 0, g_3DhInst, 0); return TestPostReset(); } void TestCleanup() { TestPreReset(); if (g_swapwnd) DestroyWindow(g_swapwnd); } void TestPreReset() { if (g_pSwapDepthSurf) g_pSwapDepthSurf->Release(); g_pSwapDepthSurf = 0; if (g_pSwapRenderSurf) g_pSwapRenderSurf->Release(); g_pSwapRenderSurf = 0; if (g_pSwap) g_pSwap->Release(); g_pSwap = 0; if (g_pDevRenderSurf) g_pDevRenderSurf->Release(); g_pDevRenderSurf = 0; if (g_pDevDepthSurf) g_pDevDepthSurf->Release(); g_pDevDepthSurf = 0; } bool TestPostReset() { memset(&g_scparam, 0, sizeof(g_scparam)); g_scparam.BackBufferCount = 1; g_scparam.BackBufferFormat = D3DFMT_X8R8G8B8; g_scparam.BackBufferHeight = 400; g_scparam.BackBufferWidth = 400; g_scparam.hDeviceWindow = g_swapwnd; g_scparam.SwapEffect = D3DSWAPEFFECT_DISCARD; g_scparam.Windowed = true; g_scparam.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; g_pDev->CreateAdditionalSwapChain(&g_scparam, &g_pSwap); g_pSwap->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &g_pSwapRenderSurf); g_pDev->CreateDepthStencilSurface(400,400,D3DFMT_D24X8, D3DMULTISAMPLE_NONE, 0, false, &g_pSwapDepthSurf, 0); g_pDev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &g_pDevRenderSurf); g_pDev->GetDepthStencilSurface(&g_pDevDepthSurf); return true; } class TestVert { public: float x,y,z; DWORD color; }; TestVert g_aoVerts[4]; D3DXMATRIX w,v,p; void TestUpdate() { g_aoVerts[0].x = -1; g_aoVerts[0].y = -1; g_aoVerts[0].z = 0; g_aoVerts[0].color = 0xFFFF0000; g_aoVerts[1].x = -1; g_aoVerts[1].y = 1; g_aoVerts[1].z = 0; g_aoVerts[1].color = 0xFFFFFF00; g_aoVerts[2].x = 1; g_aoVerts[2].y = -1; g_aoVerts[2].z = 0; g_aoVerts[2].color = 0xFFFF00FF; g_aoVerts[3].x = 1; g_aoVerts[3].y = 1; g_aoVerts[3].z = 0; g_aoVerts[3].color = 0xFFFFFFFF; POINT pt; GetCursorPos(&pt); D3DXMatrixRotationYawPitchRoll(&w, (pt.x - 800.0f) / 800 * D3DX_PI / 2, (pt.y - 600.0f) / 600 * D3DX_PI / 2, 0); w._43 = 2; D3DXMatrixPerspectiveFovLH(&p, D3DX_PI/4, 1.0, 0.1f, 500.0f); g_pDev->SetTransform(D3DTS_WORLD, &w); g_pDev->SetTransform(D3DTS_PROJECTION, &p); D3DXMatrixIdentity(&w); g_pDev->SetTransform(D3DTS_VIEW, &w); } void TestRender() { g_pDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); g_pDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE); g_pDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); g_pDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); g_pDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); g_pDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); g_pDev->SetRenderState(D3DRS_LIGHTING, false); g_pDev->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE); g_pDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); g_pDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_aoVerts, sizeof(TestVert)); } int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdLine, int cmdShow) { g_3DhInst = hInst; do { if (!RegisterWin()) break; if (!CreateWin()) break; if (!CreateD3D()) break; if (!CreateDevice()) break; if (!TestSetup()) break; while (MsgPump()) { if (TestDevice()) { D3DVIEWPORT9 vp; vp.X = 0; vp.Y = 0; vp.Width = 800; vp.Height = 600; vp.MinZ = 0; vp.MaxZ = 1; TestUpdate(); g_pDev->SetRenderTarget(0, g_pDevRenderSurf); g_pDev->SetDepthStencilSurface(g_pDevDepthSurf); g_pDev->SetViewport(&vp); g_pDev->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x456789, 1.0f, 0); g_pDev->BeginScene(); TestRender(); g_pDev->EndScene(); g_pDev->resent(0,0,0,0); g_pDev->SetRenderTarget(0, g_pSwapRenderSurf); g_pDev->SetDepthStencilSurface(g_pSwapDepthSurf); vp.Width = 400; vp.Height = 400; g_pDev->SetViewport(&vp); g_pDev->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x654321, 1.0f, 0); g_pDev->BeginScene(); TestRender(); g_pDev->EndScene(); g_pSwap->resent(0, 0, 0, 0, 0); } }; } while (0); TestCleanup(); Cleanup(); return 0; } |