int Device::Init(HWND _hWnd, POINT _vResolution)
{
m_vRenderResolution = _vResolution;
m_hRenderWnd = _hWnd;
// 장치 초기화
D3D_FEATURE_LEVEL eLevel = D3D_FEATURE_LEVEL_11_0;
if (FAILED(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr,
D3D11_CREATE_DEVICE_DEBUG, nullptr, 0, D3D11_SDK_VERSION,
m_Device.GetAddressOf(), &eLevel, m_Context.GetAddressOf())))
{
return E_FAIL;
}
// 스왑 체인 생성
if (FAILED(CreateSwapChain()))
{
return E_FAIL;
}
// 렌더 타켓 뷰
if (FAILED(CreateTargetView()))
{
return E_FAIL;
}
return S_OK;
}
※ DXGI(DirectX Graphics Infrastructure)
: 그래픽 카드를 운영체제에서 추상화 해줄 때 드라이버와 이 DXGI 객체를 통해 추상화해준다.
int Device::CreateSwapChain()
{
// SwapChain 생성 구조체
DXGI_SWAP_CHAIN_DESC tDesc = {};
// SwapChain 이 관리하는 Buffer(RenderTarget) 의 구성 정보
tDesc.BufferCount = 1;
tDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
tDesc.BufferDesc.Width = (UINT)m_vRenderResolution.x;
tDesc.BufferDesc.Height = (UINT)m_vRenderResolution.y;
tDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // buffer에 pixle format
tDesc.BufferDesc.RefreshRate.Denominator = 1; // 분모 1
tDesc.BufferDesc.RefreshRate.Numerator = 60; // 분자 60
tDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
tDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
tDesc.Flags = 0;
tDesc.SampleDesc.Count = 1;
tDesc.SampleDesc.Quality = 0;
tDesc.Windowed = true; // 창모드
tDesc.OutputWindow = m_hRenderWnd; // swapchain 출력 윈도우 지정
// swapchain을 생성시키는 객체 생성
IDXGIDevice* pIdxgiDevice = nullptr;
IDXGIAdapter* pAdapter = nullptr;
IDXGIFactory* pFactory = nullptr;
m_Device->QueryInterface(__uuidof(IDXGIDevice), (void**)&pIdxgiDevice);
pIdxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&pAdapter);
pAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&pFactory);
pIdxgiDevice->Release();
pAdapter->Release();
pFactory->Release();
// 스왑 체인 생성
if(FAILED(pFactory->CreateSwapChain(m_Device.Get(), &tDesc, m_SwapChain.GetAddressOf())))
{
return E_FAIL;
}
return S_OK;
}
※ View 객체는 DX resource(texture,buffer)를 가리키고 있는 객체라 생각하면 된다.
DX에서는 resource들이 각자의 역할을 가지고 있는데 resource를 사용하는 곳에서 그 사용처에 맞지 않은 객체를 사용하는것(resource는 다 같은 타입이기때문에)를 방지하기 위해 resource가 아닌 resource를 가리키고 있는 View 객체를 호출한다.
View 객체에 대한 texture가 오류를 내지 않았다면, View 객체는 왠만하면 오류를 내지 않는다!
// 렌더타켓 텍스쳐를 스왑체인으로 부터 얻어온다.
// 스왑 체인을 보면 버퍼를 생성했음( 스왑 체인이 관리하는 렌더 텍스쳐가 생성됨(옛날에 DC로 생성한 bitmap이라 생각하면됨 )
// 해당 버퍼는 GPU안에 있는 메모리에 적재됨 예전 API 프로젝트 같은 경우 RAM에 저장되었는데
// GPU 상에 존재하는 리소스를 관리해주는 역할을 함
// ID3D11Resource(부모 클래스) 자식 - > buffer , texture2d 등이 있음
// swapchain으로 부터 만들어진 buffer resource를 가리키기 위해 사용함
if (FAILED(m_SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)m_RTTex.GetAddressOf())))
{
return E_FAIL;
}
// RenderTargetView
// DepthStencilView texture는 없음
// ShaderResourceView
// UnorderedAccessView
// 리소스 객체를 이용해서 중간에 view가 생성됨 리소스가 필요한 곳은 view를 달라함
// 이유 : 텍스터를 하나 만들때도 용도가 정해져있음 즉, 그 용도에 맞는 view를 달라해야 그 용도에 맞게 가져올 수 있음
// 이유는 해당 리소스 뷰는 그 리소스로 밖에 생성하지 못하기 때문
// 하지만 예외로 용도에 맞는 뷰를 만들 수 있는 리소스 객체도 있음
// rendertargettview : 그림이 그려질 곳(rendertarget texture를 가리키고 있음)
// shaderview : 저장해놓고 그림을 그릴곳에 복사할 원본
// 왠만하면 해당 함수는 실패할 일이 없음 그 전에 texture가 오류가 날 수는 있지만
// 그 전에 함수 역시 swapchain이 오류를 내지 해당 함수는 오류를 낼 경우가 없음
if (FAILED(m_Device->CreateRenderTargetView(m_RTTex.Get(), nullptr, m_RTView.GetAddressOf())))
{
return E_FAIL;
}
// DepthStencilTexture
// pixel 하나당 4바이트
// 4바이트는 깊이를 저장한 것
// 1바이트는 stencil 정보를 저장한 것
D3D11_TEXTURE2D_DESC Desc = {};
Desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
// DepthStencilState 텍스쳐 해상도는 반드시 RenderTargetTexture와 동일해야한다.
Desc.Width = (UINT)m_vRenderResolution.x;
Desc.Height = (UINT)m_vRenderResolution.y;
// 깊이를 저장하는 texture다라고 용도를 정해주는것
Desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
// GPU 메모리를 사용하여 만들어진다고 했으나,
// CPU (주메모리)와 연락을 위한 flag
Desc.CPUAccessFlags = 0;
Desc.Usage = D3D11_USAGE_DEFAULT;
// 샘플링은 고정
Desc.SampleDesc.Count = 1;
Desc.SampleDesc.Quality = 0;
// 저퀄리티 버전의 사본 샘플
// 원본에 해상도를 점점 낮추는것
// 거리에 따른 해상도에 활용함
Desc.MipLevels = 1;
Desc.MiscFlags = 0;
Desc.ArraySize = 1;
if (FAILED(m_Device->CreateTexture2D(&Desc, nullptr, m_DSTex.GetAddressOf())))
{
return E_FAIL;
}
// DepthStencilView
if (FAILED(m_Device->CreateDepthStencilView(m_DSTex.Get(), nullptr, m_DSView.GetAddressOf())))
{
return E_FAIL;
}