안녕하세요 ^^ 엔젤루스입니다.
이번에는 Direct X를 시작해보려고 합니다.
그러고 보니 참 이것 저것 많이 한다는 생각이 들기도 하네요 ㅎ
하지만 워낙 프로그래밍이 좋은 사람이라 약간의 이해를 ^^
Direct X를 이용하게 되면 우리는 그래픽 카드를 사용할 수 있게 됩니다. 그래서 더 빠르게 멋진 영상이나 그래픽 요소를
출력할 수 있게 되는 거죠. 그럼 첫 시작인 장치의 생성에 대해서 알아 보도록 하겠습니다.
장치를 생성한다는 것은 Direct X를 사용할 수 있도록 Direct3D 개체를 생성한다는 이야기 입니다.
그럼 이녀석을 생성하는 방법에 대해서 알아볼까요...
INT WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, INT)
{
//윈도우 클래스의 등록
WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L"D3D Tutorial", NULL};
RegisterClassEx(&wc);
//윈도우 어플리케이션의 생성
HWND hWnd = CreateWindow(L"D3D Tutorial", L"D3D Tutorial 01: CreateDevice", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, wc.hInstance, NULL);
if(SUCCEEDED(InitD3D(hWnd)))
{
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
UnregisterClass(L"D3D Tutorial", wc.hInstance); //클래스 해제
return 0;
}
우리는 이렇게 main 소스를 만듭니다. 처음에 클래스를 등록하고 어플리케이션을 생성하게 됩니다.
그리고 direct3D개체를 생성 하게 되죠 InitD3D 함수에서 말이죠.
//어플리케이션의 정의
HRESULT InitD3D(HWND hWnd)
{
if(NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
return E_FAIL;
D3DPRESENT_PARAMETERS d3dpp; //3D어플리케이션의 동작을 지정
ZeroMemory(&d3dpp,sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
//3D 장치를 생성..
if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice)))
{
return E_FAIL;
}
return S_OK;
}
Direct3DCreate9에 파라미터는 D3D_SDK_VERSION 뿐인데 이녀석을 통해서 사용하는 올바른 헤더 파일이 Direct3D에 통지되게 됩니다.
그리고 나면 Scene의 렌더링을 할 수 있게 됩니다. 이때 메시지가 처리되게 됩니다.
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
Cleanup();
PostQuitMessage(0);
return 0;
case WM_PAINT:
Render();
ValidateRect(hWnd, NULL);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
메시지 루프가 실행이 되고 WM_PAINT가 호출될때 어플리케이션은 윈도우를 재드로잉하는 정의 함수 Render함수를 호출하고 ValidateRect함수를 호출해 클라이언트 영역 전체를 검증한다.
VOID Render()
{
if(NULL == g_pd3dDevice)
return;
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0); //scene를 클리어함..
if(SUCCEEDED(g_pd3dDevice->BeginScene())) //렌더링의 시작
{
g_pd3dDevice->EndScene(); //렌더링의 종료
}
g_pd3dDevice->Present(NULL, NULL, NULL, NULL); //장면 렌더링시 장면을 표시해줌.
}
메시지 처리에서 불려진 Render 함수는 백 버퍼에 청색에 클리어해, 백 버퍼의 내용을 프론트 버터에 전송하고 프론트 버퍼를 화면에 표시하게 됩니다.
Clear함수의 최초 2개의 인수는 Direct3D에 클리어 하는 직사각형의 배열의 사이즈와 주소를 통지합니다. 보통은 렌더링 타겟 전체를 가리는 1개의 직사각형을 사용하는데 이때 최초 0, 두번째 NULL로 설정합니다. 3번째 인수는 메서드의 동작을 결정합니다. 보통 렌더링 타겟 표면, 관련 깊이 버퍼, 스텐실 버퍼의 편성을 클리어 할 수가 있죠. 뭐 현재 자세히 설명은 하지 않겠습니다.(사실 제가 완벽히 공부를 하지 못했죠 ㅜ_ㅜ)
그리고 렌더링을 시작, 보여주고 끝으로 나뉘게 됩니다~
그리고 이 모든게 끝나게 되면 어플리케이션을 종료할 뿐만 아니라 DirectX개체도 해제해 시켜 줘야 합니다.
VOID Cleanup()
{
if(g_pd3dDevice != NULL)
g_pd3dDevice->Release();
if(g_pD3D != NULL)
g_pD3D->Release();
}
그래서 위 코드가 필요하게 되는 것입니다. 장치의 해제를 시켜주고 개체 해제시켜주는 부분입니다.
#include <d3d9.h>
HRESULT InitD3D(HWND);
LRESULT WINAPI MsgProc(HWND, UINT, WPARAM, LPARAM);
VOID Render();
VOID Cleanup();
LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
INT WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, INT)
{
//윈도우 클래스의 등록
WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L"D3D Tutorial", NULL};
RegisterClassEx(&wc);
//윈도우 어플리케이션의 생성
HWND hWnd = CreateWindow(L"D3D Tutorial", L"D3D Tutorial 01: CreateDevice", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, wc.hInstance, NULL);
if(SUCCEEDED(InitD3D(hWnd)))
{
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
UnregisterClass(L"D3D Tutorial", wc.hInstance); //클래스 해제
return 0;
}
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
Cleanup();
PostQuitMessage(0);
return 0;
case WM_PAINT:
Render();
ValidateRect(hWnd, NULL);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
//어플리케이션의 정의
HRESULT InitD3D(HWND hWnd)
{
if(NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
return E_FAIL;
D3DPRESENT_PARAMETERS d3dpp; //3D어플리케이션의 동작을 지정
ZeroMemory(&d3dpp,sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
//3D 장치를 생성..
if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice)))
{
return E_FAIL;
}
return S_OK;
}
VOID Cleanup()
{
if(g_pd3dDevice != NULL)
g_pd3dDevice->Release();
if(g_pD3D != NULL)
g_pD3D->Release();
}
VOID Render()
{
if(NULL == g_pd3dDevice)
return;
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0); //scene를 클리어함..
if(SUCCEEDED(g_pd3dDevice->BeginScene())) //렌더링의 시작
{
g_pd3dDevice->EndScene(); //렌더링의 종료
}
g_pd3dDevice->Present(NULL, NULL, NULL, NULL); //장면 렌더링시 장면을 표시해줌.
}
전체 코드를 보면 다음과 같습니다~, 출력 화면은 다음과 같죠
처음부분이지만 또 어렵게 느껴지네요. 공부했던 부분이 아닌지라 많이 어렵게 느껴지지만...그래도 정복 못하진 않겠죠
앞으로 더 열심히해서 멋진 게임을 만들 수 있으면 좋겠네요
감사합니다~
앞으로 더 열심히 하는 엔젤루스가 되겠습니다 ^ㅡ^