DirectX并不是一個單純的圖形API,它是由微軟公司開發的用途廣泛的API,它包含有Direct Graphics(Direct 3D+Direct Draw)、Direct Input、Direct Play、Direct Sound、Direct Show、Direct Setup、Direct Media Objects等多個元件,它提供了一整套的多媒體接口方案。
DirectX是一系列的COM對象或接口,Direct 3D隻是DirectX的一個部分,Direct3D是一個相當進階的類,它封裝了你運作2D和3D圖形所需要的全部硬體啊,軟體啊,以及其他。
COM
COM對象實際就是C++類,或者說是供你調用以實作一定目标的類内的函數。每個類都可以單獨而不是互相間配合才能進行工作,而且可以作為一個單獨元件解除安裝或加載而不影響程式的運作。獨立性是COM的最大特性之一。
COM的特點,讓DirectX 獨立于語言而向下相容。
一般将COM對象作為接口,将其視為C++類使用,我們所必須知道的僅是通過某個特定函數或另一個COM接口來擷取指向某一個COM接口的指針。通常使用CreateX()函數。獲得指針後就可以該接口的功能(接口内的方法)。
注意到建立COM接口不可使用C++的關鍵字new,而是特定的函數,同時使用完一個接口,應該地調用接口對應的Release方法而不是delete。
這是因為每一個對象都有其的應用計數(Reference Counter),當建立對象時,為該計數初始為1,當使用該對象時進行AddRef(),遞增計數,每次試圖删除進行Release(),隻有當引用計數為0,表明該對象正式删除,進行delete操作。
這樣保證了當我們進行一次Create操作時,我們獲得的是該對象指針,至于該指針是在哪裡new出來的我們不在需要關注,而隻需要Release,就能使該對象準确的時機被delete:
LPDIRECT3D9 d3d;
d3d = Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface
d3d->Release(); // close and release Direct3D
在D3D學習的過程我們需要的NEED:
- Visual Studio 2010 以及以上版本
- The DirectX SDK June 2010
- C++基礎知識
- 開發遊戲的強烈熱情
WIN32基礎
遊戲基本流程
1 Initialize the program:初始化程式如建立視窗,初始化Direct3D
2 Start the game:啟動遊戲
3 Get input from the player:擷取輸入,是遊戲與玩家的互動部分
4 Run the game logic, such as physics and AI:運作遊戲實體引擎、邏輯AI等
5 Render graphics:渲染圖形
6 Loop:進入遊戲循環
7 Cleanup:資源的釋放
WIN32視窗程式
1 注冊視窗類 RegisterClassEx
2 建立視窗 CreateWindowEx
3 顯示視窗 ShowWindow
4 消息循環 Loop GetMessage
以下為完整的WIN32視窗程式代碼
// include the basic windows header file
#include <windows.h>
// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam);
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// the handle for the window, filled by a function
HWND hWnd;
// this struct holds information for the window class
WNDCLASSEX wc;
// clear out the window class for use
ZeroMemory(&wc, sizeof(WNDCLASSEX));
// fill in the struct with the needed information
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = L"WindowClass";
// register the window class
RegisterClassEx(&wc);
// create the window and use the result as the handle
hWnd = CreateWindowEx(NULL,
L"WindowClass", // name of the window class
L"First Window", // title of the window
WS_OVERLAPPEDWINDOW, // window style
300, // x-position of the window
300, // y-position of the window
500, // width of the window
400, // height of the window
NULL, // we have no parent window, NULL
NULL, // we aren't using menus, NULL
hInstance, // application handle
NULL); // used with multiple windows, NULL
// display the window on the screen
ShowWindow(hWnd, nCmdShow);
// enter the main loop:
// this struct holds Windows event messages
MSG msg;
// wait for the next message in the queue, store the result in 'msg'
while(GetMessage(&msg, NULL, 0, 0))
{
// translate keystroke messages into the right format
TranslateMessage(&msg);
// send the message to the WindowProc function
DispatchMessage(&msg);
}
// return this part of the WM_QUIT message to Windows
return msg.wParam;
}
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// sort through and find what code to run for the message given
switch(message)
{
// this message is read when the window is closed
case WM_DESTROY:
{
// close the application entirely
PostQuitMessage(0);
return 0;
} break;
}
// Handle any messages the switch statement didn't
return DefWindowProc (hWnd, message, wParam, lParam);
}
遊戲循環消息處理函數PeekMessage與GetMessage的差別之處:它不在等待消息,相當于對視窗消息隊列消息進行檢查而已,是以我們必須另外處理循環的退出情況。
while(TRUE)
{
// Check to see if any messages are waiting in the queue
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// translate keystroke messages into the right format
TranslateMessage(&msg);
// send the message to the WindowProc function
DispatchMessage(&msg);
}
// If the message is WM_QUIT, exit the while loop
if(msg.message == WM_QUIT)
break;
// Run game code here
// ...
// ...
}
Direct3D程式
- 建立全局變量與函數原型
- 寫初始化Direct3D函數,建立Direct3D Device
- 寫渲染函數
- 關閉與釋放Direct3D資源的函數
1 建立全局變量與函數原型
#include <windows.h>
#include <d3d9.h>
// include the Direct3D Library file
#pragma comment (lib, "d3d9.lib")
// global declarations
LPDIRECT3D9 d3d; // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
// function prototypes
void initD3D(HWND hWnd); // sets up and initializes Direct3D
void render_frame(void); // renders a single frame
void cleanD3D(void); // closes Direct3D and releases memory
// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
2 寫初始化Direct3D函數,建立Direct3D Device
初始化Direct3D的步驟:
- 擷取IDirect3D9指針(Direct3DCreate9)
- 檢查裝置性能(D3DCAPS9 -Device Capabilities)
- 填充D3DPRESENT_PARAMETERS結構,該結構用于指定建立IDirect3DDevice9對象的特性
- 建立IDirect3DDevice9對象,其代表了我們顯示圖像的實體裝置
// this function initializes and prepares Direct3D for use
void initD3D(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface
D3DPRESENT_PARAMETERS d3dpp; // create a struct to hold various device information
ZeroMemory(&d3dpp, sizeof(d3dpp)); // clear out the struct for use
d3dpp.Windowed = TRUE; // program windowed, not fullscreen
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames
d3dpp.hDeviceWindow = hWnd; // set the window to be used by Direct3D
// create a device class using this information and information from the d3dpp stuct
d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);
}
3 寫渲染函數
// this is the function used to render a single frame
void render_frame(void)
{
// clear the window to a deep blue
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);
d3ddev->BeginScene(); // begins the 3D scene
// do 3D rendering on the back buffer here
d3ddev->EndScene(); // ends the 3D scene
d3ddev->Present(NULL, NULL, NULL, NULL); // displays the created frame
}
4 關閉與釋放Direct3D資源的函數
// this is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
d3ddev->Release(); // close and release the 3D device
d3d->Release(); // close and release Direct3D
}
REL
網絡教程:
DirectXTutorial.com
書籍:
《DIRECTX 9.0 3D 遊戲開發程式設計基礎》 Frank D.Luna 清華大學出版社
《Windows程式設計第五版》