반응형
아니 분명 몇달전에 했던 건데 안돼서 거의 한달 걸림...
토폴리지로 범위를 지정하고 그 위에 텍스쳐를 입히는 방식으로 처리했다.
전체 이미지를 배경으로 띄우는 방식으로도 사용가능하고,
이미지를 잘라서 일부만 띄울 수도 있고, 위치 데이터를 조정할 수도 있다.
DX로 2D게임 만들때 기본적으로 사용했던 방법.
윈도우 생성 소스부터 쭉 올린다.
스크롤을 줄이기 위해서 타이머, 폰트, 인풋은 빼놨는데 이전 소스에서 그대로 가져와서 붙이면 된다.
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()
{
}
obj.h
#pragma once
#include "header.h"
class Object_DX
{
protected:
ID3D11Buffer * m_pVertexBuffer; // 정점 버퍼
ID3D11VertexShader* m_pVS; // 정점 쉐이더
ID3D11PixelShader* m_pPS; // 픽셀 쉐이더
ID3D11InputLayout* m_pInputLayout; // 인풋 레이아웃
ID3D11ShaderResourceView* m_pTextureSRV; // 텍스쳐 SRV
ID3D11BlendState* m_pAlphaBlend;
ID3D11SamplerState* m_pSamplerState;
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 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()
{
}
//화면좌표계 -> 투영좌표게
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 / imgSize.width;
fImageUV.top = (float)m_uImagePart.top / imgSize.Height;
fImageUV.right = (float)m_uImagePart.right / imgSize.width;
fImageUV.bottom = (float)m_uImagePart.bottom / imgSize.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::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;
}
D3D11_SAMPLER_DESC samplerDesc;
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
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) {
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);
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;
}반응형