首先 Direct3DCreate9 创建IDirect3D9 对象,这个方法是对Com 创建对象封装,封装套间初始化,类厂创建,IDirect3D9 对象创建为一体。所以使用了这个API,那么就直接Ok。
然后在创建LPDIRECT3DDEVICE9 对象,IDirect3D9 的CreateDevice来创建。
有了这个对象之后,就可以画图了,当然必须在g_pD3DDevice->BeginScene(); 和 g_pD3DDevice->EndScene(); 之间,因为这样相当于Gdi中的BeginPaitDC ,就是准备,同样,EndScene 表示画完毕了,
最后,将画好的图片贴出去g_pD3DDevice->Present(NULL, NULL, NULL, NULL);
1. 我们看看如何获得IDirect3D9 对象和设备对象
HRESULT Init3D(HWND hWnd) { if ( NULL == g_pD3D ) { g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); } if (NULL == g_pD3D ) { return E_FAIL; } D3DDISPLAYMODE d3ddm; FillMemory(&d3ddm, sizeof(D3DDISPLAYMODE), 0); if (FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) { return E_FAIL; } D3DPRESENT_PARAMETERS d3dpm; FillMemory(&d3dpm, sizeof(D3DPRESENT_PARAMETERS), 0); d3dpm.Windowed = TRUE; d3dpm.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpm.BackBufferFormat = d3ddm.Format; if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpm, &g_pD3DDevice))) { return E_FAIL; } if ( NULL == g_pD3DDevice ) { return E_FAIL; } return S_OK; }
void Render() { #define D3DFVF_MYVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 128, 0), 1.0f, 0); g_pD3DDevice->BeginScene(); // draw here g_pD3DDevice->SetStreamSource(0, g_pD3DVBuffer, 0, sizeof(DrawVertex)); g_pD3DDevice->SetFVF(D3DFVF_MYVERTEX); g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); g_pD3DDevice->EndScene(); g_pD3DDevice->Present(NULL, NULL, NULL, NULL); }
// direct3d1.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "direct3d1.h" #include <d3d9.h> //#include <D3dx9core.h> //#include <d3d10.h> #pragma comment(lib, "D3D9.lib") //#pragma comment(lib,"D3dx9.lib") #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pD3DDevice = NULL; IDirect3DVertexBuffer9* g_pD3DVBuffer = NULL; // Forward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); HRESULT Init3D(HWND hWnd); void Render( void ); void Term3D( void ); INT DoMSGLoop( void ); HRESULT InitVertexBuffer(); int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here. //MSG msg; HACCEL hAccelTable; INT ExitCode = 0; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_DIRECT3D1, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DIRECT3D1)); // Main message loop: // while (GetMessage(&msg, NULL, 0, 0)) // { // if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) // { // TranslateMessage(&msg); // DispatchMessage(&msg); // } // } ExitCode = DoMSGLoop(); Term3D(); return ExitCode; } // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // // COMMENTS: // // This function and its usage are only necessary if you want this code // to be compatible with Win32 systems prior to the 'RegisterClassEx' // function that was added to Windows 95. It is important to call this function // so that the application will get 'well formed' small icons associated // with it. // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DIRECT3D1)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_DIRECT3D1); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } // // FUNCTION: InitInstance(HINSTANCE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } if (FAILED(Init3D(hWnd))) { DestroyWindow(hWnd); return FALSE; } InitVertexBuffer(); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) // // PURPOSE: Processes messages for the main window. // // WM_COMMAND - process the application menu // WM_PAINT - Paint the main window // WM_DESTROY - post a quit message and return // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; // case WM_PAINT: // hdc = BeginPaint(hWnd, &ps); // // TODO: Add any drawing code here... // EndPaint(hWnd, &ps); // break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // Message handler for about box. INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; } HRESULT Init3D(HWND hWnd) { if ( NULL == g_pD3D ) { g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); } if (NULL == g_pD3D ) { return E_FAIL; } D3DDISPLAYMODE d3ddm; FillMemory(&d3ddm, sizeof(D3DDISPLAYMODE), 0); if (FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) { return E_FAIL; } D3DPRESENT_PARAMETERS d3dpm; FillMemory(&d3dpm, sizeof(D3DPRESENT_PARAMETERS), 0); d3dpm.Windowed = TRUE; d3dpm.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpm.BackBufferFormat = d3ddm.Format; if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpm, &g_pD3DDevice))) { return E_FAIL; } if ( NULL == g_pD3DDevice ) { return E_FAIL; } return S_OK; } INT DoMSGLoop() { BOOL bMsg = FALSE; MSG msg; PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); while (msg.message != WM_QUIT) { bMsg = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); if (bMsg) { TranslateMessage(&msg); DispatchMessage(&msg); } else { Render(); } } return (INT)msg.wParam; } struct DrawVertex { FLOAT x, y, z, rhw; DWORD colour; }; void Render() { #define D3DFVF_MYVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 128, 0), 1.0f, 0); g_pD3DDevice->BeginScene(); // draw here g_pD3DDevice->SetStreamSource(0, g_pD3DVBuffer, 0, sizeof(DrawVertex)); g_pD3DDevice->SetFVF(D3DFVF_MYVERTEX); g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); g_pD3DDevice->EndScene(); g_pD3DDevice->Present(NULL, NULL, NULL, NULL); } void Term3D() { if (g_pD3DDevice != NULL) { g_pD3DDevice->Release(); g_pD3DDevice = NULL; } if (g_pD3D != NULL) { g_pD3D->Release(); g_pD3D = NULL; } } HRESULT InitVertexBuffer() { #define D3DFVF_MYVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) LPVOID pV = NULL; DrawVertex aVertex[] = { {450.0f, 100.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 255) }, {600.0f, 300.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0) }, {300.0f, 300.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0) } }; UINT nSize = 3 * sizeof(DrawVertex); if(FAILED(g_pD3DDevice->CreateVertexBuffer(nSize, D3DUSAGE_SOFTWAREPROCESSING, D3DFVF_MYVERTEX, D3DPOOL_DEFAULT, &g_pD3DVBuffer, NULL))) { return E_FAIL; } if(FAILED(g_pD3DVBuffer->Lock(0, nSize, &pV, 0))) { return E_FAIL; } MoveMemory(pV, aVertex, nSize); g_pD3DVBuffer->Unlock(); return S_OK; }
效果图如下: