공부 중 메모/DirectX

11. SamplerState

라이피 (Lypi) 2019. 1. 30. 14:31
반응형

샘플러 스테이트를 적용한 코드


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;
}


반응형