1. Device
2. Window
3. Sample
//TDevice.h
#pragma once
#include <assert.h>
#include <tchar.h>
#include <d3d11.h>
#include <dxerr.h>
#pragma comment (lib, "dxgi.lib")
#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "dxerr.lib")
#pragma comment (lib, "legacy_stdio_definitions.lib")
class TDevice
{
public:
//--------------------------------------------------------------------------------------
// Global Variables
//--------------------------------------------------------------------------------------
ID3D11Device* m_pd3dDevice; // 디바이스 객체
IDXGISwapChain* m_pSwapChain; // 스왑체인 객체
ID3D11RenderTargetView* m_pRenderTargetView;// 메인 랜더타켓 뷰
D3D11_VIEWPORT m_ViewPort; // 뷰포트
D3D_DRIVER_TYPE m_driverType; // 디바이스 타입( 디폴트:하드웨어 가속 )
IDXGIFactory* m_pGIFactory; // DXGI 객체
ID3D11DeviceContext* m_pImmediateContext;// 디바이스 컨텍스트
D3D_DRIVER_TYPE m_DriverType; // 디바이스 타입
D3D_FEATURE_LEVEL m_FeatureLevel; // DirectX의 기능수준
public:
//--------------------------------------------------------------------------------------
// 디바이스 및 스왑체인 생성 :
// 1, CreateDevice()
// 2, CreateGIFactory()
// 3, CreateSwapChain()
// 4, SetRenderTargetView()
// 5, SetViewPort()
//--------------------------------------------------------------------------------------
HRESULT CreateDevice();
HRESULT CreateGIFactory();
HRESULT CreateSwapChain(HWND hWnd, UINT iWidth, UINT iHeigh);
//--------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------
HRESULT SetRenderTargetView();
HRESULT SetViewPort();
bool CleanupDevice();
public:
TDevice(void);
virtual ~TDevice(void);
};
/////////////////////////////////////////////
//TDevice.cpp
#include "TDevice.h"
//--------------------------------------------------------------------------------------
// ID3D11Device 인터페이스를 생성한다.
//--------------------------------------------------------------------------------------
HRESULT TDevice::CreateDevice()
{
HRESULT hr;
UINT createDeviceFlags = 0;
#ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D_DRIVER_TYPE driverTypes[] =
{
D3D_DRIVER_TYPE_UNKNOWN,
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
UINT numDriverTypes = sizeof( driverTypes ) / sizeof( driverTypes[0] );
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
};
UINT numFeatureLevels = sizeof( featureLevels ) / sizeof( featureLevels[0] );
//IDXGIAdapter* pAdapter = NULL;
//m_pGIFactory->EnumAdapters( 0, &pAdapter );
for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
{
m_DriverType = driverTypes[driverTypeIndex];
if( SUCCEEDED( hr = D3D11CreateDevice( NULL, m_DriverType, NULL, createDeviceFlags,
featureLevels, numFeatureLevels,
D3D11_SDK_VERSION, &m_pd3dDevice, &m_FeatureLevel, &m_pImmediateContext ) ))
{
if( FAILED( hr ) || m_FeatureLevel < D3D_FEATURE_LEVEL_11_0)
{
if( m_pImmediateContext ) m_pImmediateContext->Release();
if( m_pd3dDevice ) m_pd3dDevice->Release();
continue;
}
break;
}
}
//if( pAdapter ) pAdapter->Release();
if( FAILED( hr ) )
{
//DXTRACE_ERR_MSGBOX(DXGetErrorDescription(hr), hr);
return false;
}
DXTRACE_MSG(DXGetErrorDescription(hr));
return S_OK;
}
//--------------------------------------------------------------------------------------
// DXGIFactory 인터페이스를 생성한다.
//--------------------------------------------------------------------------------------
HRESULT TDevice::CreateGIFactory()
{
HRESULT hr;
if( FAILED( hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&m_pGIFactory) ) ))
{
//DXTRACE_ERR_MSGBOX( DXGetErrorDescription(hr), hr );
//MessageBox( m_hWnd, DXGetErrorDescription(hr), DXGetErrorString(hr), MB_OK );
return false;
}
return hr;
}
//--------------------------------------------------------------------------------------
// DXGIFactory 인터페이스로부터 IDXGISwapChain 인터페이스를 생성한다.
//--------------------------------------------------------------------------------------
HRESULT TDevice::CreateSwapChain( HWND hWnd, UINT iWidth, UINT iHeight)
{
HRESULT hr = S_OK;
if( m_pGIFactory == NULL ) return S_FALSE;
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory( &sd, sizeof( sd ) );
sd.BufferCount = 1;
sd.BufferDesc.Width = iWidth;
sd.BufferDesc.Height = iHeight;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = true;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
if( FAILED( hr = m_pGIFactory->CreateSwapChain( m_pd3dDevice, &sd, &m_pSwapChain ) ))
{
return hr;
}
return hr;
}
HRESULT TDevice::SetRenderTargetView()
{
HRESULT hr = S_OK;
// Create a render target view
ID3D11Texture2D* pBackBuffer;
hr = m_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&pBackBuffer );
if( FAILED( hr ) )
return hr;
hr = m_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &m_pRenderTargetView );
pBackBuffer->Release();
if( FAILED( hr ) )
return hr;
m_pImmediateContext->OMSetRenderTargets( 1, &m_pRenderTargetView, NULL );
return S_OK;
}
HRESULT TDevice::SetViewPort()
{
HRESULT hr = S_OK;
DXGI_SWAP_CHAIN_DESC Desc;
m_pSwapChain->GetDesc( &Desc );
// Setup the viewport
m_ViewPort.Width = Desc.BufferDesc.Width;
m_ViewPort.Height = Desc.BufferDesc.Height;
m_ViewPort.MinDepth = 0.0f;
m_ViewPort.MaxDepth = 1.0f;
m_ViewPort.TopLeftX = 0;
m_ViewPort.TopLeftY = 0;
m_pImmediateContext->RSSetViewports( 1, &m_ViewPort );
return S_OK;
}
bool TDevice::CleanupDevice()
{
if( m_pImmediateContext ) m_pImmediateContext->ClearState();
if( m_pRenderTargetView ) m_pRenderTargetView->Release();
if( m_pSwapChain ) m_pSwapChain->Release();
if( m_pImmediateContext ) m_pImmediateContext->Release();
if( m_pd3dDevice ) m_pd3dDevice->Release();
if( m_pGIFactory ) m_pGIFactory->Release();
m_pd3dDevice = NULL;
m_pSwapChain = NULL;
m_pRenderTargetView = NULL;
m_pImmediateContext = NULL;
m_pGIFactory = NULL;
return true;
}
TDevice::TDevice(void)
{
m_driverType = D3D_DRIVER_TYPE_NULL;
m_FeatureLevel = D3D_FEATURE_LEVEL_11_0;
m_pd3dDevice = NULL;
m_pSwapChain = NULL;
m_pRenderTargetView = NULL;
m_pImmediateContext = NULL;
}
TDevice::~TDevice(void)
{
}
//TWindow.h
#pragma once
#include "TDevice.h"
class TWindow : public TDevice
{
public:
//--------------------------------------------------------------------------------------
// Global Variables
//--------------------------------------------------------------------------------------
HINSTANCE m_hInstance; // 인스턴스 핸들
HWND m_hWnd; // 윈도우 핸들
DWORD m_dwWindowStyle; // 윈도우 스타일
RECT m_rcWindowBounds; // 윈도우 영역
RECT m_rcWindowClient; // 클라이언트 영역
UINT m_iWindowWidth; // 클라이언트 영역 가로크기
UINT m_iWindowHeight; // 을라이언트 영역 세로크기
public:
// 윈도우 생성
bool InitWindow( HINSTANCE hInstance, int nCmdShow, TCHAR* strWindowTitle );
// 윈도우 위치 화면 중앙으로 이동
void CenterWindow(HWND hwnd);
public:
virtual bool Init();
virtual bool Frame();
virtual bool Render();
virtual bool Release();
virtual bool Run();
virtual LRESULT WndProc( HWND, UINT, WPARAM, LPARAM );
public:
TWindow(void);
virtual ~TWindow(void);
};
//TWindow.cpp
#include "TWindow.h"
TWindow* g_pWindow = NULL;
//--------------------------------------------------------------------------------------
// 메인 윈도우 프로시져
//--------------------------------------------------------------------------------------
LRESULT CALLBACK StaticWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
assert( g_pWindow );
return g_pWindow->WndProc(hWnd, message, wParam, lParam);
}
//--------------------------------------------------------------------------------------
// 윈도우 프로시져
//--------------------------------------------------------------------------------------
LRESULT TWindow::WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
PAINTSTRUCT ps;
HDC hdc;
switch( message )
{
case WM_DESTROY:
PostQuitMessage( 0 );
break;
}
return DefWindowProc( hWnd, message, wParam, lParam );
}
void TWindow::CenterWindow(HWND hwnd)
{
// 화면 스크린의 해상도(넓이와 높이)을 얻는다.
int iScreenWidth = GetSystemMetrics(SM_CXFULLSCREEN);
int iScreenHeight= GetSystemMetrics(SM_CYFULLSCREEN);
// 윈도우 클라이언트 중앙과 화면 스크린 중앙을 맞춘다.
int iDestX = (iScreenWidth-(m_rcWindowBounds.right-m_rcWindowBounds.left)) / 2;
int iDestY = (iScreenHeight-(m_rcWindowBounds.bottom-m_rcWindowBounds.top)) / 2;
// 윈도우를 화면중앙으로 이동시킨다.
MoveWindow( hwnd, iDestX, iDestY,
m_rcWindowBounds.right -m_rcWindowBounds.left,
m_rcWindowBounds.bottom -m_rcWindowBounds.top,
true);
}
bool TWindow::InitWindow(HINSTANCE hInstance, int nCmdShow, TCHAR* strWindowTitle)
{
// Register class
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = &StaticWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"TBasis3D11_Sample";
wcex.hIconSm = LoadIcon( wcex.hInstance,MAKEINTRESOURCE(IDI_APPLICATION) );
if( !RegisterClassEx( &wcex ) )
return false;
// Create window
m_hInstance = hInstance;
RECT rc = { 0, 0, 800, 600 };
// 작업영역( 타이틀 바/경계선/메뉴/스크롤 바 등의 영역을 제외한 영역), 윈도우 스타일, 메뉴여부
AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
m_hWnd = CreateWindow( L"TBasis3D11_Sample",strWindowTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance,
NULL );
if( !m_hWnd )
return false;
// 윈도우 스타일을 저장하고 스크린 영역과 클라이언트 영역을 얻는다.
m_dwWindowStyle = GetWindowLong( m_hWnd, GWL_STYLE );
GetWindowRect( m_hWnd, &m_rcWindowBounds );
GetClientRect( m_hWnd, &m_rcWindowClient );
CenterWindow(m_hWnd);
UpdateWindow(m_hWnd);
// 윈도우 클라이언트 넓이와 높이를 얻는다.
m_iWindowWidth = m_rcWindowClient.right - m_rcWindowClient.left;
m_iWindowHeight = m_rcWindowClient.bottom-m_rcWindowClient.top;
ShowWindow( m_hWnd, nCmdShow );
return true;
}
bool TWindow::Init()
{
return true;
}
bool TWindow::Frame()
{
return true;
}
bool TWindow::Render()
{
return true;
}
bool TWindow::Release()
{
return true;
}
bool TWindow::Run()
{
if( !Init() ) return false;
// Main message loop
MSG msg = {0};
while( WM_QUIT != msg.message )
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
if( !Frame() || !Render() )
{
break;
}
}
}
if( !Release() ) return false;
return true;
}
TWindow::TWindow(void)
{
m_hInstance = NULL;
m_hWnd = NULL;
g_pWindow = this;
}
TWindow::~TWindow(void)
{
}
//Sample.h
#pragma once
#include "TWindow.h"
class Sample : public TWindow
{
public:
bool Init();
bool Render();
bool Release();
public:
Sample(void);
~Sample(void);
};
//Sample.cpp
//내용들은 Device로 이동하여, Sample 함수 내용물을 비워서 기본구조로 사용
bool Sample::Init()
{
HRESULT hr;
if( FAILED( hr = CreateGIFactory() ))
{
DXTRACE_MSG( DXGetErrorDescription(hr), hr );
return false;
}
if( FAILED( hr = CreateDevice() ))
{
DXTRACE_MSG( DXGetErrorDescription(hr), hr );
return false;
}
if( FAILED( hr = CreateSwapChain(m_hWnd,this->m_iWindowWidth, this->m_iWindowHeight) ) )
{
DXTRACE_MSG( DXGetErrorDescription(hr), hr );
return false;
}
if( FAILED( hr = SetRenderTargetView() ) )
{
DXTRACE_MSG( DXGetErrorDescription(hr), hr );
return false;
}
if( FAILED( hr = SetViewPort() ) )
{
DXTRACE_MSG( DXGetErrorDescription(hr), hr );
return false;
}
return true;
}
bool Sample::Render()
{
DXGI_SWAP_CHAIN_DESC CurrentSD;
m_pSwapChain->GetDesc( &CurrentSD );
GetClientRect( m_hWnd, &m_rcWindowClient );
float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha
m_pImmediateContext->ClearRenderTargetView( m_pRenderTargetView, ClearColor );
m_pSwapChain->Present( 0, 0 );
return true;
}
bool Sample::Release()
{
if( !CleanupDevice() ) return false;
return true;
}
Sample::Sample(void)
{
}
Sample::~Sample(void)
{
}
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
Sample gSample;
if( !gSample.InitWindow( hInstance, nCmdShow, L"CreateDevice_1" ) )
{
MessageBox( 0, _T("Sample 초기화 실패"), _T("Fatal error"), MB_OK );
return 0;
}
ShowCursor ( TRUE );
gSample.Run();
return 1;
}
'DirectX > Project' 카테고리의 다른 글
0. CreateDevice 1 (0) | 2019.05.13 |
---|---|
0. Windows 만들기 (0) | 2019.05.13 |
0. DirectX 사용하기 (0) | 2019.05.13 |