반응형
샘플러 스테이트를 적용한 코드
Input의 keyDownOnce와 KeyUp 함수가 제대로 작동을 안하니 체크한 부분에 중단점 설정하고 확인해야 결과를 보기 좋을 것이다.
진도가 좀 급해서 일단 코드만 올리고 있지만 좀 여유로워지면 코드에 대한 설명을 추가하려고 한다.
지난 포스팅의 코드에서 obj.h와 obj.cpp에만 내용이 추가된 것이지만 혹시 모르니 이번에는 전체 코드를 첨부한다.
//아 갑자기 든 생각인데 이미지 경로는 따로 설정해야한다.
header.h
#pragma once #pragma warning(disable : 4005) #define DIRECTINPUT_VERSION 0x0800 #pragma region //헤더 및 lib 포함 //DX11을 쓰려면 필요함 #pragma comment (lib, "D3D11.lib") #include "D3D11.h" //DXGIFactory를 만드는데 사용됨. #pragma comment (lib, "DXGI.lib") #include "DXGI.h" //다이렉트 2D사용 #pragma comment (lib, "d2d1.lib") #include "D2D1.h" #include "D2D1Helper.h" //다이렉트 라이트 사용 #pragma comment (lib, "dwrite.lib") #include "DWrite.h" //다이렉트 인풋 사용. #pragma comment(lib, "dxguid.lib") #pragma comment(lib, "dinput8.lib") #include "dinput.h" //쉐이더를 사용가 #pragma comment(lib, "d3dx11.lib") #include "D3DX11.h" #pragma comment(lib, "d3dcompiler.lib") #include "D3Dcompiler.h" //DX벡터 사용 #include "D3DX10math.h" //에러처리를 위한 헤더 #include <assert.h> //유니코드 처리를 위한 부분 #include <string> using std::string; #include <tchar.h> using C_STR = std::basic_string<char>; using W_STR = std::basic_string<wchar_t>; using T_STR = std::basic_string<TCHAR>; using T_ITOR = std::basic_string<TCHAR>::iterator; //STL 헤더 #include <vector> #include <map> #include <list> #include <set> #include <bitset> #include <algorithm> #include <functional> #include <math.h> using namespace std; using namespace D2D1; #pragma endregion #pragma region //타입 정의 using T_STR_VECTOR = vector<basic_string<TCHAR>>; using C_STR_VECTOR = vector<string>; using DWORD_VECTOR = vector<DWORD>; using DWORD_VECTOR_ITOR = vector<DWORD>::iterator; using T_STR_LIST = list<basic_string<TCHAR>>; using CHAR_STRING = string; using DWORD_LIST = list<DWORD>; using DWORD_LIST_ITOR = list<DWORD>::iterator; using HANDLE_LIST = list<HANDLE>; using HANDLE_LIST_ITOR = list<HANDLE>::iterator; #pragma endregion #pragma region //매크로 정의 #ifndef V #define V(x) { hr = (x); } #endif #ifndef V_FRETURN #define V_FRETURN(x){ hr = (x); if( FAILED(hr) ) { return hr; } } #endif ////////////////////////////////////////////// // 객체 및 배열 할당과 삭제 및 소멸 매크로 ////////////////////////////////////////////// #ifndef SAFE_ZERO #define SAFE_ZERO(A) { A = 0; } #endif #ifndef SAFE_NEW #define SAFE_NEW(A, B) { if (!A) A = new B; } #endif #ifndef SAFE_DEL #define SAFE_DEL(A) { if (A) delete A; (A)=NULL; } #endif #ifndef SAFE_NEW_ARRAY #define SAFE_NEW_ARRAY(A, B, C) { if (!A && C) A = new B[C]; } #endif #ifndef SAFE_DELETE_ARRAY #define SAFE_DELETE_ARRAY(A) { if (A) delete [] A; (A)=NULL; } #endif #ifndef SAFE_RELEASE #define SAFE_RELEASE(A) { if(A) { (A)->Release(); (A)=NULL; } } #endif #ifndef SAFE_NEW_CLEAR #define SAFE_NEW_CLEAR( A, B ) { if (!A) A = new B; if(A) memset( A, 0, sizeof(B) ); }; #endif #ifndef SAFE_NEW_ARRAY_CLEAR #define NEW_ARRAY_CLEAR( A, B, C ) { if (!A && C) A = new B[C]; if(A) memset( A, 0, sizeof(B)*C ); }; #endif #pragma endregion #pragma region //외부 변수 정의 class wndC_DX; //device_DX extern ID3D11Device* g_pD3dDevice; extern ID3D11DeviceContext* g_pD3dContext; extern IDXGISwapChain* g_pSwapChain; //WndC_DX extern HINSTANCE g_hInst; extern HWND g_hWnd; extern RECT g_rtWindow; extern RECT g_rtClient; extern wndC_DX* g_pWindow; //core extern float g_dSPF; //게임 씬에서 extern float g_iWaveX; extern float g_iWaveY; //Hero extern float g_PCSpeedX; extern float g_PCSpeedY; #pragma endregion #pragma region //열거형 정의 enum direction { d_NO = 0, d_LEFT = 1, d_TOP = 2, d_RIGHT = 3, d_BOTTOM = 4, }; enum push { p_FREE = 0, p_DOWN = 1, p_HOLD = 2, p_UP = 3, }; #pragma endregion #pragma region //구조체 정의 struct PCT_VERTEX { D3DXVECTOR3 p; D3DXVECTOR4 c; D3DXVECTOR2 t; PCT_VERTEX() {} PCT_VERTEX(D3DXVECTOR3 vp, D3DXVECTOR4 vc, D3DXVECTOR2 vt) { p = vp; c = vc; t = vt; } bool operator== (const PCT_VERTEX& Vertex) { if (p == Vertex.p && c == Vertex.c && t == Vertex.t) { return true; } else { return false; } } }; struct PNCT_VERTEX { D3DXVECTOR3 p; D3DXVECTOR3 n; D3DXVECTOR4 c; D3DXVECTOR2 t; bool operator == (const PNCT_VERTEX & Vertex) { if (p == Vertex.p && n == Vertex.n && c == Vertex.c && t == Vertex.t) { return true; } return false; } PNCT_VERTEX() {} PNCT_VERTEX(D3DXVECTOR3 vp, D3DXVECTOR3 vn, D3DXVECTOR4 vc, D3DXVECTOR2 vt) { p = vp, n = vn, c = vc, t = vt; } }; struct uWH { UINT width; UINT Height; }; struct uPOINT { UINT x; UINT y; uPOINT& operator= (const POINT& pt) { x = pt.x; y = pt.y; return *this; } }; struct fLTRB { float left; float top; float right; float bottom; }; struct iXYWH { LONG ltx; LONG lty; UINT width; UINT height; }; struct iLTRB { LONG left; LONG top; LONG right; LONG bottom; iLTRB& operator= (const iXYWH& _xywh) { left = _xywh.ltx; top = _xywh.lty; right = _xywh.ltx + _xywh.width; bottom = _xywh.lty + _xywh.height; return *this; } }; struct circle { POINT pCenter; double dRadius; }; struct ClsInfo { bool bDoCls; direction drClsSrc; direction drClsDest; POINT ptInLength; }; struct MouseInfo { POINT xy; push left; push right; push middle; }; #pragma endregion #define stpX(x) ((x) / ((float)g_rtClient.right)) #define stpY(y) -((y) / ((float)g_rtClient.bottom))
device.h
#pragma once #include "header.h" //------------------------------------------------------------------------------------// //-DX11 Device를 생성한다. -----------------------------------------------------------// //-wndC_DX에서 DX11의 멤버 변수를 직접 접근하기 위해서 deviceC_DX가 더 위에 있다.-----// //------------------------------------------------------------------------------------// class deviceC_DX { protected: D3D_DRIVER_TYPE m_d3dDriverType; // 디바이스 타입 (디폴트 : 하드웨어 가속) D3D_FEATURE_LEVEL m_d3dFeatureLevel; // DX의 기능 수준 IDXGIFactory* m_pGIFactory; // DXGI 객체 ID3D11RenderTargetView* m_pRenderTagetView; // 메인 렌더타켓 뷰 D3D11_VIEWPORT m_d3dViewPort; // 뷰포트 public: HRESULT CreateDevice(); // 디바이스 및 디바이스 컨텍스트를 생성한다. HRESULT CreateGIFactory(); // IDXGIFactory 객체 생성 HRESULT CreateSwapChain(); // IDXGIFactory를 이용하여 스왑체인 생성 HRESULT SetRenderTargetView(); // 타겟 뷰 설정 HRESULT SetViewPort(); // 뷰 포트 설정 public: HRESULT InitDevice(); // 장치를 순서대로 생성한다. bool CreanupDevice(); // 생성한 것을 역순으로 삭제한다. public: deviceC_DX(); virtual ~deviceC_DX( ); };
device.cpp
#include "device.h" ID3D11Device* g_pD3dDevice; // 디바이스 객체 ID3D11DeviceContext* g_pD3dContext; // 디바이스 컨텍스트 IDXGISwapChain* g_pSwapChain; // 스왑체인 객체 deviceC_DX::deviceC_DX() { //어댑터(그래픽카드)를 사용하여 디바이스 객체를 생성해야 하므로 NULL로 선택. m_d3dDriverType = D3D_DRIVER_TYPE_NULL; //쉐이더5.0을 사용해야 하므로 11을 선택. m_d3dFeatureLevel = D3D_FEATURE_LEVEL_11_0; //선언 후 생성 전 초기화. g_pD3dDevice = nullptr; g_pD3dContext = nullptr; m_pGIFactory = nullptr; g_pSwapChain = nullptr; m_pRenderTagetView = nullptr; } //ID3D11Device 인터페이스를 생성한다. HRESULT deviceC_DX::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 버전 &g_pD3dDevice, //생성된 디바이스를 반환받을 주소 &m_d3dFeatureLevel, //선택된 피처레벨을 반환받을 주소. &g_pD3dContext); //생성된 DC를 반환받을 주소. //디바이스를 생성하는데 성공하였지만 버전이 11이 아닐 경우 다시 생성하게 한다. if (SUCCEEDED(hr)) { if (FAILED(hr) || m_d3dFeatureLevel < D3D_FEATURE_LEVEL_11_0) { if (g_pD3dContext) { g_pD3dContext->Release(); } if (g_pD3dDevice) { g_pD3dDevice->Release(); } continue; } break; } } if (FAILED(hr)) { return false; } return S_OK; } //DXGIFactory 인터페이스를 생성한다. HRESULT deviceC_DX::CreateGIFactory() { if (g_pD3dDevice == nullptr) { return E_FAIL; } HRESULT hr; IDXGIDevice* pDXGIDevice; IDXGIAdapter* pDXGIAdapter; //생성되어 있는 ID3D11Device로부터 출발해서 IDXGIFactory를 넘겨받는다. hr = g_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 deviceC_DX::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.Width = g_rtWindow.right; sd.BufferDesc.Height = g_rtWindow.bottom; sd.BufferDesc.RefreshRate.Numerator = 60; //화면 주사율 (분자) sd.BufferDesc.RefreshRate.Denominator = 1; //화면 주사율 (분모) sd.SampleDesc.Count = 1; //멀티샘플링용 sd.SampleDesc.Quality = 0; //이미지 품질 수준 sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; //버퍼 용도 sd.OutputWindow = g_hWnd; //어느 윈도우에 뿌릴지 (필수) sd.Windowed = true; //false 전체화면, true 창모드 sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; //스왑체인 생성 hr = m_pGIFactory->CreateSwapChain(g_pD3dDevice, &sd, &g_pSwapChain); if (FAILED(hr)) { return hr; } return hr; } //렌더타겟뷰 생성 및 세팅 HRESULT deviceC_DX::SetRenderTargetView() { HRESULT hr; ID3D11Texture2D* pBackBuffer; //백버퍼를 받아옴 hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); if (FAILED(hr)) { return hr; } //렌더 타겟 뷰 생성 hr = g_pD3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &m_pRenderTagetView); if (FAILED(hr)) { return hr; } pBackBuffer->Release(); //렌더타겟뷰 세팅 g_pD3dContext->OMSetRenderTargets(1, &m_pRenderTagetView, nullptr); return S_OK; } //뷰포트 세팅 HRESULT deviceC_DX::SetViewPort() { //스왑체인 정보를 가져옴. DXGI_SWAP_CHAIN_DESC Desc; g_pSwapChain->GetDesc(&Desc); //뷰포트의 높이와 넓이를 스왑체인 버퍼의 크기로 설정 m_d3dViewPort.Width = (FLOAT)Desc.BufferDesc.Width; m_d3dViewPort.Height = (FLOAT)Desc.BufferDesc.Height; m_d3dViewPort.MinDepth = 0.0f; //깊이값은 0에서 1사이로 제한됨 m_d3dViewPort.MaxDepth = 1.0f; //렌더타켓뷰 세팅 g_pD3dContext->RSSetViewports(1, &m_d3dViewPort); return S_OK; } //전체 생성하기 HRESULT deviceC_DX::InitDevice() { HRESULT hr; if (FAILED(hr = CreateDevice())) { return hr; } if (FAILED(hr = CreateGIFactory())) { return hr; } if (FAILED(hr = CreateSwapChain())) { 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; } //정리하기 bool deviceC_DX::CreanupDevice() { //삭제는 생성의 역순. //세팅값을 복원시켜주고 삭제한다. if (g_pD3dContext) { g_pD3dContext->ClearState(); } if (g_pD3dContext) { g_pD3dContext->Release(); } g_pD3dContext = nullptr; if (m_pRenderTagetView) { m_pRenderTagetView->Release(); } m_pRenderTagetView = nullptr; if (g_pSwapChain) { g_pSwapChain->Release(); } g_pSwapChain = nullptr; if (g_pD3dDevice) { g_pD3dDevice->Release(); } g_pD3dDevice = nullptr; if (m_pGIFactory) { m_pGIFactory->Release(); } m_pGIFactory = nullptr; return true; } deviceC_DX::~deviceC_DX() { }
wndC.h
#pragma once #include "device.h" class wndC_DX : public deviceC_DX { protected: WNDCLASSEX m_wndC; //윈도우 클래스 LPCWSTR m_lWndName; //윈도우 이름 public: void CenterWindow(); //윈도우를 중앙으로 옮기는 함수 //윈도우 프로시저 - 아예 전역 함수화 시켜둠. static LRESULT CALLBACK MsgProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); bool registWnd(LPCTSTR LWndName); //윈도우 등록. virtual bool runWindow(); //윈도우 돌리기 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: wndC_DX(LPCTSTR LWndName); virtual ~wndC_DX(); };
wndC.cpp
#include "wndC.h" //전역변수 선언 HINSTANCE g_hInst; //윈도우의 인스턴스 핸들값 HWND g_hWnd; //생성된 윈도우의 핸들값 RECT g_rtWindow; //윈도우 영역 RECT g_rtClient; //클라이언트 영역 (작업영역) wndC_DX* g_pWindow; //현재 생성된 윈도우에 대한 포인터 RECT g_rtScreen; //윈도우 프로시져 Static함수 LRESULT CALLBACK wndC_DX::MsgProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { assert(g_pWindow); switch (iMsg) { //윈도우를 생성할 때 발생하는 메시지 case WM_CREATE: { }break; //윈도우를 종료할 때 발생하는 메시지 (프로그램 종료와는 별도) case WM_DESTROY: { PostQuitMessage(0); }break; } return DefWindowProc(hWnd, iMsg, wParam, lParam); } wndC_DX::wndC_DX(LPCTSTR LWndName) { g_pWindow = this; registWnd(LWndName); } //윈도우를 중앙으로 옮기는 함수. void wndC_DX::CenterWindow() { // 화면 스크린의 해상도(넓이와 높이)을 얻는다. int iScreenWidth = GetSystemMetrics(SM_CXFULLSCREEN); int iScreenHeight = GetSystemMetrics(SM_CYFULLSCREEN); // 윈도우 클라이언트 중앙과 화면 스크린 중앙을 맞춘다. int iDestX = (iScreenWidth - g_rtWindow.right) / 2; int iDestY = (iScreenHeight - g_rtWindow.bottom) / 2; // 윈도우를 화면중앙으로 이동시킨다. MoveWindow(g_hWnd, iDestX, iDestY, g_rtWindow.right, g_rtWindow.bottom, true); } //윈도우 등록 및 생성 bool wndC_DX::registWnd(LPCTSTR LWndName) { //Regist wndClass ZeroMemory(&m_wndC, sizeof(WNDCLASSEX)); m_wndC.cbSize = sizeof(WNDCLASSEX); m_wndC.hInstance = g_hInst; m_wndC.lpfnWndProc = MsgProc; m_wndC.lpszClassName = LWndName; if (!RegisterClassEx(&m_wndC)) { return false; } g_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구조체 포인터 //창 스타일과 창 확장 스타일에 대한 부분은 문서 참조 //윈도우가 생성되지 않았으면 false를 리턴한다. if (g_hWnd == NULL) { return false; } GetWindowRect(g_hWnd, &g_rtWindow); GetClientRect(g_hWnd, &g_rtClient); return true; } //윈도우 돌리기 bool wndC_DX::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; } wndC_DX::~wndC_DX() { }
core.h
#pragma once #include "wndC.h" #include "timer.h" #include "write.h" #include "input.h" #include "obj.h" class coreC_DX : public wndC_DX { timerC_DX m_GameTimer; writeC_DX m_Font; Object_DX m_bg; ID3D11RasterizerState* m_pRSSolid; private: bool m_swTimerRender; bool m_swKeyRender; HRESULT SetRasterizerState(); public: //게임 전체적인 처리 순서에 대한 함수들. 게임에 관한 부분과 윈도우 생성에 관한 부분을 분리 bool gameInit() override; bool gameRun() override; bool gameFrame() override; bool gamePreRender() override; bool gameRender() override; bool gamePostRender() override; bool gameRelease() override; public: bool Init(); bool Frame(); bool Render(); bool Release(); public: coreC_DX(LPCTSTR LWndName); virtual ~coreC_DX(); };
core.cpp
#include "core.h" float g_dSPF; coreC_DX::coreC_DX(LPCTSTR LWndName) : wndC_DX(LWndName) { m_swTimerRender = false; m_swKeyRender = false; } HRESULT coreC_DX::SetRasterizerState() { HRESULT hr; D3D11_RASTERIZER_DESC desc; ZeroMemory(&desc, sizeof(D3D11_RASTERIZER_DESC)); desc.FillMode = D3D11_FILL_SOLID; desc.CullMode = D3D11_CULL_NONE; desc.DepthClipEnable = TRUE; hr = g_pD3dDevice->CreateRasterizerState(&desc, &m_pRSSolid); return hr; } bool coreC_DX::gameInit() { //디바이스 생성 작업 실행. InitDevice(); m_GameTimer.Init(); //SwapChain의 백버퍼 정보로 DXWrite객체 생성 IDXGISurface1* pBackBuffer = nullptr; HRESULT hr = g_pSwapChain->GetBuffer(0, __uuidof(IDXGISurface), (void**)&pBackBuffer); m_Font.Init(); m_Font.Set(pBackBuffer); if (pBackBuffer) { pBackBuffer->Release(); } //DXInput Device 생성 if (!I_Input.InitDirectInput(true, true)) { return false; } //DXInput 초기화 if (!I_Input.Init()) { return false; } g_pWindow->CenterWindow(); //윈도우를 화면 중앙으로 이동시킨다. SetRasterizerState(); //init Init(); return true; } bool coreC_DX::gameRun() { gameFrame(); gamePreRender(); gameRender(); gamePostRender(); return true; } bool coreC_DX::gameFrame() { m_GameTimer.Frame(); g_dSPF = m_GameTimer.getSPF(); I_Input.Frame(); if (I_Input.IsKeyDown(DIK_9)) { //중단점 설정 m_swTimerRender = !m_swTimerRender; } if (I_Input.IsKeyDown(DIK_0)) { //중단점 설정 m_swKeyRender = !m_swKeyRender; } //frame Frame(); return true; } bool coreC_DX::gamePreRender() { m_Font.DrawTextBegin(); return true; } bool coreC_DX::gameRender() { //ID3D11RenderTargetView 객체에 컬러를 채운다. (BackBuffer를 지운다.) float r = 0.21f; float g = 0.32f; float b = 0.45f; float ClearColor[4] = { r, g, b, 0.0f }; //r,g,b,a g_pD3dContext->ClearRenderTargetView(m_pRenderTagetView, ClearColor); Render(); TCHAR pBuffer[256]; memset(pBuffer, 0, sizeof(TCHAR) * 256); m_Font.SetTextPos(); m_Font.SetlayoutRt(0, 0, (FLOAT)g_rtClient.right, (FLOAT)g_rtClient.bottom); if (m_swTimerRender) { m_Font.SetAlignment(DWRITE_TEXT_ALIGNMENT_LEADING, DWRITE_PARAGRAPH_ALIGNMENT_NEAR); m_Font.SetTextColor(ColorF(1, 1, 1, 1)); _stprintf_s(pBuffer, _T("FPS:%d, SPF:%10.5f, GameTime:%10.2f"), m_GameTimer.getFPS(), m_GameTimer.getSPF(), m_GameTimer.getGameTime()); m_Font.DrawText(pBuffer); } if (m_swKeyRender) { m_Font.SetAlignment(DWRITE_TEXT_ALIGNMENT_LEADING, DWRITE_PARAGRAPH_ALIGNMENT_NEAR); //m_Font.SetTextPos(Matrix3x2F::Rotation(g_GameTimer*100, Point2F(400, 300))); m_Font.SetTextColor(ColorF(1, 0.3f, 0, 1)); int iCount = 0; MouseInfo Mouse = I_Input.getMouseInfo(); _stprintf_s(pBuffer, _T("Mouse X:%ld, Y:%ld"), Mouse.xy.x, Mouse.xy.y); UINT iStartX = 0; UINT iStartY = 30 + (20 * iCount); m_Font.SetlayoutRt((FLOAT)iStartX, (FLOAT)iStartY, (FLOAT)g_rtClient.right, (FLOAT)g_rtClient.bottom); m_Font.DrawText(pBuffer); iCount++; for (int iKey = 0; iKey < KeyStateCount; iKey++) { if (I_Input.m_KeyCurState[iKey] & 0x80) { _stprintf_s(pBuffer, _T("Key State : 0x%02x : %d"), iKey, I_Input.m_KeyCurState[iKey]); UINT iStartX = 0; UINT iStartY = 30 + (20 * iCount); m_Font.SetlayoutRt((FLOAT)iStartX, (FLOAT)iStartY, (FLOAT)g_rtClient.right, (FLOAT)g_rtClient.bottom); m_Font.DrawText(pBuffer); iCount++; } } } //render g_pD3dContext->RSSetState(m_pRSSolid); return true; } bool coreC_DX::gamePostRender() { //IDXGISwapChain 객체를 사용하여 시연(출력)한다. //모든 렌더링 작업들은 present앞에서 이뤄져야 한다. m_Font.DrawTextEnd(); g_pSwapChain->Present(0, 0); return true; } bool coreC_DX::gameRelease() { Release(); if (!I_Input.Release()) { return false; } if (!m_Font.Release()) { return false; } if (!m_GameTimer.Release()) { return false; } if (!CreanupDevice()) { return false; } return true; } bool coreC_DX::Init() { m_bg.CreateFullImgObj({ 0,0,1500,750 }, L"Desert.jpg"); return true; } bool coreC_DX::Frame() { I_Input.Frame(); m_bg.Frame(); return true; } bool coreC_DX::Render() { m_bg.Render(); return true; } bool coreC_DX::Release() { m_bg.Release(); return true; } coreC_DX::~coreC_DX() { }
input.h
#pragma once #include "header.h" #define KeyStateCount 256 #define DataBufferSize 16 class input_DX { public: LPDIRECTINPUT8 m_pDxInput; LPDIRECTINPUTDEVICE8 m_pDxKeypad; LPDIRECTINPUTDEVICE8 m_pDxMouse; BYTE m_KeyCurState[KeyStateCount]; BYTE m_KeyBefState[KeyStateCount]; DIMOUSESTATE m_MouseCurState; DIMOUSESTATE m_MouseBefState; MouseInfo m_MouseState; public: bool Init(); bool Frame(); bool Render(); bool Release(); bool ResetDevice(); bool ResetResource(); public: bool InitDirectInput(bool keypad, bool mouse); bool KeyProcess(); bool MouseProcess(); void SetAcquire(bool bActive); void DeviceAcquire(); void DeviceUnacquire(); bool IsKeyDown(DWORD dwKey); bool IsKeyUP(DWORD dwKey); bool IsKeyDownOnce(DWORD dwKey); MouseInfo getMouseInfo(); public: static input_DX& GetInstance(); protected: input_DX(); virtual ~input_DX(); }; #define I_Input input_DX::GetInstance()
input.cpp
#include "input.h" input_DX& input_DX::GetInstance() { static input_DX inst; return inst; } input_DX::input_DX() { m_pDxInput = nullptr; m_pDxKeypad = nullptr; m_pDxMouse = nullptr; } bool input_DX::Init() { //프로그램 시작시 한번만 초기화 되면 되는 거면 생성자에서, //필요할 때 한번씩 초기화 시켜줘야하는 거면 Init에서. ZeroMemory(&m_KeyBefState, sizeof(BYTE)*KeyStateCount); ZeroMemory(&m_KeyCurState, sizeof(BYTE)*KeyStateCount); ZeroMemory(&m_MouseBefState, sizeof(DIMOUSESTATE)); ZeroMemory(&m_MouseCurState, sizeof(DIMOUSESTATE)); return true; } bool input_DX::Frame() { if (!KeyProcess() || !MouseProcess()) { return false; } return true; } bool input_DX::Render() { return true; } bool input_DX::Release() { if (m_pDxInput) { if (m_pDxKeypad) { m_pDxKeypad->Unacquire(); m_pDxKeypad->Release(); m_pDxKeypad = nullptr; } if (m_pDxMouse) { m_pDxMouse->Unacquire(); m_pDxMouse->Release(); m_pDxMouse = nullptr; } m_pDxInput->Release(); m_pDxInput = nullptr; } return true; } bool input_DX::InitDirectInput(bool keypad, bool mouse) { HRESULT hr; if (m_pDxKeypad || m_pDxMouse) { return true; } V_FRETURN(DirectInput8Create(g_hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&m_pDxInput, NULL)); if (keypad) { V_FRETURN(m_pDxInput->CreateDevice(GUID_SysKeyboard, &m_pDxKeypad, NULL)); V_FRETURN(m_pDxKeypad->SetDataFormat(&c_dfDIKeyboard)); if (FAILED(hr = m_pDxKeypad->SetCooperativeLevel(g_hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND | DISCL_NOWINKEY))) { while (m_pDxKeypad->Acquire() == DIERR_INPUTLOST); if (FAILED(m_pDxKeypad->SetCooperativeLevel(g_hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND | DISCL_NOWINKEY))) { return false; } } while (m_pDxKeypad->Acquire() == DIERR_INPUTLOST); } if (mouse) { V_FRETURN(m_pDxInput->CreateDevice(GUID_SysMouse, &m_pDxMouse, NULL)); V_FRETURN(m_pDxMouse->SetDataFormat(&c_dfDIMouse)); if (FAILED(m_pDxMouse->SetCooperativeLevel(g_hWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) { while (m_pDxMouse->Acquire() == DIERR_INPUTLOST); if (FAILED(m_pDxMouse->SetCooperativeLevel(g_hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND))) { return false; } } while (m_pDxMouse->Acquire() == DIERR_INPUTLOST); } return true; } void input_DX::DeviceAcquire() { if (m_pDxKeypad) { m_pDxKeypad->Acquire(); } if (m_pDxMouse) { m_pDxMouse->Acquire(); } } void input_DX::DeviceUnacquire() { if (m_pDxKeypad) { m_pDxKeypad->Unacquire(); } if (m_pDxMouse) { m_pDxMouse->Unacquire(); } } void input_DX::SetAcquire(bool bActive) { if (bActive) { DeviceAcquire(); } else { DeviceUnacquire(); } } bool input_DX::KeyProcess() { memcpy(&m_KeyBefState, &m_KeyCurState, sizeof(BYTE) * KeyStateCount); ZeroMemory(m_KeyCurState, sizeof(BYTE)*KeyStateCount); if (!m_pDxKeypad) { return false; } if (FAILED(m_pDxKeypad->GetDeviceState(KeyStateCount, m_KeyCurState))) { while (m_pDxKeypad->Acquire() == DIERR_INPUTLOST) { m_pDxKeypad->Acquire(); } return true; } return true; } bool input_DX::MouseProcess() { memcpy(&m_MouseBefState, &m_MouseCurState, sizeof(DIMOUSESTATE)); ZeroMemory(&m_MouseCurState, sizeof(DIMOUSESTATE)); if (!m_pDxMouse) { return false; } if (FAILED(m_pDxMouse->GetDeviceState(sizeof(DIMOUSESTATE), &m_MouseCurState))) { while (m_pDxMouse->Acquire() == DIERR_INPUTLOST) { m_pDxMouse->Acquire(); } return true; } return true; } bool input_DX::ResetDevice() { Release(); Init(); return true; } bool input_DX::ResetResource() { return true; } #define KEYDOWN(key) (((m_KeyCurState[key]) & 0x80) ? true : false) #define KEYUP(key) (((m_KeyCurState[key]) & 0x00) ? true : false) bool input_DX::IsKeyDown(DWORD dwKey) { if (KEYDOWN(dwKey)) { return true; } return false; } bool input_DX::IsKeyUP(DWORD dwKey) { if (KEYDOWN(dwKey)) { if (KEYUP(dwKey)) { return true; } } return false; } bool input_DX::IsKeyDownOnce(DWORD dwKey) { if (KEYUP(dwKey)) { if (KEYDOWN(dwKey)) { return true; } } return false; } MouseInfo input_DX::getMouseInfo() { MouseInfo ret; POINT MousePos; GetCursorPos(&MousePos); ScreenToClient(g_hWnd, &MousePos); ret.xy = MousePos; ret.xy.x = MousePos.x * g_rtClient.right / (g_rtClient.right + g_rtWindow.left); ret.xy.y = MousePos.y * g_rtClient.bottom / (g_rtClient.bottom + g_rtWindow.top); for (int iB = 0; iB < 3; iB++) if (m_MouseBefState.rgbButtons[iB] & 0x80) { if (m_MouseCurState.rgbButtons[iB] & 0x80) { switch (iB) { case 0: ret.left = p_HOLD; case 1: ret.right = p_HOLD; case 2: ret.middle = p_HOLD; } } else { switch (iB) { case 0: ret.left = p_UP; case 1: ret.right = p_UP; case 2: ret.middle = p_UP; } } } else { if (m_MouseCurState.rgbButtons[iB] & 0x80) { switch (iB) { case 0: ret.left = p_DOWN; case 1: ret.right = p_DOWN; case 2: ret.middle = p_DOWN; } } else { switch (iB) { case 0: ret.left = p_FREE; case 1: ret.right = p_FREE; case 2: ret.middle = p_FREE; } } } for (int iB = 0; iB < 3; iB++) { m_MouseBefState.rgbButtons[iB] = m_MouseCurState.rgbButtons[iB]; } return ret; } input_DX::~input_DX() { Release(); }
timer.h
#pragma once #include "header.h" class timerC_DX { private: LARGE_INTEGER m_liFrequency; //초당 주파수 LARGE_INTEGER m_liCurTime; //현재 프레임에서의 시간 LARGE_INTEGER m_liBefTime; //이전 프레임에서의 시간 LARGE_INTEGER m_liFBefTime; //이전 프레임에서의 시간 LARGE_INTEGER m_liBef1sTime; //1초전 시간 float m_dGameTime; float m_dSPF; int m_iFPS; int m_iFPSGether; //초당 프레임 누적용 //개별 타이머는 타이머 클래스를 상속받아서 만드는걸로... LARGE_INTEGER m_BefTickTime; LARGE_INTEGER m_curTickTime; public: bool Init(); bool Frame(); bool Render(); bool Release(); bool tickAlram(double tick); float getGameTime(); float getSPF(); int getFPS(); public: timerC_DX(); virtual ~timerC_DX(); };
timer.cpp
#include "timer.h" timerC_DX::timerC_DX() { m_liFrequency.QuadPart = 0; m_liCurTime.QuadPart = 0; m_liBefTime.QuadPart = 0; m_liBef1sTime.QuadPart = 0; m_iFPSGether = 0; m_BefTickTime.QuadPart = 0; m_curTickTime.QuadPart = 0; //시스템의 주파수 변동폭을 얻어옴 // QueryPerformanceFrequency((LARGE_INTEGER*)&m_liFrequency); } bool timerC_DX::Init() { //일단 카운터 가져오기 QueryPerformanceCounter(&m_liBefTime); QueryPerformanceCounter(&m_liBef1sTime); QueryPerformanceCounter(&m_BefTickTime); //타이머 지원 여부 확인 if (m_liBefTime.QuadPart == 0) { return false; } m_iFPSGether = 0; return true; } bool timerC_DX::Frame() { //현재 시간 확인 QueryPerformanceCounter(&m_liCurTime); m_dSPF = static_cast<float>(m_liCurTime.QuadPart - m_liBefTime.QuadPart) / static_cast<float>(m_liFrequency.QuadPart); m_liBefTime = m_liCurTime; m_dGameTime += m_dSPF; static double fpsPivot; fpsPivot += m_dSPF; m_iFPSGether++; if (fpsPivot >= 1.0) { m_iFPS = m_iFPSGether; m_iFPSGether = 0; fpsPivot -= 1.0; } return true; } bool timerC_DX::Render() { return true; } bool timerC_DX::Release() { return true; } bool timerC_DX::tickAlram(double tick) { QueryPerformanceCounter(&m_curTickTime); if (((m_curTickTime.LowPart - m_BefTickTime.LowPart) / (m_liFrequency.LowPart)) >= tick) { m_BefTickTime = m_curTickTime; return true; } return false; } float timerC_DX::getGameTime() { return m_dGameTime; } float timerC_DX::getSPF() { return m_dSPF; } int timerC_DX::getFPS() { return m_iFPS; } timerC_DX::~timerC_DX() { }
write.h
#pragma once #include "header.h" class writeC_DX { protected: double m_dDpiScaleX; //화면 스케일 (출력 영역의 크기를 지정할 때 사용된다.) double m_dDpiScaleY; //화면 스케일 (출력 영역의 크기를 지정할 때 사용된다.) FLOAT m_FDpiX; //화면의 인치당 도트수 (요즘 모니터는 대부분 96.0F이다.) FLOAT m_FDpiY; //화면의 인치당 도트수 (요즘 모니터는 대부분 96.0F이다.) //DXGI에 독립적인 객체 ID2D1Factory* m_pD2dFactory; //d2d 팩토리 IDWriteFactory* m_pDWriteFactory; //DW 팩토리 IDWriteTextFormat* m_pTextFormat; //텍스트포맷 //DXGI에 종속적인 객체 ID2D1RenderTarget* m_pD2dRT; //d2d 렌더타켓뷰 ID2D1SolidColorBrush* m_pD2dSCB; //d2d 브러쉬 //텍스트 포맷 관련 D2D1_RECT_F m_D2rtLayoutRect; D2D1_COLOR_F m_D2dTextColor; //IDWriteTextLayout* m_pTextLayout; //텍스트 레이아웃 관련된건 다음에 더 파보는 걸로... public: //초기화 bool Init(); bool Set(IDXGISurface1* m_pSurface); //객체 생성 및 소멸 HRESULT CreateDeviceIR(); HRESULT CreateDeviceR(IDXGISurface1* pSurface); void DiscardDeviceIR(); void DiscardDeviceR(); //포맷 변경 void SetAlignment(DWRITE_TEXT_ALIGNMENT textAlignment, DWRITE_PARAGRAPH_ALIGNMENT paragraphAlignment); void SetlayoutRt(FLOAT left, FLOAT top, FLOAT right, FLOAT bottom); void SetTextPos(const D2D1_MATRIX_3X2_F& transform = Matrix3x2F::Identity()); ColorF SetTextColor(ColorF color); //텍스트 그리기 void DrawTextBegin(); bool DrawText(TCHAR* pText); void DrawTextEnd(); //전체 삭제 bool Release(); public: writeC_DX(); virtual ~writeC_DX(); };
write.cpp
#include "write.h" using namespace D2D1; writeC_DX::writeC_DX() { m_pD2dFactory = nullptr; m_pD2dRT = nullptr; m_pD2dSCB = nullptr; m_pDWriteFactory = nullptr; m_pTextFormat = nullptr; m_dDpiScaleX = 0; m_dDpiScaleY = 0; m_FDpiX = 0; m_FDpiY = 0; //흰색을 기본값으로 함. m_D2dTextColor = ColorF(1, 1, 1, 1); } //객체 생성 HRESULT writeC_DX::CreateDeviceIR() { HRESULT hr; //D2D 팩토리 생성 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2dFactory); //사실 어차피 96이고 나누면 1이다(..) m_pD2dFactory->GetDesktopDpi(&m_FDpiX, &m_FDpiY); m_dDpiScaleX = m_FDpiX / 96.0; m_dDpiScaleY = m_FDpiY / 96.0; //DW 팩토리 생성 if (SUCCEEDED(hr)) { hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), (IUnknown**)&m_pDWriteFactory); } //텍스트 포맷 생성 if (SUCCEEDED(hr)) { hr = m_pDWriteFactory->CreateTextFormat( _T("고딕"), NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_ULTRA_EXPANDED, 15.0f, _T("ko-kr"), &m_pTextFormat ); } return hr; } HRESULT writeC_DX::CreateDeviceR(IDXGISurface1* pSurface) { HRESULT hr = S_OK; //렌더링 옵션을 설정하는 구조체. D2D1_RENDER_TARGET_PROPERTIES props; props.type = D2D1_RENDER_TARGET_TYPE_DEFAULT; props.pixelFormat = PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_IGNORE); props.dpiX = m_FDpiX; props.dpiY = m_FDpiY; props.usage = D2D1_RENDER_TARGET_USAGE_NONE; props.minLevel = D2D1_FEATURE_LEVEL_DEFAULT; //D2D렌더타겟 생성 hr = m_pD2dFactory->CreateDxgiSurfaceRenderTarget(pSurface, &props, &m_pD2dRT); if (FAILED(hr)) { return hr; } //정해진 색 사용시 ColorF(ColorF::Coral) V_FRETURN(m_pD2dRT->CreateSolidColorBrush(m_D2dTextColor, &m_pD2dSCB)); return hr; } //객체 삭제 void writeC_DX::DiscardDeviceIR() { SAFE_RELEASE(m_pD2dFactory); SAFE_RELEASE(m_pDWriteFactory); SAFE_RELEASE(m_pTextFormat); } void writeC_DX::DiscardDeviceR() { SAFE_RELEASE(m_pD2dRT); SAFE_RELEASE(m_pD2dSCB); } //초기화 bool writeC_DX::Init() { HRESULT hr; //독립적인 객체 생성 V(CreateDeviceIR()); return true; } bool writeC_DX::Set(IDXGISurface1* m_pSurface) { HRESULT hr; //종속적인 객체 생성 (화면 크기 변경시 재생성함) V(CreateDeviceR(m_pSurface)); return true; } //포맷 변경 void writeC_DX::SetAlignment(DWRITE_TEXT_ALIGNMENT textAlignment, DWRITE_PARAGRAPH_ALIGNMENT paragraphAlignment) { //TextFormat 지정 m_pTextFormat->SetTextAlignment(textAlignment); m_pTextFormat->SetParagraphAlignment(paragraphAlignment); } void writeC_DX::SetlayoutRt(FLOAT left, FLOAT top, FLOAT right, FLOAT bottom) { m_D2rtLayoutRect = RectF(left, top, right, bottom); } void writeC_DX::SetTextPos(const D2D1_MATRIX_3X2_F& transform) { m_pD2dRT->SetTransform(transform); } ColorF writeC_DX::SetTextColor(ColorF color) { ColorF oldColor(m_D2dTextColor.r, m_D2dTextColor.g, m_D2dTextColor.b, m_D2dTextColor.a); m_D2dTextColor = color; m_pD2dSCB->SetColor(m_D2dTextColor); return oldColor; } //DrawText void writeC_DX::DrawTextBegin() { m_pD2dRT->BeginDraw(); } bool writeC_DX::DrawText(TCHAR* pText) { //D2D Draw는 Begin과 End사이에서 이루어져야한다. if (m_pD2dRT && m_pD2dSCB) { //텍스트 출력 m_pD2dRT->DrawTextW(pText, (UINT)_tcslen(pText), m_pTextFormat, m_D2rtLayoutRect, m_pD2dSCB); } return true; } void writeC_DX::DrawTextEnd() { m_pD2dRT->EndDraw(); } //전체 삭제 bool writeC_DX::Release() { DiscardDeviceIR(); DiscardDeviceR(); return true; } writeC_DX::~writeC_DX() { Release(); }
obj.h
#pragma once #include "header.h" #include "input.h" class Object_DX { protected: ID3D11Buffer * m_pVertexBuffer; // 정점 버퍼 ID3D11VertexShader* m_pVS; // 정점 쉐이더 ID3D11PixelShader* m_pPS; // 픽셀 쉐이더 ID3D11InputLayout* m_pInputLayout; // 인풋 레이아웃 ID3D11ShaderResourceView* m_pTextureSRV; // 텍스쳐 SRV ID3D11BlendState* m_pAlphaBlend; //sampler 변수 ID3D11SamplerState* m_pSamplerState; UINT m_idxFilter; D3D11_FILTER m_dxFilter; UINT m_iTexAddressMode; FLOAT m_MinLod; int m_i; protected: PNCT_VERTEX m_pVertexList[4]; uWH m_uImageSize; iLTRB m_uImagePart; fLTRB m_fPRegion; POINT m_ptCenter; D3DXVECTOR3 m_v3Center; public: iLTRB m_uSRegion; bool m_bExist; private: void transStoP(); //화면 -> 투영 void transPtoS(); //투영 -> 화면 void UpdateCP(); //중점 갱신 void UpdateVertexList(); //정점 리스트 갱신 void ImagePartialSelect(iXYWH imgXYWH, uWH imgSize); HRESULT setSamplerState(); HRESULT Create(const TCHAR* pTexFile); public: void SetPosition(iXYWH _xywh); void CreateFullImgObj(iXYWH _xywh, const TCHAR* pTexFile); void CreatePartImgObj(iXYWH _xywh, iXYWH imgXYWH, uWH imgSize, const TCHAR* pTexFile); void ImagePartialChange(iXYWH); void ImageFileChange(const TCHAR* pTexFile); void MoveX(float fDis); void MoveY(float fDis); iLTRB getPos(); void spin(float fAngle); void scale(float size); void ColorChange(float r, float g, float b, float a); public: virtual bool Init(); virtual bool Frame(); virtual bool Render(); virtual bool Release(); public: Object_DX(); virtual ~Object_DX(); };
obj.cpp
#include "obj.h" Object_DX::Object_DX() { m_i = 1; } //화면좌표계 -> 투영좌표게 void Object_DX::transStoP() { m_fPRegion.left = (m_uSRegion.left / ((float)g_rtClient.right)) * 2 - 1.0f; m_fPRegion.top = -((m_uSRegion.top / ((float)g_rtClient.bottom)) * 2 - 1.0f); m_fPRegion.right = (m_uSRegion.right / ((float)g_rtClient.right)) * 2 - 1.0f; m_fPRegion.bottom = -((m_uSRegion.bottom / ((float)g_rtClient.bottom)) * 2 - 1.0f); } //투영좌표계 -> 화면좌표계 void Object_DX::transPtoS() { m_uSRegion.left = (UINT)((m_fPRegion.left + 1.0f) / 2 * ((float)g_rtClient.right)); m_uSRegion.top = (UINT)((m_fPRegion.top - 1.0f) / -2 * ((float)g_rtClient.bottom)); m_uSRegion.right = (UINT)((m_fPRegion.right + 1.0f) / 2 * ((float)g_rtClient.right)); m_uSRegion.bottom = (UINT)((m_fPRegion.bottom - 1.0f) / -2 * ((float)g_rtClient.bottom)); } //중점 갱신 void Object_DX::UpdateCP() { m_ptCenter.x = (m_uSRegion.right + m_uSRegion.left) / 2; m_ptCenter.y = (m_uSRegion.bottom + m_uSRegion.top) / 2; m_v3Center.x = 0.0f; m_v3Center.y = 0.0f; m_v3Center.z = 0.0f; for (int iV = 0; iV < 4; iV++) { m_v3Center.x += m_pVertexList[iV].p.x; m_v3Center.y += m_pVertexList[iV].p.y; } m_v3Center.x /= 4; m_v3Center.y /= 4; } //정점 리스트 갱신 void Object_DX::UpdateVertexList() { m_pVertexList[0].p = D3DXVECTOR3(m_fPRegion.left, m_fPRegion.top, 0.0f); m_pVertexList[1].p = D3DXVECTOR3(m_fPRegion.left, m_fPRegion.bottom, 0.0f); m_pVertexList[2].p = D3DXVECTOR3(m_fPRegion.right, m_fPRegion.top, 0.0f); m_pVertexList[3].p = D3DXVECTOR3(m_fPRegion.right, m_fPRegion.bottom, 0.0f); for (int pl = 0; pl < 4; pl++) { m_pVertexList[pl].c = D3DXVECTOR4(1, 1, 1, 1); } //중점 갱신 UpdateCP(); } //생성 위치 지정하기 void Object_DX::SetPosition(iXYWH _xywh) { //화면 좌표계 저장 m_uSRegion = _xywh; //투영 좌표계 변환 transStoP(); //정점 리스트 저장 UpdateVertexList(); } //이미지 자르기 void Object_DX::ImagePartialSelect(iXYWH imgXYWH, uWH imgSize) { m_uImagePart = imgXYWH; m_uImageSize = imgSize; fLTRB fImageUV; //이미지 화면 좌표를 uv좌표로 변환 fImageUV.left = (float)m_uImagePart.left / m_uImageSize.width; fImageUV.top = (float)m_uImagePart.top / m_uImageSize.Height; fImageUV.right = (float)m_uImagePart.right / m_uImageSize.width; fImageUV.bottom = (float)m_uImagePart.bottom / m_uImageSize.Height; m_pVertexList[0].t = D3DXVECTOR2(fImageUV.left, fImageUV.top); m_pVertexList[1].t = D3DXVECTOR2(fImageUV.left, fImageUV.bottom); m_pVertexList[2].t = D3DXVECTOR2(fImageUV.right, fImageUV.top); m_pVertexList[3].t = D3DXVECTOR2(fImageUV.right, fImageUV.bottom); } HRESULT Object_DX::setSamplerState() { HRESULT hr; D3D11_SAMPLER_DESC samplerDesc; samplerDesc.Filter = m_dxFilter; samplerDesc.AddressU = (D3D11_TEXTURE_ADDRESS_MODE)m_iTexAddressMode; samplerDesc.AddressV = (D3D11_TEXTURE_ADDRESS_MODE)m_iTexAddressMode; samplerDesc.AddressW = (D3D11_TEXTURE_ADDRESS_MODE)m_iTexAddressMode; samplerDesc.MipLODBias = 0.0f; samplerDesc.MaxAnisotropy = 16; samplerDesc.ComparisonFunc = D3D11_COMPARISON_EQUAL; samplerDesc.BorderColor[0] = 0.0f; samplerDesc.BorderColor[1] = 0.0f; samplerDesc.BorderColor[2] = 0.0f; samplerDesc.BorderColor[3] = 0.0f; samplerDesc.MinLOD = m_MinLod; samplerDesc.MaxLOD = m_MinLod + 1; hr = g_pD3dDevice->CreateSamplerState(&samplerDesc, &m_pSamplerState); if (FAILED(hr)) { return hr; } return hr; } //오브젝트 생성하기 HRESULT Object_DX::Create(const TCHAR* pTexFile) { HRESULT hr; // 정점 버퍼 생성 D3D11_BUFFER_DESC sDesc; ZeroMemory(&sDesc, sizeof(D3D11_BUFFER_DESC)); sDesc.Usage = D3D11_USAGE_DEFAULT; sDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; sDesc.ByteWidth = sizeof(PNCT_VERTEX) * 4; D3D11_SUBRESOURCE_DATA sInitData; ZeroMemory(&sInitData, sizeof(D3D11_SUBRESOURCE_DATA)); sInitData.pSysMem = m_pVertexList; if (FAILED(hr = g_pD3dDevice->CreateBuffer(&sDesc, &sInitData, &m_pVertexBuffer))) { return hr; } //정점 쉐이더 생성 ID3DBlob* pErrorBlob; ID3DBlob* pVSBlob; hr = D3DX11CompileFromFile(L"shader.vsh", NULL, NULL, "VS", "vs_5_0", NULL, NULL, NULL, &pVSBlob, &pErrorBlob, NULL); if (FAILED(hr)) { OutputDebugStringA((char*)pErrorBlob->GetBufferPointer()); return false; } hr = g_pD3dDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &m_pVS); if (FAILED(hr)) { return hr; } //레이아웃 생성 if (pVSBlob == NULL) { return E_FAIL; } D3D11_INPUT_ELEMENT_DESC ied[] = { { "POS", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "NO", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; int iNumElement = sizeof(ied) / sizeof(D3D11_INPUT_ELEMENT_DESC); hr = g_pD3dDevice->CreateInputLayout(ied, iNumElement, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &m_pInputLayout); if (FAILED(hr)) { return hr; } //픽셀 쉐이더 생성 ID3DBlob* pPSBlop; hr = D3DX11CompileFromFile(L"shader.psh", NULL, NULL, "PS", "ps_5_0", NULL, NULL, NULL, &pPSBlop, &pErrorBlob, NULL); if (FAILED(hr)) { OutputDebugStringA((char*)pErrorBlob->GetBufferPointer()); return false; } hr = g_pD3dDevice->CreatePixelShader(pPSBlop->GetBufferPointer(), pPSBlop->GetBufferSize(), NULL, &m_pPS); if (FAILED(hr)) { SAFE_RELEASE(pPSBlop); return NULL; } SAFE_RELEASE(pErrorBlob); SAFE_RELEASE(pPSBlop); SAFE_RELEASE(pVSBlob); //블렌드 스테이트 생성 D3D11_BLEND_DESC BlendState; ZeroMemory(&BlendState, sizeof(D3D11_BLEND_DESC)); BlendState.AlphaToCoverageEnable = FALSE; BlendState.IndependentBlendEnable = FALSE; BlendState.RenderTarget[0].BlendEnable = TRUE; BlendState.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; BlendState.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; BlendState.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; BlendState.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; BlendState.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; BlendState.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; BlendState.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; if (FAILED(hr = g_pD3dDevice->CreateBlendState(&BlendState, &m_pAlphaBlend))) { return hr; } m_dxFilter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; m_iTexAddressMode = D3D11_TEXTURE_ADDRESS_CLAMP; D3D11_SAMPLER_DESC samplerDesc; samplerDesc.Filter = m_dxFilter; samplerDesc.AddressU = (D3D11_TEXTURE_ADDRESS_MODE)m_iTexAddressMode; samplerDesc.AddressV = (D3D11_TEXTURE_ADDRESS_MODE)m_iTexAddressMode; samplerDesc.AddressW = (D3D11_TEXTURE_ADDRESS_MODE)m_iTexAddressMode; samplerDesc.MipLODBias = 0.0f; samplerDesc.MaxAnisotropy = 16; samplerDesc.ComparisonFunc = D3D11_COMPARISON_EQUAL; samplerDesc.BorderColor[0] = 0.0f; samplerDesc.BorderColor[1] = 0.0f; samplerDesc.BorderColor[2] = 0.0f; samplerDesc.BorderColor[3] = 0.0f; samplerDesc.MinLOD = 0; samplerDesc.MaxLOD = 0; hr = g_pD3dDevice->CreateSamplerState(&samplerDesc, &m_pSamplerState); if (FAILED(hr)) { return hr; } //텍스쳐 로드 hr = D3DX11CreateShaderResourceViewFromFile(g_pD3dDevice, pTexFile, NULL, NULL, &m_pTextureSRV, NULL); if (FAILED(hr)) { return hr; } return hr; } void Object_DX::ImageFileChange(const TCHAR* pTexFile) { D3DX11CreateShaderResourceViewFromFile(g_pD3dDevice, pTexFile, NULL, NULL, &m_pTextureSRV, NULL); } //전체 이미지 오브젝트 생성 void Object_DX::CreateFullImgObj(iXYWH _xywh, const TCHAR* pTexFile) { int i = 1; SetPosition(_xywh); ImagePartialSelect({ 0,0,1,1 }, { 1,1 }); Create(pTexFile); } //부분 이미지 오브젝트 생성 void Object_DX::CreatePartImgObj(iXYWH _xywh, iXYWH imgXYWH, uWH imgSize, const TCHAR* pTexFile) { SetPosition(_xywh); ImagePartialSelect(imgXYWH, imgSize); Create(pTexFile); } //이미지 선택 영역 변경 void Object_DX::ImagePartialChange(iXYWH _uXYWH) { ImagePartialSelect(_uXYWH, m_uImageSize); } iLTRB Object_DX::getPos() { return m_uSRegion; } //x축 이동 void Object_DX::MoveX(float fDis) { for (int iV = 0; iV < 4; iV++) { m_pVertexList[iV].p.x += fDis * g_dSPF; } m_fPRegion.left += fDis * g_dSPF; m_fPRegion.right += fDis * g_dSPF; transPtoS(); UpdateCP(); } //y축 이동 void Object_DX::MoveY(float fDis) { for (int iV = 0; iV < 4; iV++) { m_pVertexList[iV].p.y += fDis * g_dSPF; } m_fPRegion.top += fDis * g_dSPF; m_fPRegion.bottom += fDis * g_dSPF; transPtoS(); UpdateCP(); } //회전 void Object_DX::spin(float fAngle) { float S = sinf(fAngle); float C = cosf(fAngle); for (int iV = 0; iV < 4; iV++) { D3DXVECTOR3 vertex = m_pVertexList[iV].p; m_pVertexList[iV].p.x -= m_v3Center.x; m_pVertexList[iV].p.y -= m_v3Center.y; vertex.x = m_pVertexList[iV].p.x * C + m_pVertexList[iV].p.y * S / 2; vertex.y = m_pVertexList[iV].p.x * -S * 2 + m_pVertexList[iV].p.y * C; vertex.x += m_v3Center.x; vertex.y += m_v3Center.y; m_pVertexList[iV].p = vertex; } } //크기 조절 void Object_DX::scale(float size) {//값 넣을 때 주의 for (int iV = 0; iV < 4; iV++) { m_pVertexList[iV].p.x -= m_v3Center.x; m_pVertexList[iV].p.y -= m_v3Center.y; m_pVertexList[iV].p.x *= size; m_pVertexList[iV].p.y *= size; m_pVertexList[iV].p.x += m_v3Center.x; m_pVertexList[iV].p.y += m_v3Center.y; } } void Object_DX::ColorChange(float r, float g, float b, float a) { for (int pl = 0; pl < 4; pl++) { m_pVertexList[pl].c = D3DXVECTOR4(r, g, b, a); } } bool Object_DX::Init() { return true; } bool Object_DX::Frame() { g_pD3dContext->UpdateSubresource(m_pVertexBuffer, 0, NULL, m_pVertexList, 0, 0); if (I_Input.IsKeyDown(DIK_4) == true) {//중단점 설정 m_i++; fLTRB fImageUV; //이미지 화면 좌표를 uv좌표로 변환 fImageUV.left = (float)m_uImagePart.left / m_uImageSize.width; fImageUV.top = (float)m_uImagePart.top / m_uImageSize.Height; fImageUV.right = (float)m_uImagePart.right * m_i / m_uImageSize.width; fImageUV.bottom = (float)m_uImagePart.bottom * m_i / m_uImageSize.Height; m_pVertexList[0].t = D3DXVECTOR2(fImageUV.left, fImageUV.top); m_pVertexList[1].t = D3DXVECTOR2(fImageUV.left, fImageUV.bottom); m_pVertexList[2].t = D3DXVECTOR2(fImageUV.right, fImageUV.top); m_pVertexList[3].t = D3DXVECTOR2(fImageUV.right, fImageUV.bottom); } if (I_Input.IsKeyDown(DIK_5) == true) {//중단점 설정 m_idxFilter++; switch (m_idxFilter) { case 1: { m_dxFilter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; setSamplerState(); }break; case 2: { m_dxFilter = D3D11_FILTER_ANISOTROPIC; setSamplerState(); }break; default: m_dxFilter = D3D11_FILTER_MIN_MAG_MIP_POINT; m_idxFilter = 0; setSamplerState(); break; } } if (I_Input.IsKeyDown(DIK_6) == true) {//중단점 설정 m_iTexAddressMode++; if (m_iTexAddressMode > 5) { m_iTexAddressMode = 1; } setSamplerState(); } if (I_Input.IsKeyDown(DIK_7) == true) {//중단점 설정 m_MinLod++; setSamplerState(); } return true; return true; } bool Object_DX::Render() { UINT pStrides = sizeof(PNCT_VERTEX); UINT pOffsets = 0; ID3D11SamplerState* SS[1]; SS[0] = m_pSamplerState; g_pD3dContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &pStrides, &pOffsets); g_pD3dContext->IASetInputLayout(m_pInputLayout); g_pD3dContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); g_pD3dContext->VSSetShader(m_pVS, NULL, NULL); g_pD3dContext->PSSetShader(m_pPS, NULL, NULL); g_pD3dContext->PSSetShaderResources(0, 1, &m_pTextureSRV); g_pD3dContext->PSSetSamplers(0, 1, SS); g_pD3dContext->OMSetBlendState(m_pAlphaBlend, 0, -1); g_pD3dContext->Draw(4, 0); return true; } bool Object_DX::Release() { SAFE_RELEASE(m_pVertexBuffer); SAFE_RELEASE(m_pVS); SAFE_RELEASE(m_pPS); SAFE_RELEASE(m_pInputLayout); SAFE_RELEASE(m_pTextureSRV); return true; } Object_DX::~Object_DX() { }
main.cpp
#include "core.h" int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) { g_hInst = hInst; coreC_DX GameWnd(_T("GameWindow")); GameWnd.runWindow(); return 0; }
반응형