這里要討論的是,DXUT中的一般框架。以前看了很多資料了,講得十分詳細。不過我在這里就把一些簡單的東西總結一下,比如DXUT的工作機制以及模式。對只想了解一下并且快速上手使用的人應該很有幫助。
下面要說的只是我自己自學以及領悟到的內容而已,難免有疏漏和錯誤,希望讀者可以幫我指出。
DXUT,就是DirectX SDK中附帶的一個功能齊全的Direct3D底層框架,有各種語言版本,但其實構架都差不多。這里以C++的為標準,SDK版本為June 2008。
先把DirectX SDK里的EmptyProject安裝了,打開工程。
簡單了解的話,只用來看一下這個DXUT.h,我再稍微說一下就應該大概明白了。
不要被代碼嚇住!!!往后看吧。這個代碼是拿來對照講的。
1
//--------------------------------------------------------------------------------------
2
// File: DXUT.h
3
//
4
// Copyright (c) Microsoft Corporation. All rights reserved.
5
//--------------------------------------------------------------------------------------
6
#pragma once
7
#ifndef DXUT_H
8
#define DXUT_H
9
10
#ifndef UNICODE
11
#error "DXUT requires a Unicode build. See the nearby comments for details"
12
//
13
// If you are using Microsoft Visual C++ .NET, under the General tab of the project
14
// properties change the Character Set to 'Use Unicode Character Set'.
15
//
16
// Windows XP and later are native Unicode so Unicode applications will perform better.
17
// For Windows 98 and Windows Me support, consider using the Microsoft Layer for Unicode (MSLU).
18
//
19
// To use MSLU, link against a set of libraries similar to this
20
// /nod:kernel32.lib /nod:advapi32.lib /nod:user32.lib /nod:gdi32.lib /nod:shell32.lib /nod:comdlg32.lib /nod:version.lib /nod:mpr.lib /nod:rasapi32.lib /nod:winmm.lib /nod:winspool.lib /nod:vfw32.lib /nod:secur32.lib /nod:oleacc.lib /nod:oledlg.lib /nod:sensapi.lib UnicoWS.lib kernel32.lib advapi32.lib user32.lib gdi32.lib shell32.lib comdlg32.lib version.lib mpr.lib rasapi32.lib winmm.lib winspool.lib vfw32.lib secur32.lib oleacc.lib oledlg.lib sensapi.lib dxerr.lib dxguid.lib d3dx9d.lib d3d9.lib comctl32.lib dsound.lib
21
// and put the unicows.dll (available for download from msdn.microsoft.com) in the exe's folder.
22
//
23
// For more details see the MSDN article titled:
24
// "MSLU: Develop Unicode Applications for Windows 9x Platforms with the Microsoft Layer for Unicode"
25
// at http://msdn.microsoft.com/msdnmag/issues/01/10/MSLU/default.aspx
26
//
27
#endif
28
29
//--------------------------------------------------------------------------------------
30
// Structs
31
//--------------------------------------------------------------------------------------
32
class CD3DEnumeration;
33
34
struct DXUTDeviceSettings
35

{
36
UINT AdapterOrdinal;
37
D3DDEVTYPE DeviceType;
38
D3DFORMAT AdapterFormat;
39
DWORD BehaviorFlags;
40
D3DPRESENT_PARAMETERS pp;
41
};
42
43
44
//--------------------------------------------------------------------------------------
45
// Error codes
46
//--------------------------------------------------------------------------------------
47
#define DXUTERR_NODIRECT3D MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0901)
48
#define DXUTERR_NOCOMPATIBLEDEVICES MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0902)
49
#define DXUTERR_MEDIANOTFOUND MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0903)
50
#define DXUTERR_NONZEROREFCOUNT MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0904)
51
#define DXUTERR_CREATINGDEVICE MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0905)
52
#define DXUTERR_RESETTINGDEVICE MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0906)
53
#define DXUTERR_CREATINGDEVICEOBJECTS MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0907)
54
#define DXUTERR_RESETTINGDEVICEOBJECTS MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0908)
55
#define DXUTERR_INCORRECTVERSION MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0909)
56
57
58
//--------------------------------------------------------------------------------------
59
// Callback registration
60
//--------------------------------------------------------------------------------------
61
typedef bool (CALLBACK *LPDXUTCALLBACKISDEVICEACCEPTABLE)( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext );
62
typedef bool (CALLBACK *LPDXUTCALLBACKMODIFYDEVICESETTINGS)( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps, void* pUserContext );
63
typedef HRESULT (CALLBACK *LPDXUTCALLBACKDEVICECREATED)( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext );
64
typedef HRESULT (CALLBACK *LPDXUTCALLBACKDEVICERESET)( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext );
65
typedef void (CALLBACK *LPDXUTCALLBACKDEVICEDESTROYED)( void* pUserContext );
66
typedef void (CALLBACK *LPDXUTCALLBACKDEVICELOST)( void* pUserContext );
67
typedef void (CALLBACK *LPDXUTCALLBACKFRAMEMOVE)( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext );
68
typedef void (CALLBACK *LPDXUTCALLBACKFRAMERENDER)( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext );
69
typedef void (CALLBACK *LPDXUTCALLBACKKEYBOARD)( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext );
70
typedef void (CALLBACK *LPDXUTCALLBACKMOUSE)( bool bLeftButtonDown, bool bRightButtonDown, bool bMiddleButtonDown, bool bSideButton1Down, bool bSideButton2Down, int nMouseWheelDelta, int xPos, int yPos, void* pUserContext );
71
typedef LRESULT (CALLBACK *LPDXUTCALLBACKMSGPROC)( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext );
72
typedef void (CALLBACK *LPDXUTCALLBACKTIMER)( UINT idEvent, void* pUserContext );
73
74
// Device callbacks
75
void DXUTSetCallbackDeviceCreated( LPDXUTCALLBACKDEVICECREATED pCallbackDeviceCreated, void* pUserContext = NULL );
76
void DXUTSetCallbackDeviceReset( LPDXUTCALLBACKDEVICERESET pCallbackDeviceReset, void* pUserContext = NULL );
77
void DXUTSetCallbackDeviceLost( LPDXUTCALLBACKDEVICELOST pCallbackDeviceLost, void* pUserContext = NULL );
78
void DXUTSetCallbackDeviceDestroyed( LPDXUTCALLBACKDEVICEDESTROYED pCallbackDeviceDestroyed, void* pUserContext = NULL );
79
void DXUTSetCallbackDeviceChanging( LPDXUTCALLBACKMODIFYDEVICESETTINGS pCallbackModifyDeviceSettings, void* pUserContext = NULL );
80
81
// Frame callbacks
82
void DXUTSetCallbackFrameMove( LPDXUTCALLBACKFRAMEMOVE pCallbackFrameMove, void* pUserContext = NULL );
83
void DXUTSetCallbackFrameRender( LPDXUTCALLBACKFRAMERENDER pCallbackFrameRender, void* pUserContext = NULL );
84
85
// Message callbacks
86
void DXUTSetCallbackKeyboard( LPDXUTCALLBACKKEYBOARD pCallbackKeyboard, void* pUserContext = NULL );
87
void DXUTSetCallbackMouse( LPDXUTCALLBACKMOUSE pCallbackMouse, bool bIncludeMouseMove = false, void* pUserContext = NULL );
88
void DXUTSetCallbackMsgProc( LPDXUTCALLBACKMSGPROC pCallbackMsgProc, void* pUserContext = NULL );
89
90
91
//--------------------------------------------------------------------------------------
92
// Initialization
93
//--------------------------------------------------------------------------------------
94
HRESULT DXUTInit( bool bParseCommandLine = true, bool bHandleDefaultHotkeys = true, bool bShowMsgBoxOnError = true, bool bHandleAltEnter = true );
95
96
// Choose either DXUTCreateWindow or DXUTSetWindow. If using DXUTSetWindow, consider using DXUTStaticWndProc
97
HRESULT DXUTCreateWindow( const WCHAR* strWindowTitle = L"Direct3D Window",
98
HINSTANCE hInstance = NULL, HICON hIcon = NULL, HMENU hMenu = NULL,
99
int x = CW_USEDEFAULT, int y = CW_USEDEFAULT );
100
HRESULT DXUTSetWindow( HWND hWndFocus, HWND hWndDeviceFullScreen, HWND hWndDeviceWindowed, bool bHandleMessages = true );
101
LRESULT CALLBACK DXUTStaticWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
102
103
// Choose either DXUTCreateDevice or DXUTSetDevice or DXUTCreateDeviceFromSettings
104
HRESULT DXUTCreateDevice( UINT AdapterOrdinal = D3DADAPTER_DEFAULT, bool bWindowed = true,
105
int nSuggestedWidth = 0, int nSuggestedHeight = 0,
106
LPDXUTCALLBACKISDEVICEACCEPTABLE pCallbackIsDeviceAcceptable = NULL,
107
LPDXUTCALLBACKMODIFYDEVICESETTINGS pCallbackModifyDeviceSettings = NULL,
108
void* pUserContext = NULL );
109
HRESULT DXUTCreateDeviceFromSettings( DXUTDeviceSettings* pDeviceSettings, bool bPreserveInput = false, bool bClipWindowToSingleAdapter = true );
110
HRESULT DXUTSetDevice( IDirect3DDevice9* pd3dDevice );
111
112
// Choose either DXUTMainLoop or implement your own main loop
113
HRESULT DXUTMainLoop( HACCEL hAccel = NULL );
114
115
// If not using DXUTMainLoop consider using DXUTRender3DEnvironment
116
void DXUTRender3DEnvironment();
117
118
119
//--------------------------------------------------------------------------------------
120
// Finding valid device settings
121
//--------------------------------------------------------------------------------------
122
enum DXUT_MATCH_TYPE
123

{
124
DXUTMT_IGNORE_INPUT = 0, // Use the closest valid value to a default
125
DXUTMT_PRESERVE_INPUT, // Use input without change, but may cause no valid device to be found
126
DXUTMT_CLOSEST_TO_INPUT // Use the closest valid value to the input
127
};
128
129
struct DXUTMatchOptions
130

{
131
DXUT_MATCH_TYPE eAdapterOrdinal;
132
DXUT_MATCH_TYPE eDeviceType;
133
DXUT_MATCH_TYPE eWindowed;
134
DXUT_MATCH_TYPE eAdapterFormat;
135
DXUT_MATCH_TYPE eVertexProcessing;
136
DXUT_MATCH_TYPE eResolution;
137
DXUT_MATCH_TYPE eBackBufferFormat;
138
DXUT_MATCH_TYPE eBackBufferCount;
139
DXUT_MATCH_TYPE eMultiSample;
140
DXUT_MATCH_TYPE eSwapEffect;
141
DXUT_MATCH_TYPE eDepthFormat;
142
DXUT_MATCH_TYPE eStencilFormat;
143
DXUT_MATCH_TYPE ePresentFlags;
144
DXUT_MATCH_TYPE eRefreshRate;
145
DXUT_MATCH_TYPE ePresentInterval;
146
};
147
148
HRESULT DXUTFindValidDeviceSettings( DXUTDeviceSettings* pOut, DXUTDeviceSettings* pIn = NULL, DXUTMatchOptions* pMatchOptions = NULL );
149
150
151
//--------------------------------------------------------------------------------------
152
// Common Tasks
153
//--------------------------------------------------------------------------------------
154
void DXUTSetCursorSettings( bool bShowCursorWhenFullScreen, bool bClipCursorWhenFullScreen );
155
void DXUTSetMultimonSettings( bool bAutoChangeAdapter );
156
void DXUTSetShortcutKeySettings( bool bAllowWhenFullscreen = false, bool bAllowWhenWindowed = true ); // Controls the Windows key, and accessibility shortcut keys
157
void DXUTSetWindowSettings( bool bCallDefWindowProc = true );
158
void DXUTSetConstantFrameTime( bool bConstantFrameTime, float fTimePerFrame = 0.0163f );
159
HRESULT DXUTSetTimer( LPDXUTCALLBACKTIMER pCallbackTimer, float fTimeoutInSecs = 1.0f, UINT* pnIDEvent = NULL, void* pCallbackUserContext = NULL );
160
HRESULT DXUTKillTimer( UINT nIDEvent );
161
HRESULT DXUTToggleFullScreen();
162
HRESULT DXUTToggleREF();
163
void DXUTPause( bool bPauseTime, bool bPauseRendering );
164
void DXUTResetFrameworkState();
165
void DXUTShutdown( int nExitCode = 0 );
166
167
168
//--------------------------------------------------------------------------------------
169
// State Retrieval
170
//--------------------------------------------------------------------------------------
171
IDirect3D9* DXUTGetD3DObject(); // Does not addref unlike typical Get* APIs
172
IDirect3DDevice9* DXUTGetD3DDevice(); // Does not addref unlike typical Get* APIs
173
DXUTDeviceSettings DXUTGetDeviceSettings();
174
D3DPRESENT_PARAMETERS DXUTGetPresentParameters();
175
const D3DSURFACE_DESC* DXUTGetBackBufferSurfaceDesc();
176
const D3DCAPS9* DXUTGetDeviceCaps();
177
HINSTANCE DXUTGetHINSTANCE();
178
HWND DXUTGetHWND();
179
HWND DXUTGetHWNDFocus();
180
HWND DXUTGetHWNDDeviceFullScreen();
181
HWND DXUTGetHWNDDeviceWindowed();
182
RECT DXUTGetWindowClientRect();
183
RECT DXUTGetWindowClientRectAtModeChange(); // Useful for returning to windowed mode with the same resolution as before toggle to full screen mode
184
RECT DXUTGetFullsceenClientRectAtModeChange(); // Useful for returning to full screen mode with the same resolution as before toggle to windowed mode
185
double DXUTGetTime();
186
float DXUTGetElapsedTime();
187
bool DXUTIsWindowed();
188
float DXUTGetFPS();
189
LPCWSTR DXUTGetWindowTitle();
190
LPCWSTR DXUTGetFrameStats( bool bIncludeFPS = false );
191
LPCWSTR DXUTGetDeviceStats();
192
bool DXUTIsRenderingPaused();
193
bool DXUTIsTimePaused();
194
bool DXUTIsActive();
195
int DXUTGetExitCode();
196
bool DXUTGetShowMsgBoxOnError();
197
bool DXUTGetHandleDefaultHotkeys();
198
bool DXUTIsKeyDown( BYTE vKey ); // Pass a virtual-key code, ex. VK_F1, 'A', VK_RETURN, VK_LSHIFT, etc
199
bool DXUTIsMouseButtonDown( BYTE vButton ); // Pass a virtual-key code: VK_LBUTTON, VK_RBUTTON, VK_MBUTTON, VK_XBUTTON1, VK_XBUTTON2
200
bool DXUTGetAutomation(); // Returns true if -automation parameter is used to launch the app
201
202
#endif
203
204
205
206
207

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35



36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123



124

125

126

127

128

129

130



131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

千萬別被代碼嚇住。對于不需要深入理解的我們來說,大多數都是不需要關心的。如果您需要深入理解的話,我非常抱歉我幫不上忙。在CPPBLOG里面有個標題為“天行健 君子當自強不息”的一個BLOG里面有專門詳細解析DXUT的文章。鏈接請自己百度一下吧。
于是我們來關注一下這個優美的框架。它定義了很多回調函數,以及留了許多接口。
我們需要關心的是這幾個:
DXUTSetCallbackDeviceCreated
為框架掛接上Direct3D設備創建后的回調函數
DXUTSetCallbackDeviceReset
掛接Direct3D設備重置后的回調函數
DXUTSetCallbackDeviceLost
掛接Direct3D設備丟失后的回調函數
DXUTSetCallbackDeviceDestroyed
掛接Direct3D設備銷毀后的回調函數
DXUTSetCallbackFrameRender
掛接每幀渲染場景時的回調函數
DXUTSetCallbackFrameMove
掛接每幀渲染前需要更新場景時的回調函數
DXUTSetCallbackMouse
掛接鼠標事件的回調函數
DXUTSetCallbackKeyboard
掛接鍵盤事件的回調函數
于是我們打開EmptyProject.cpp
看著WinMain函數
1
//--------------------------------------------------------------------------------------
2
// Initialize everything and go into a render loop
3
//--------------------------------------------------------------------------------------
4
INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
5

{
6
7
//設置回調函數
8
DXUTSetCallbackDeviceCreated( OnCreateDevice );
9
DXUTSetCallbackDeviceReset( OnResetDevice );
10
DXUTSetCallbackDeviceLost( OnLostDevice );
11
DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
12
DXUTSetCallbackMsgProc( MsgProc );
13
DXUTSetCallbackFrameRender( OnFrameRender );
14
DXUTSetCallbackFrameMove( OnFrameMove );
15
DXUTSetCallbackMouse( OnMouseEvent ,true);//第二個參數是指是否包含鼠標移動事件
16
DXUTSetCallbackKeyboard( OnKeyEvent );
17
18
// 這里寫在程序底層初始化前需要的代碼
19
20
21
// 初始化DXUT、程序窗口、Direct3D設備
22
DXUTInit( true, false, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
23
DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
24
DXUTCreateWindow( “EmptyProject”);//窗口標題
25
DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );//創建設備
26
// 開始DXUT主循環
27
DXUTMainLoop();
28
29
// 這里寫清理底層的代碼
30
return DXUTGetExitCode();
31
}

2

3

4

5



6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

看見了么,在這里掛接了需要的回調函數,不如我們將他們叫做“事件”,這樣更好理解。
自己看一下就能明白那些代碼的意思了
OnCreateDevice OnResetDevice OnLostDevice OnDestroyDevice MSgProc OnFrameRender OnFrameMove OnMouseEvent OnKetEvent
這些都是已經定義好的CALLBACK,我們的框架將從DXUTMainLoop()這里開始
簡單來說,我們需要了解的就只有這些事件的觸發順序了。
HRESULT CALLBACK OnCreateDevice( Device* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
這個事件在設備創建完畢時就會觸發,最先觸發的東西。第一個參數是創建后的設備,第二個是設備的表面參數。pUserContext不需要關心,因此不討論。下同。
HRESULT CALLBACK OnResetDevice( Device* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
這個事件在設備重置的時候會觸發。那么什么叫做設備重置呢?等下會和設備丟失一起說。第一個參數是重置后的設備,第二個是重置后設備的表面參數。
void CALLBACK OnLostDevice( void* pUserContext )
這個事件在設備丟失的時候會觸發。舉個簡單的例子,把窗口最小化的時候設備會丟失,而恢復的時候設備會重置。從全屏換為窗口的時候也會丟失并且重置。大概就是改變窗口的大小、位置、是否全屏的時候,會導致設備丟失,隨后恢復的時候會重置。這兩個事件的觸發就是為了在窗口改變的時候重新設置一些參數,讓畫面適應當前窗口設置。
void CALLBACK OnFrameMove( Device* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
這個事件在每幀繪制前會觸發,為的是更新場景信息。第一個參數是傳入的Direct3D設備,第二個參數是從第一次觸發這個事件到現在為止的時間,第三個參數是這次觸發此事件距上次的時間。
void CALLBACK OnFrameRender( Device* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
這個事件在每幀渲染屏幕的時候觸發。參數意義和OnFrameMove一樣。
void CALLBACK OnMouseEvent(bool bLeftButtonDown, bool bRightButtonDown, bool bMiddleButtonDown, bool bSideButton1Down,
bool bSideButton2Down, int nMouseWheelDelta, int xPos, int yPos, void* pUserContext)
這個事件在鼠標有動作的時候觸發。bLeftButtonDown:左鍵是否按下,bRighButtonDown:右鍵是否按下,bMiddleButtonDown:中間鍵是否按下,bSidebutton1Down:邊鍵1是否按下,bSideButton2Down:邊鍵2是否按下,nMouseWheelDelta:滾輪的滾動值,向手指指的方向滾動一格是-120,反之則為120,xPos:在窗口中的X坐標,yPos:在窗口中的Y坐標。
void CALLBACK OnKeyEvent( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext )
這個事件在鍵盤有動作的時候觸發。nChar:發生動作的鍵,bKeyDown:發生動作的鍵是被按下還是被抬起,bAltDown:Alt鍵是否同時被按下。
這些了解了后,你就可以開始干事兒了。你可以把上面的回調函數都當做事件來看,而且是多線程的,這樣更方便。
總結一下事件順序:

如上圖所示,DXUT的工作順序大概就是這樣。對于不需要深入了解DXUT工作細節來說,已經差不多了。
現在應該對框架的工作機制有一定得認識了,這篇簡單的文章也就這樣結束了。下一篇還是預告了吧,是在DXUT框架下,關于2D方面的東西。
順便說一些DXUT.h中比較實用的接口
163行:void DXUTPause( bool bPauseTime, bool bPauseRendering ); 讓OnFrameMove和OnFrameRender事件暫停或恢復觸發,第一個參數為是否停止計時,第二個為是否停止繪制。
178行:HWND DXUTGetHWND();獲取目前窗口句柄
182行:RECT DXUTGetWindowClientRect();
188行:float DXUTGetFPS();獲取當前的FPS(Frame Per second 每秒幀數)
差不多就這些。
以上的代碼在EmptyProject里面全部都有,這篇文章只是幫還沒有接觸過的新手入門而已。請勿鄙視,有任何意見和建議請提出,謝謝了。
現在已經傻瓜式地把框架搭建好了,并且可以簡單使用了。那么下一步該干嘛?干事兒唄。
下一篇:Direct3D中的簡單2D運用。有空再寫了,先預告了吧。