[ Dx11 ] Framework 생성(1)
구현
그래픽스 API 중 하나인 DirectX11로 렌더링을 구현한다. DirectX11를 사용하기 위해 프레임 워크 작업이 필요하다.
전체 어플리케이션을 캡슐화하는 SystemClass를 정의
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
main.cpp
//main 함수
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
// System 객체 생성
SystemClass* System = new SystemClass;
if (!System)
{
return -1;
}
// System 객체 초기화 및 실행
if (System->Initialize())
{
System->Run();
}
// System 객체 종료 및 메모리 반환
System->Shutdown();
delete System;
System = nullptr;
return 0;
}
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
SystemClass.h
#pragma once
class InputClass;
class GraphicsClass;
class SystemClass
{
public:
SystemClass();
SystemClass(const SystemClass&);
~SystemClass();
bool Initialize();
void Shutdown();
void Run();
LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM);
private:
bool Frame();
void InitializeWindows(int&, int&);
void ShutdownWindows();
private:
LPCWSTR m_applicationName;
HINSTANCE m_hinstance;
HWND m_hwnd;
InputClass* m_Input = nullptr;
GraphicsClass* m_Graphics = nullptr;
};
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static SystemClass* ApplicationHandle = 0;
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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
SystemClass.cpp
#include "stdafx.h"
#include "inputclass.h"
#include "graphicsclass.h"
#include "systemclass.h"
// 생성자
SystemClass::SystemClass()
{
}
// 복사 생성자
SystemClass::SystemClass(const SystemClass& other)
{
}
// 파괴자
SystemClass::~SystemClass()
{
}
// 초기화
bool SystemClass::Initialize()
{
// 윈도우 창 가로, 세로 넓이 변수 초기화
int screenWidth = 0;
int screenHeight = 0;
// 윈도우 생성 초기화
InitializeWindows(screenWidth, screenHeight);
// m_Input 객체 생성, 키보드 입력 처리에 사용
m_Input = new InputClass;
if (!m_Input)
{
return false;
}
// m_Input 객체 초기화
if (!m_Input->Initialize(m_hinstance, m_hwnd, screenWidth, screenHeight))
{
MessageBox(m_hwnd, L"Could not initialize the input object.", L"Error", MB_OK);
return false;
}
// m_Graphics 객체 생성, 그래픽 랜더링
m_Graphics = new GraphicsClass;
if (!m_Graphics)
{
return false;
}
// m_Graphics 객체 초기화.
if (!m_Graphics->Initialize(screenWidth, screenHeight, m_hwnd))
{
return false;
}
return true;
}
// 객체 정리
void SystemClass::Shutdown()
{
// m_Graphics 객체 반환
if (m_Graphics)
{
m_Graphics->Shutdown();
delete m_Graphics;
m_Graphics = 0;
}
// m_Input 객체 반환
if (m_Input)
{
m_Input->Shutdown();
delete m_Input;
m_Input = 0;
}
// Window 종료 처리
ShutdownWindows();
}
//프로그램이 종료될 때까지 루프를 돌면서 어플리케이션의 모든 작업을 처리
void SystemClass::Run()
{
// 메시지 구조체 생성 및 초기화
MSG msg;
ZeroMemory(&msg, sizeof(MSG));
// 사용자로부터 종료 메시지를 받을때까지 루프
while (true)
{
// 윈도우 메시지를 처리합니다
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// 종료 메시지를 받을 경우 메시지 루프를 탈출합니다
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// 그 외에는 Frame 함수를 처리합니다.
if (!Frame())
{
MessageBox(m_hwnd, L"Frame Processing Failed", L"Error", MB_OK);
break;
}
}
// 사용자가 ESC키를 눌렀는지 확인 후 종료 처리함
if (m_Input->IsEscapePressed())
{
break;
}
}
}
// 어플리케아션의 모든 작업 처리
bool SystemClass::Frame()
{
bool result;
// 유저가 Esc키를 눌러 어플리케이션을 종료하기를 원하는지 확인
if(m_Input->IsKeyDown(VK_ESCAPE)) return false;
// graphics객체의 작업을 처리
result = m_Graphics->Frame();
if(!result) return false;
return true;
}
// 윈도우의 시스템 메세지 전달
LRESULT CALLBACK SystemClass::MessageHandler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
return DefWindowProc(hwnd, umsg, wparam, lparam);
}
// 윈도우 생성
void SystemClass::InitializeWindows(int& screenWidth, int& screenHeight)
{
// 외부 포인터를 이 객체로 지정
ApplicationHandle = this;
// 이 프로그램의 인스턴스 호출
m_hinstance = GetModuleHandle(NULL);
// 프로그램 이름 지정
m_applicationName = L"Dx11Demo_22";
// windows class 설정(기본)
WNDCLASSEX wc;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = m_hinstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hIconSm = wc.hIcon;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = m_applicationName;
wc.cbSize = sizeof(WNDCLASSEX);
// windows class 등록
RegisterClassEx(&wc);
// 해상도 임포트
screenWidth = GetSystemMetrics(SM_CXSCREEN);
screenHeight = GetSystemMetrics(SM_CYSCREEN);
int posX = 0;
int posY = 0;
// FULL_SCREEN 시, 변수 값에 따라 화면을 설정
if (FULL_SCREEN)
{
// 모니터 화면 해상도를 데스크톱 해상도로 지정하고 색상을 32bit로 지정
DEVMODE dmScreenSettings;
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = (unsigned long)screenWidth;
dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight;
dmScreenSettings.dmBitsPerPel = 32;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
// 풀스크린으로 디스플레이 설정 변경
ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
}
else
{
// 윈도우 모드 시, 800 * 600 크기를 지정
screenWidth = 800;
screenHeight = 600;
// 윈도우 창을 가로, 세로의 정 가운데 위치
posX = (GetSystemMetrics(SM_CXSCREEN) - screenWidth) / 2;
posY = (GetSystemMetrics(SM_CYSCREEN) - screenHeight) / 2;
}
// 윈도우를 생성하고 핸들
m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName,
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP,
posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL);
// 윈도우를 화면에 표시하고 포커스를 지정
ShowWindow(m_hwnd, SW_SHOW);
SetForegroundWindow(m_hwnd);
SetFocus(m_hwnd);
}
// 화면 설정을 되돌리고 윈도우와 그 핸들들을 반환
void SystemClass::ShutdownWindows()
{
// 풀스크린 모드였다면 디스플레이 설정을 초기화
if (FULL_SCREEN)
{
ChangeDisplaySettings(NULL, 0);
}
// 창을 제거
DestroyWindow(m_hwnd);
m_hwnd = NULL;
// 프로그램 인스턴스를 제거
UnregisterClass(m_applicationName, m_hinstance);
m_hinstance = NULL;
// 외부포인터 참조를 초기화
ApplicationHandle = NULL;
}
//윈도우시스템 메세지 송신
LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
{
switch (umessage)
{
// 윈도우 종료를 확인
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
// 윈도우가 닫히는지 확인
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}
// 그 외의 모든 메시지들은 시스템 클래스의 메시지 처리로 이동
default:
{
return ApplicationHandle->MessageHandler(hwnd, umessage, wparam, lparam);
}
}
}
사용자 입력을 처리하는 Inputclass 정의
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Inputclass.h
class InputClass
{
public:
InputClass();
InputClass(const InputClass&);
~InputClass();
void Initialize();
void KeyDown(unsigned int);
void KeyUp(unsigned int);
bool IsKeyDown(unsigned int);
private:
bool m_keys[256];
};
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
#include "inputclass.h"
InputClass::InputClass()
{
}
InputClass::InputClass(const InputClass& other)
{
}
InputClass::~InputClass()
{
}
void InputClass::Initialize()
{
// 모든 키 초기화
for(int i=0; i<256; i++)
{
m_keys[i] = false;
}
return;
}
void InputClass::KeyDown(unsigned int input)
{
// KeyDown 시, 배열 저장
m_keys[input] = true;
return;
}
void InputClass::KeyUp(unsigned int input)
{
// KeyUp 시, 배열 저장
m_keys[input] = false;
return;
}
bool InputClass::IsKeyDown(unsigned int key)
{
// KeyDown 상태 확인
return m_keys[key];
}
출처: www.rastertek.com/tutdx11win10.html
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.