반응형
# 아무 기능 없이 윈도우만 띄우는 기능까지만 들어간 라이브러리.
# 헤더파일의 DX관련 헤더와 라이브러리는 참조하기 쉽게 위치를 옮겨놨다.
# 실질적인 기능은 zCore파일에서 정의된다.
stdHeader_L.h
#pragma once #define DIRECTINPUT_VERSION 0x0800 #define _CRT_SECURE_NO_WARNINGS #pragma warning( disable:4005) //매크로 재정의 에러 띄우지 않기. //#define _DISABLE_EXTENDED_ALIGNED_STORAGE //메모리 자동 정렬 사용 안함? #pragma region //헤더 파일 및 라이브러리 파일 추가 #include <Windows.h> #include <wrl.h> //Windows Runtime C++ Template Library //ComPtr사용 #include <tchar.h> #include <time.h> #include <cassert> #include <memory> //스마트 포인터 사용 //stl헤더 #include <set> #include <list> #include <map> #include <vector> #include <algorithm> #include <functional> #include <unordered_map> #include <iterator> //dx (순서 주의) #include "d3dx11.h" #include "D3D11.h" #include "dxgi.h" #include "D3Dcompiler.h" #include "D2D1.h" #include "D2D1Helper.h" #include "DWrite.h" #include "dinput.h" //라이브러리 포함 #pragma comment (lib, "D3D11.lib") #if defined(DEBUG) || defined(_DEBUG) #pragma comment( lib, "d3dx10d.lib" ) #pragma comment( lib, "d3dx11d.lib" ) #else #pragma comment( lib, "d3dx10.lib" ) #pragma comment( lib, "d3dx11.lib" ) #endif #pragma comment (lib, "dxgi.lib") #pragma comment (lib, "D3Dcompiler.lib") #pragma comment (lib, "D2D1.lib") #pragma comment (lib, "DWrite.lib") #pragma comment (lib, "dxguid.lib") #pragma comment (lib, "dinput8.lib") #pragma endregion #pragma region //namespace 사용 using namespace std; using namespace Microsoft::WRL; using namespace D2D1; #pragma endregion namespace Lypi { #pragma region //문자열 타입정의 typedef basic_string<TCHAR> T_STR; typedef basic_string<wchar_t> W_STR; typedef basic_string<char> C_STR; typedef vector<T_STR> T_STR_VECTOR; #pragma endregion #pragma region //매크로 #define str(x) L#x #define randf(x) (((float)x)*rand()/(float)RAND_MAX) //0~x사이의 랜덤한 실수값을 반환 #define randstep(fMin,fMax) (fMin+randf(fMax-fmin)) //min에서 max까지의 랜덤할 실수값을 반환 #define clamp(x,MinX,MaxX) if (x>MaxX) x=MaxX; else if (x<MinX) x=MinX; //x값이 min보다 작으면 min으로, max보다 크면 max로 고정시킴. #define SAFE_NEW(A, B) { if (!A) A = new B; } //A가 널포인트이면 A에 B를 동적할당한다. #define SAFE_DEL(A) { if (A) delete A; (A)=nullptr; } //A가 널포인트가 아니면 A의 메모리를 해제하고, Nullptr로 설정한다. #define SAFE_NEW_ARRAY(A, B, C) { if (!A && C>0) A = new B[C]; } //A가 널포인트가 아니고 C가 1이상이면 A에 B를 C개의 배열로 동적할당한다. #define SAFE_DELETE_ARRAY(A) { if (A) delete[] A; (A)=nullptr; } //A가 널포인트가 아니면 A에 할당된 배열 메모리를 해제하고, nullptr로 설정한다. #define SAFE_RELEASE(A) { if(A) { (A)->Release(); (A)=NULL; } } //A가 널포인터가 아니면 A를 릴리즈하고 nullptr로 설정한다. #define V(x) { hr = (x); } #define V_FRETURN(x) { hr = (x); if( FAILED(hr) ) { return hr; } } //디버그 메시지 출력용 #define DEBUGMSG(lpText)\ {\ TCHAR szBuffer[256];\ _stprintf_s(szBuffer, _T("[File: %s][Line: %d]\n[Note : %s]"), _CRT_WIDE(__FILE__), __LINE__, lpText); \ MessageBox(NULL, szBuffer, _T("ERROR"), MB_ICONERROR);} #if defined(DEBUG) | defined(_DEBUG) #define H_RETURN(x){ if (FAILED(x)){\ LPWSTR output;\ WCHAR buffer[256]={0,};\ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS |FORMAT_MESSAGE_ALLOCATE_BUFFER,\ NULL,x,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR)&output,0,NULL);\ wsprintf(buffer,L"File=%s\nLine=%s", str(__FILE__),str(__LINE__));\ MessageBox(NULL, buffer,output,MB_OK); return hr;}\ } #define H(x){ if (FAILED(x)){\ LPWSTR output;\ WCHAR buffer[256]={0,};\ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS |FORMAT_MESSAGE_ALLOCATE_BUFFER,\ NULL,x,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR)&output,0,NULL);\ wsprintf(buffer,L"File=%s\nLine=%s", str(__FILE__),str(__LINE__));\ MessageBox(NULL, buffer,output,MB_OK);}\ } #else #define H_RETURN(x) (x) #define H(x) (x) #endif #pragma endregion #pragma region //외부변수 정의 class winL; //device_DX extern ID3D11Device* g_pD3dDevice; extern ID3D11DeviceContext* g_pD3dContext; extern IDXGISwapChain* g_pSwapChain; extern ID3D11RenderTargetView* g_pRenderTagetView; extern ID3D11DepthStencilView* g_pDepthStencilView; extern D3D11_VIEWPORT g_d3dViewPort; //WndC_DX extern HINSTANCE g_hInst; //윈도우의 인스턴스 핸들값 extern HWND g_hWnd; //생성된 윈도우의 핸들값 extern RECT g_rtWindow; //윈도우 영역 extern RECT g_rtClient; //클라이언트 영역 (작업영역) extern winL* g_pWindow; //현재 생성된 윈도우에 대한 포인터 extern float g_dSPF; //SPF }
DxDevice.h
#pragma once #include "stdHeader_L.h" namespace Lypi { class DxDevice { protected: ID3D11Device* m_pD3dDevice; // 디바이스 객체 ID3D11DeviceContext* m_pD3dContext; // 디바이스 컨텍스트 객체 IDXGISwapChain* m_pSwapChain; // 스왑체인 객체 D3D_DRIVER_TYPE m_d3dDriverType; // 디바이스 타입 (디폴트 : 하드웨어 가속) D3D_FEATURE_LEVEL m_d3dFeatureLevel; // DX의 기능 수준 IDXGIFactory* m_pGIFactory; // DXGI 객체 ID3D11RenderTargetView* m_pRenderTagetView; // 메인 렌더타켓 뷰 ID3D11DepthStencilView* m_pDepthStencilView; // 깊이 스텐실 뷰 D3D11_VIEWPORT m_d3dViewPort; // 뷰 포트 protected: //디바이스 생성 HRESULT InitDevice(); // 장치를 순서대로 생성한다. HRESULT CreateDevice(); // 디바이스 및 디바이스 컨텍스트를 생성한다. HRESULT CreateGIFactory(); // IDXGIFactory 객체 생성 HRESULT CreateSwapChain(); // IDXGIFactory를 이용하여 스왑체인 생성 HRESULT CreateDpethStencilView(); // 깊이 스텐실 뷰 생성 HRESULT SetRenderTargetView(); // 타겟 뷰 설정 HRESULT SetViewPort(); // 뷰 포트 설정 protected: bool CreanupDevice(); // 생성한 것을 역순으로 삭제한다. public: DxDevice(); virtual ~DxDevice(); }; }
DxDevice.cpp
#include "DxDevice.h" namespace Lypi { ID3D11Device* g_pD3dDevice; // 디바이스 객체 ID3D11DeviceContext* g_pD3dContext; // 디바이스 컨텍스트 IDXGISwapChain* g_pSwapChain; // 스왑체인 객체 ID3D11RenderTargetView* g_pRenderTagetView; // 메인 렌더타켓뷰 정보 얻기 ID3D11DepthStencilView* g_pDepthStencilView; // 깊이 스텐실 정보 얻기 D3D11_VIEWPORT g_d3dViewPort; // 뷰포트 정보 얻기 DxDevice::DxDevice() { //어댑터(그래픽카드)를 사용하여 디바이스 객체를 생성해야 하므로 NULL로 선택. m_d3dDriverType = D3D_DRIVER_TYPE_NULL; //쉐이더5.0을 사용해야 하므로 11을 선택. m_d3dFeatureLevel = D3D_FEATURE_LEVEL_11_0; //선언 후 생성 전 초기화. m_pD3dDevice = nullptr; m_pD3dContext = nullptr; m_pGIFactory = nullptr; m_pSwapChain = nullptr; m_pRenderTagetView = nullptr; m_pDepthStencilView = nullptr; } #pragma region //디바이스 생성 //ID3D11Device 인터페이스를 생성한다. HRESULT DxDevice::CreateDevice() { HRESULT hr; //d2d를 쓰려면 이 플래그를 써야함. UINT uCreateDeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; //디바이스 생성 플래그 #if defined(DEBUG) || defined(_DEBUG) uCreateDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif //디바이스 생성 타입 D3D_DRIVER_TYPE dxDriverTypes[] = { D3D_DRIVER_TYPE_UNKNOWN, //디바이스 객체를 생성할 수 있는 최상의 드라이브 타입이 자동적으로 선택된다는데...? D3D_DRIVER_TYPE_HARDWARE, //최선 D3D_DRIVER_TYPE_WARP, //차선 D3D_DRIVER_TYPE_REFERENCE //최악 (그래픽 카드가 안 받쳐줄때 개발용으로 사용) }; UINT uNumDriverTypes = sizeof(dxDriverTypes) / sizeof(dxDriverTypes[0]); //선택될 수 있는 피처레벨 배열 D3D_FEATURE_LEVEL dxFeatureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, }; UINT uNumFeatureLevels = sizeof(dxFeatureLevels) / sizeof(dxFeatureLevels[0]); //피쳐레벨이 11로 생성될 때까지 돌리기 위한 반복문 for (UINT uDriverTypeIndex = 0; uDriverTypeIndex < uNumDriverTypes; uDriverTypeIndex++) { m_d3dDriverType = dxDriverTypes[uDriverTypeIndex]; hr = D3D11CreateDevice( NULL, //디스플레이 시스템(어댑터) NULL이면 주디스플레이로 자동 선택됨. m_d3dDriverType, //드라이버 타입 지정. NULL, //특정 소프트웨어의 모듈을 사용하는 디바이스를 만들때 사용. uCreateDeviceFlags, //디바이스 생성 플래그 dxFeatureLevels, //선택될 수 있는 피처 레벨이 담겨있는 배열 uNumFeatureLevels, //위의 배열의 원소수 D3D11_SDK_VERSION, //SDK 버전 &m_pD3dDevice, //생성된 디바이스를 반환받을 주소 &m_d3dFeatureLevel, //선택된 피처레벨을 반환받을 주소. &m_pD3dContext); //생성된 DC를 반환받을 주소. //디바이스를 생성하는데 성공하였지만 버전이 11이 아닐 경우 다시 생성하게 한다. if (SUCCEEDED(hr)) { if (FAILED(hr) || m_d3dFeatureLevel < D3D_FEATURE_LEVEL_11_0) { if (m_pD3dContext) { m_pD3dContext->Release(); } if (m_pD3dDevice) { m_pD3dDevice->Release(); } continue; } break; } } if (FAILED(hr)) { return false; } g_pD3dDevice = m_pD3dDevice; g_pD3dContext = m_pD3dContext; return S_OK; } //DXGIFactory 인터페이스를 생성한다. HRESULT DxDevice::CreateGIFactory() { if (m_pD3dDevice == nullptr) { return E_FAIL; } HRESULT hr; IDXGIDevice* pDXGIDevice; IDXGIAdapter* pDXGIAdapter; //생성되어 있는 ID3D11Device로부터 출발해서 IDXGIFactory를 넘겨받는다. hr = m_pD3dDevice->QueryInterface(__uuidof(IDXGIDevice), (LPVOID*)(&pDXGIDevice)); hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (LPVOID*)(&pDXGIAdapter)); hr = pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), (LPVOID*)(&m_pGIFactory)); pDXGIDevice->Release(); pDXGIAdapter->Release(); return hr; } //DXGIFactory 인터페이스로부터 IDXGISwapChain 인터페이스를 생성한다. HRESULT DxDevice::CreateSwapChain() { HRESULT hr = S_OK; if (m_pGIFactory == nullptr) { return S_FALSE; } //스왑체인 구조체를 생성한 뒤 필요한 내용을 채워서 이를 이용해 스왑체인 객체를 생성한다. DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 1; //버퍼 개수 sd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; //버퍼의 색상 포맷 (필수) sd.BufferDesc.RefreshRate.Numerator = 60; //화면 주사율 (분자) sd.BufferDesc.RefreshRate.Denominator = 1; //화면 주사율 (분모) sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; //버퍼 용도 sd.OutputWindow = g_hWnd; //어느 윈도우에 뿌릴지 (필수) sd.Windowed = true; //false 전체화면, true 창모드 sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; //샘플링 수준 sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; //스왑체인 버퍼의 크기. 깊이스텐실뷰와 같은 크기로 생성해야 호환이 된다. //왜냐하면 스왑체인에서 백버퍼를 생성할 것이기 때문. sd.BufferDesc.Width = g_rtClient.right; sd.BufferDesc.Height = g_rtClient.bottom; //화면 크기 변경을 막아놓았기 때문에 //sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; //는 쓰지 않았다. //스왑체인 생성 hr = m_pGIFactory->CreateSwapChain(m_pD3dDevice, &sd, &m_pSwapChain); if (FAILED(hr)) { return hr; } g_pSwapChain = m_pSwapChain; return hr; } //깊이 스텐실 뷰 생성 HRESULT DxDevice::CreateDpethStencilView() { if (m_pD3dDevice == nullptr) { return E_FAIL; } HRESULT hr = S_OK; ID3D11Texture2D* m_pTex2D; // 깊이 스텐실 버퍼 D3D11_TEXTURE2D_DESC td; td.MipLevels = 1; // 밉맵 갯수. td.ArraySize = 1; // 텍스쳐 배열의 텍스쳐 수 td.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; td.Usage = D3D11_USAGE_DEFAULT; td.BindFlags = D3D11_BIND_DEPTH_STENCIL; //기타 옵션 td.CPUAccessFlags = 0; td.MiscFlags = 0; //샘플링 수준 td.SampleDesc.Count = 1; td.SampleDesc.Quality = 0; //깊이스텐실 버퍼의 크기. 백버퍼의 크기와 같아야 한다. td.Width = g_rtClient.right; td.Height = g_rtClient.bottom; hr = g_pD3dDevice->CreateTexture2D(&td, 0, &m_pTex2D); if (FAILED(hr)) { return hr; } D3D11_DEPTH_STENCIL_VIEW_DESC dsvd; dsvd.Format = td.Format; //3차원이니까 2차원 자원을 깊이스텐실맵으로 사용. dsvd.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; dsvd.Texture2D.MipSlice = 0; //밉맵의 첫번째 인덱스. dsvd.Flags = 0; //옵션값 //깊이스텐실뷰 생성 (생성에 사용할 리소스, 생성 정보, 반환인자) hr = g_pD3dDevice->CreateDepthStencilView(m_pTex2D, &dsvd, &m_pDepthStencilView); if (FAILED(hr)) { return hr; } g_pDepthStencilView = m_pDepthStencilView; return hr; } //렌더타겟뷰 생성 및 세팅 HRESULT DxDevice::SetRenderTargetView() { HRESULT hr; ID3D11Texture2D* pBackBuffer; hr = m_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); //백버퍼를 받아옴 hr = m_pD3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &m_pRenderTagetView); //렌더 타겟 뷰 생성 pBackBuffer->Release(); g_pRenderTagetView = m_pRenderTagetView; return S_OK; } //뷰포트 세팅 HRESULT DxDevice::SetViewPort() { //스왑체인 정보를 가져옴. DXGI_SWAP_CHAIN_DESC Desc; m_pSwapChain->GetDesc(&Desc); //뷰포트의 시작 좌표 m_d3dViewPort.TopLeftX = 0; m_d3dViewPort.TopLeftY = 0; //스왑체인값에서 뷰포트 크기를 가져옴 m_d3dViewPort.Width = (FLOAT)Desc.BufferDesc.Width; m_d3dViewPort.Height = (FLOAT)Desc.BufferDesc.Height; //뷰포트의 깊이값은 0에서 1사이로 제한됨 m_d3dViewPort.MinDepth = 0.0f; m_d3dViewPort.MaxDepth = 1.0f; //렌더타켓뷰 세팅 m_pD3dContext->RSSetViewports(1, &m_d3dViewPort); g_d3dViewPort = m_d3dViewPort; return S_OK; } //전체 생성하기 HRESULT DxDevice::InitDevice() { HRESULT hr; if (FAILED(hr = CreateDevice())) { return hr; } if (FAILED(hr = CreateGIFactory())) { return hr; } if (FAILED(hr = CreateSwapChain())) { return hr; } if (FAILED(hr = CreateDpethStencilView())) { return hr; } if (FAILED(hr = SetRenderTargetView())) { return hr; } if (FAILED(hr = SetViewPort())) { return hr; } //ALT+ENTER와 메시지큐 모니터링을 막는다. m_pGIFactory->MakeWindowAssociation(g_hWnd, DXGI_MWA_NO_ALT_ENTER | DXGI_MWA_NO_WINDOW_CHANGES); return hr; } #pragma endregion //정리하기 bool DxDevice::CreanupDevice() { //삭제는 생성의 역순. //세팅값을 복원시켜주고 삭제한다. if (m_pD3dContext) { m_pD3dContext->ClearState(); } if (m_pD3dContext) { m_pD3dContext->Release(); } m_pD3dContext = g_pD3dContext = nullptr; if (m_pDepthStencilView) { m_pDepthStencilView->Release(); } m_pDepthStencilView = g_pDepthStencilView = nullptr; if (m_pRenderTagetView) { m_pRenderTagetView->Release(); } m_pRenderTagetView = g_pRenderTagetView = nullptr; if (m_pSwapChain) { m_pSwapChain->Release(); } m_pSwapChain = g_pSwapChain = nullptr; if (m_pD3dDevice) { m_pD3dDevice->Release(); } m_pD3dDevice = g_pD3dDevice = nullptr; if (m_pGIFactory) { m_pGIFactory->Release(); } m_pGIFactory = nullptr; return true; } DxDevice::~DxDevice() { } }
WinL.h
#pragma once #include "DxDevice.h" namespace Lypi { class winL : public DxDevice { protected: WNDCLASSEX m_wndC; //윈도우 클래스 LPCWSTR m_lWndName; //윈도우 이름 HWND m_hWnd; //생성된 윈도우의 핸들값 RECT m_rtWindow; //윈도우 영역 RECT m_rtClient; //클라이언트 영역 (작업영역) winL* m_pWindow; //현재 생성된 윈도우에 대한 포인터 public: bool registWnd(LPCTSTR LWndName); //윈도우 등록. LRESULT MsgProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); //윈도우 프로시저 virtual bool runWindow(); //윈도우 돌리기 virtual LRESULT MsgProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); //윈도우 메시지를 이용할 때 코어에서 호출 void CenterWindow(); //윈도우를 중앙으로 옮기는 함수 public: virtual bool gameInit() = 0; //게임 전체의 초기화를 담당 virtual bool gameRun() = 0; //게임의 전 과정을 실행. virtual bool gameFrame() = 0; //게임의 매 프레임 계산을 담당. virtual bool gamePreRender() = 0; //게임의 매 프레임 렌더링 전 필요한 절차를 담당. virtual bool gameRender() = 0; //게임의 매 프레임 렌더링을 담당. virtual bool gamePostRender() = 0; //게임의 매 프레임 렌더링 후 필요한 절차를 담당. virtual bool gameRelease() = 0; //게임 전체의 메모리 소멸 및 객체 해제를 담당. virtual bool ResetRT() = 0; public: winL(LPCTSTR LWndName); virtual ~winL(); }; }
WinL.cpp
#pragma once #include "WinL.h" namespace Lypi { //전역변수 선언 HINSTANCE g_hInst; //윈도우의 인스턴스 핸들값 HWND g_hWnd; //생성된 윈도우의 핸들값 winL* g_pWindow; //현재 생성된 윈도우에 대한 포인터 RECT g_rtWindow; //윈도우 영역 RECT g_rtClient; //클라이언트 영역 (작업영역) //전역함수 선언 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); //------------- winL::winL(LPCTSTR LWndName) { m_pWindow = this; g_pWindow = this; registWnd(LWndName); } //윈도우 등록 및 생성 bool winL::registWnd(LPCTSTR LWndName) { //Regist wndClass ZeroMemory(&m_wndC, sizeof(WNDCLASSEX)); m_wndC.cbSize = sizeof(WNDCLASSEX); m_wndC.hInstance = g_hInst; m_wndC.lpfnWndProc = WndProc; m_wndC.lpszClassName = LWndName; m_wndC.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); if (!RegisterClassEx(&m_wndC)) { return false; } m_hWnd = CreateWindowEx(0,//WS_EX_TOPMOST, // 윈도우 창 확장 스타일 m_wndC.lpszClassName, m_wndC.lpszClassName, // 윈도우 클래스 이름(중요), 타이틀 바에 나타날 문자열. WS_SYSMENU | WS_BORDER | WS_VISIBLE, // 생성될 윈도우 창의 스타일 지정 CW_USEDEFAULT, CW_USEDEFAULT, // 윈도우 X,Y 좌표 1516, 789, // 윈도우 수평, 수직 크기 (픽셀 단위) (x+16, y+39) NULL, NULL, g_hInst, // 부모 윈도우의 핸들 지정, 메뉴 핸들 지정, 윈도우를 생성하는 인스턴스 핸들 NULL); // WM_CREATE메시지의 lParam으로 전달될 CREATESTRUCT구조체 포인터 if (m_hWnd == NULL) { return false; } g_hWnd = m_hWnd; GetWindowRect(m_hWnd, &m_rtWindow); g_rtWindow = m_rtWindow; GetClientRect(m_hWnd, &m_rtClient); g_rtClient = m_rtClient; return true; } //in-class Msg Proc LRESULT winL::MsgProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { assert(m_pWindow); MsgProcA(hWnd, iMsg, wParam, lParam); switch (iMsg) { case WM_CREATE: { //윈도우를 생성할 때 발생하는 메시지 }break; case WM_SIZE: { }break; case WM_DESTROY: { //윈도우를 종료할 때 발생하는 메시지 (프로그램 종료와는 별도) PostQuitMessage(0); //프로그램 종료 명령 }break; } return 1; } LRESULT winL::MsgProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { return 1; } //윈도우 돌리기 bool winL::runWindow() { if (!gameInit()) { return false; } //Main message loop MSG msg; ZeroMemory(&msg, sizeof(MSG)); while (true) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); if (msg.message == WM_QUIT) { break; } } else { gameRun(); } } if (!gameRelease()) { return false; } return true; } //윈도우를 중앙으로 옮기는 함수. void winL::CenterWindow() { // 화면 스크린의 해상도(넓이와 높이)을 얻는다. int iScreenWidth = GetSystemMetrics(SM_CXFULLSCREEN); int iScreenHeight = GetSystemMetrics(SM_CYFULLSCREEN); // 윈도우 클라이언트 중앙과 화면 스크린 중앙을 맞춘다. int iDestX = (iScreenWidth - m_rtClient.right) / 2; int iDestY = (iScreenHeight - m_rtClient.bottom) / 2; // 윈도우를 화면중앙으로 이동시킨다. MoveWindow(m_hWnd, iDestX, iDestY, m_rtClient.right, m_rtClient.bottom, true); } winL::~winL() { } //전역함수 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { assert(g_pWindow != NULL); g_pWindow->MsgProc(hWnd, msg, wParam, lParam); return DefWindowProc(hWnd, msg, wParam, lParam); } }
zCore.h
#pragma once #include "WinL.h" #include "DxWrite.h" #include "DxTimer.h" #include "DxInput.h" namespace Lypi { class zCore : public winL { protected: public: bool ResetRT(); public: //게임 전체적인 처리 순서에 대한 함수들. 게임에 관한 부분과 윈도우 생성에 관한 부분을 분리 bool gameInit() override; bool gameRun() override; bool gameFrame() override; bool gamePreRender() override; bool gameRender() override; bool gamePostRender() override; bool gameRelease() override; public: //클래스 각각에 대한 처리 순서에 관한 함수들. virtual bool Init() { return true; }; virtual bool Frame() { return true; }; virtual bool PreRender() { return true; }; virtual bool Render() { return true; }; virtual bool PostRender() { return true; }; virtual bool Release() { return true; }; LRESULT MsgProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); public: zCore(LPCTSTR LWndName); virtual ~zCore(); }; }
zCore.cpp
#include "zCore.h" namespace Lypi { zCore::zCore(LPCTSTR LWndName) : winL(LWndName) { } LRESULT zCore::MsgProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { return 1; } bool zCore::ResetRT() { IDXGISurface1* pBackBuffer = nullptr; HRESULT hr = g_pSwapChain->GetBuffer(0, __uuidof(IDXGISurface), (void**)&pBackBuffer); if (pBackBuffer) { pBackBuffer->Release(); } return true; } bool zCore::gameInit() { //디바이스 생성 작업 실행. InitDevice(); ResetRT(); g_pWindow->CenterWindow(); Init(); return true; } bool zCore::gameRun() { gameFrame(); gamePreRender(); gameRender(); gamePostRender(); return true; } bool zCore::gameFrame() { Frame(); return true; } bool zCore::gamePreRender() { float ClearColor[4] = { 0.1f, 0.2f, 0.3f, 1.0f }; //r,g,b,a g_pD3dContext->ClearRenderTargetView(m_pRenderTagetView, ClearColor); g_pD3dContext->ClearDepthStencilView(m_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); g_pD3dContext->OMSetRenderTargets(1, &m_pRenderTagetView, m_pDepthStencilView); PreRender(); return true; } bool zCore::gameRender() { Render(); return true; } bool zCore::gamePostRender() { PostRender(); //IDXGISwapChain 객체를 사용하여 시연(출력)한다. //모든 렌더링 작업들은 present앞에서 이뤄져야 한다. g_pSwapChain->Present(0, 0); return true; } bool zCore::gameRelease() { Release(); if (!CreanupDevice()) { return false; } return true; } zCore::~zCore() { } }
반응형