[toc]

C++使用Direct3D画点线面

1.点

1
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
#include<d3d9.h>

#pragma comment(lib, "d3d9.lib")

#define WINDOW_CLASS L"UGPDX"
#define WINDOW_NAME L"Drawing Points"

// Function Prototypes...
BOOL InitializeD3D(HWND hWnd, BOOL fullscreen);
BOOL InitializeObjects();
void RenderScene();
void Shutdown();

// Direct3D object and device.
LPDIRECT3D9 g_D3D = NULL;
LPDIRECT3DDEVICE9 g_D3DDevice = NULL;

// Vertex buffer to hold the geometry.
LPDIRECT3DVERTEXBUFFER9 g_VertexBuffer = NULL;

// A structure for our custom vertex type
typedef struct
{
float x, y, z, rhw;
unsigned long color;
} stD3DVertex;

// Our custom FVF, which describes our custom vertex structure.
#define D3DFVF_VERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)

LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// 清除窗口背景
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
// 调用绘制点的函数
EndPaint(hWnd, &ps);
} break;
case WM_KEYUP:
if (wp == VK_ESCAPE) PostQuitMessage(0);
break;
}

return DefWindowProc(hWnd, msg, wp, lp);
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE prevhInst,
LPSTR cmdLine, int show)
{
// Register the window class
WNDCLASSEXW wc = { sizeof(WNDCLASSEXW), CS_CLASSDC, MsgProc,
0, 0, GetModuleHandle(NULL), NULL, LoadCursor(NULL,IDC_ARROW),
NULL, NULL, WINDOW_CLASS, NULL };
RegisterClassEx(&wc);

// Create the application's window
HWND hWnd = CreateWindowW(WINDOW_CLASS, WINDOW_NAME,
WS_OVERLAPPEDWINDOW, 100, 100,
640, 480, GetDesktopWindow(), NULL,
wc.hInstance, NULL);

// Initialize Direct3D
if (InitializeD3D(hWnd, FALSE))
{
// Show the window
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);

// Enter the message loop
MSG msg;
ZeroMemory(&msg, sizeof(msg));

while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
RenderScene();
}
}

// Release any and all resources.
Shutdown();

// Unregister our window.
UnregisterClass(WINDOW_CLASS, wc.hInstance);
return 0;
}

BOOL InitializeD3D(HWND hWnd, BOOL fullscreen)
{
D3DDISPLAYMODE displayMode;

// Create the D3D object.
g_D3D = Direct3DCreate9(D3D_SDK_VERSION);
if (g_D3D == NULL) return FALSE;

// Get the desktop display mode.
if (FAILED(IDirect3D9_GetAdapterDisplayMode(g_D3D, D3DADAPTER_DEFAULT,
&displayMode))) return FALSE;

// Set up the structure used to create the D3DDevice
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));

if (fullscreen)
{
d3dpp.Windowed = FALSE;
d3dpp.BackBufferWidth = 640;
d3dpp.BackBufferHeight = 480;
}
else
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = displayMode.Format;

// Create the D3DDevice
if (FAILED(IDirect3D9_CreateDevice(g_D3D, D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dpp, &g_D3DDevice))) return FALSE;

// Initialize any objects we will be displaying.
if (!InitializeObjects()) return FALSE;

return TRUE;
}

BOOL InitializeObjects()
{
unsigned long col = D3DCOLOR_XRGB(255, 0, 255);

// Fill in our structure to draw 5 points.
stD3DVertex objData[] =
{
{ 100.0f, 100.0f, 0.5f, 1.0f, col, },
{ 200.0f, 100.0f, 0.5f, 1.0f, col, },
{ 300.0f, 100.0f, 0.5f, 1.0f, col, },
{ 400.0f, 100.0f, 0.5f, 1.0f, col, },
{ 500.0f, 100.0f, 0.5f, 1.0f, col, },
};

// Create the vertex buffer.
if (FAILED(IDirect3DDevice9_CreateVertexBuffer(g_D3DDevice, sizeof(objData), 0,
D3DFVF_VERTEX, D3DPOOL_DEFAULT, &g_VertexBuffer,
NULL))) return FALSE;

// Fill the vertex buffer.
void* ptr;

if (FAILED(IDirect3DVertexBuffer9_Lock(g_VertexBuffer, 0, sizeof(objData),
(void**)&ptr, 0))) return FALSE;

memcpy(ptr, objData, sizeof(objData));

IDirect3DVertexBuffer9_Unlock(g_VertexBuffer);

return TRUE;
}

void RenderScene()
{
// Clear the backbuffer to white.
IDirect3DDevice9_Clear(g_D3DDevice, 0, NULL, D3DCLEAR_TARGET,
D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0); // Change to white

// Begin the scene. Start rendering.
IDirect3DDevice9_BeginScene(g_D3DDevice);

// Render points.
IDirect3DDevice9_SetStreamSource(g_D3DDevice, 0, g_VertexBuffer, 0,
sizeof(stD3DVertex));
IDirect3DDevice9_SetFVF(g_D3DDevice, D3DFVF_VERTEX);
IDirect3DDevice9_DrawPrimitive(g_D3DDevice, D3DPT_POINTLIST, 0, 5); // Draw 5 points

// End the scene. Stop rendering.
IDirect3DDevice9_EndScene(g_D3DDevice);

// Display the scene.
IDirect3DDevice9_Present(g_D3DDevice, NULL, NULL, NULL, NULL);
}

void Shutdown()
{
if (g_D3DDevice != NULL) IDirect3DDevice9_Release(g_D3DDevice);
if (g_D3D != NULL) IDirect3D9_Release(g_D3D);
if (g_VertexBuffer != NULL) IDirect3DVertexBuffer9_Release(g_VertexBuffer);

g_D3DDevice = NULL;
g_D3D = NULL;
g_VertexBuffer = NULL;
}

2.线

1
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
208
209
210
211
212
213
214
215
#include<d3d9.h>

#pragma comment(lib, "d3d9.lib")

#define WINDOW_CLASS L"UGPDX"
#define WINDOW_NAME L"Drawing Lines"

// Function Prototypes...
BOOL InitializeD3D(HWND hWnd, BOOL fullscreen);
BOOL InitializeObjects();
void RenderScene();
void Shutdown();


// Direct3D object and device.
LPDIRECT3D9 g_D3D = NULL;
LPDIRECT3DDEVICE9 g_D3DDevice = NULL;

// Vertex buffer to hold the geometry.
LPDIRECT3DVERTEXBUFFER9 g_VertexBuffer = NULL;


// A structure for our custom vertex type
typedef struct
{
float x, y, z, rhw;
unsigned long color;
}stD3DVertex;

// Our custom FVF, which describes our custom vertex structure.
#define D3DFVF_VERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)


LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// 清除窗口背景
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
// 调用绘制点的函数
EndPaint(hWnd, &ps);
} break;
case WM_KEYUP:
if (wp == VK_ESCAPE) PostQuitMessage(0);
break;
}

return DefWindowProc(hWnd, msg, wp, lp);
}


int WINAPI WinMain(HINSTANCE hInst, HINSTANCE prevhInst,
LPSTR cmdLine, int show)
{
// Register the window class
WNDCLASSEXW wc = { sizeof(WNDCLASSEXW), CS_CLASSDC, MsgProc,
0, 0, GetModuleHandle(NULL), NULL, LoadCursor(NULL,IDC_ARROW),
NULL, NULL, WINDOW_CLASS, NULL };
RegisterClassEx(&wc);

// Create the application's window
HWND hWnd = CreateWindowW(WINDOW_CLASS, WINDOW_NAME,
WS_OVERLAPPEDWINDOW, 100, 100,
640, 480, GetDesktopWindow(), NULL,
wc.hInstance, NULL);

// Initialize Direct3D
if (InitializeD3D(hWnd, FALSE))
{
// Show the window
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);

// Enter the message loop
MSG msg;
ZeroMemory(&msg, sizeof(msg));

while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
RenderScene();
}
}

// Release any and all resources.
Shutdown();

// Unregister our window.
UnregisterClass(WINDOW_CLASS, wc.hInstance);
return 0;
}


BOOL InitializeD3D(HWND hWnd, BOOL fullscreen)
{
D3DDISPLAYMODE displayMode;

// Create the D3D object.
g_D3D = Direct3DCreate9(D3D_SDK_VERSION);
if (g_D3D == NULL) return FALSE;


// Get the desktop display mode.
if (FAILED(IDirect3D9_GetAdapterDisplayMode(g_D3D, D3DADAPTER_DEFAULT,
&displayMode))) return FALSE;


// Set up the structure used to create the D3DDevice
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));


if (fullscreen)
{
d3dpp.Windowed = FALSE;
d3dpp.BackBufferWidth = 640;
d3dpp.BackBufferHeight = 480;
}
else
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = displayMode.Format;


// Create the D3DDevice
if (FAILED(IDirect3D9_CreateDevice(g_D3D, D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dpp, &g_D3DDevice))) return FALSE;


// Initialize any objects we will be displaying.
if (!InitializeObjects()) return FALSE;

return TRUE;
}


BOOL InitializeObjects()
{
unsigned long col = D3DCOLOR_XRGB(255, 0, 255);

// Fill in our structure to draw an object.
// x, y, z, rhw, color.
stD3DVertex objData[] =
{
{ 420.0f, 150.0f, 0.5f, 1.0f, col, },
{ 420.0f, 350.0f, 0.5f, 1.0f, col, },
{ 220.0f, 150.0f, 0.5f, 1.0f, col, },
{ 220.0f, 350.0f, 0.5f, 1.0f, col, },
};

// Create the vertex buffer.
if (FAILED(IDirect3DDevice9_CreateVertexBuffer(g_D3DDevice, sizeof(objData), 0,
D3DFVF_VERTEX, D3DPOOL_DEFAULT, &g_VertexBuffer,
NULL))) return FALSE;

// Fill the vertex buffer.
void* ptr;

if (FAILED(IDirect3DVertexBuffer9_Lock(g_VertexBuffer, 0, sizeof(objData),
(void**)&ptr, 0))) return FALSE;

memcpy(ptr, objData, sizeof(objData));


IDirect3DVertexBuffer9_Unlock(g_VertexBuffer);

return TRUE;
}


void RenderScene()
{
// Clear the backbuffer to white.
IDirect3DDevice9_Clear(g_D3DDevice, 0, NULL, D3DCLEAR_TARGET,
D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0); // Change to white

// Begin the scene. Start rendering.
IDirect3DDevice9_BeginScene(g_D3DDevice);

// Render object.
IDirect3DDevice9_SetStreamSource(g_D3DDevice, 0, g_VertexBuffer, 0,
sizeof(stD3DVertex));
IDirect3DDevice9_SetFVF(g_D3DDevice, D3DFVF_VERTEX);
IDirect3DDevice9_DrawPrimitive(g_D3DDevice, D3DPT_LINELIST, 0, 2);

// End the scene. Stop rendering.
IDirect3DDevice9_EndScene(g_D3DDevice);

// Display the scene.
IDirect3DDevice9_Present(g_D3DDevice, NULL, NULL, NULL, NULL);
}

void Shutdown()
{
if (g_D3DDevice != NULL) IDirect3DDevice9_Release(g_D3DDevice);
if (g_D3D != NULL) IDirect3D9_Release(g_D3D);
if (g_VertexBuffer != NULL) IDirect3DVertexBuffer9_Release(g_VertexBuffer);

g_D3DDevice = NULL;
g_D3D = NULL;
g_VertexBuffer = NULL;
}

3.矩形

1
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
#include <windows.h>
#include <d3d9.h>

#pragma comment(lib, "d3d9.lib")

// 全局变量
IDirect3D9* pD3D = NULL;
IDirect3DDevice9* pDevice = NULL;

// 函数声明
void InitD3D(HWND hwnd);
void Render();
void CleanD3D();
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

// 创建窗口类
void CreateWindowClass(HINSTANCE hInstance, const WCHAR* className) {
WNDCLASSW wc = { 0 };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = className;

RegisterClass(&wc);
}

// 创建窗口
HWND CreateAppWindow(HINSTANCE hInstance, const WCHAR* className, const WCHAR* windowTitle) {
HWND hwnd = CreateWindowExW(
0, className, windowTitle,
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
NULL, NULL, hInstance, NULL
);

ShowWindow(hwnd, SW_SHOW);
return hwnd;
}

// 初始化Direct3D
void InitD3D(HWND hwnd) {
pD3D = Direct3DCreate9(D3D_SDK_VERSION);
if (!pD3D) {
MessageBox(NULL, L"Failed to create Direct3D object", L"Error", MB_OK);
exit(-1);
}

D3DPRESENT_PARAMETERS d3dpp = {};
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.BackBufferWidth = 800;
d3dpp.BackBufferHeight = 600;

if (FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice))) {
MessageBox(NULL, L"Failed to create Direct3D device", L"Error", MB_OK);
exit(-1);
}
}

// 绘制矩形
void Render() {
pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0);

if (SUCCEEDED(pDevice->BeginScene())) {
D3DRECT rect = { 100, 100, 300, 300 };
pDevice->Clear(1, &rect, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
pDevice->EndScene();
}

pDevice->Present(NULL, NULL, NULL, NULL);
}

// 清理Direct3D
void CleanD3D() {
if (pDevice) {
pDevice->Release();
pDevice = NULL;
}
if (pD3D) {
pD3D->Release();
pD3D = NULL;
}
}


// 窗口过程函数
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CREATE:
InitD3D(hwnd);// 创建图形
break;

case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// 清除窗口背景
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
Render();
// 调用绘制点的函数
EndPaint(hwnd, &ps);
} break;

case WM_SIZE:
if (pDevice && wParam != SIZE_MINIMIZED) {
D3DPRESENT_PARAMETERS d3dpp = {};
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.BackBufferWidth = LOWORD(lParam);
d3dpp.BackBufferHeight = HIWORD(lParam);

pDevice->Reset(&d3dpp);
}
break;

case WM_DESTROY:
CleanD3D();
PostQuitMessage(0);
return 0;

default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}

// WinMain 函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
const WCHAR CLASS_NAME[] = L"RectangleWindowClass";
const WCHAR WINDOW_TITLE[] = L"Draw Rectangle";

CreateWindowClass(hInstance, CLASS_NAME);
HWND hwnd = CreateAppWindow(hInstance, CLASS_NAME, WINDOW_TITLE);

MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);

}

return 0;
}