코드를 보다보니, 윈도우 함수를 초기화하면서 윈도우 크기를 설정을 안해놓은 것을 확인했다..
그래서 먼저 윈도우 크기 설정부터 추가하였다.
Init함수는 윈도우 크기 인자를 추가로 받도록 해주었다.
Init함수 내부에선 이 크기를 멤버변수에 저장해주었다.
이후, CreateWindow할 때, 윈도우의 크기를 세팅해주었다.
이제, DirectX를 초기화해보자.
먼저, Init함수 내부를 조금 수정해주었다.
BOOL EngineBase::Init(HINSTANCE _hInstance, int _Width, int _Height)
{
WindowWidth = _Width;
WindowHeight = _Height;
if (!WindowInit(_hInstance))
{
return FALSE;
}
if (!DirectXInit())
{
return FALSE;
}
return TRUE;
}
이렇게, Window초기화와 DirectX초기화를 나누어주었다.
BOOL EngineBase::DirectXInit()
{
if (!CreateDevice())
{
std::cout << "CreateDevice() is Failed!" << std::endl;
return FALSE;
}
if (!CreateSwapChain())
{
std::cout << "CreateSwapChain() is Failed!" << std::endl;
return FALSE;
}
if (!CreateRasterizerState())
{
std::cout << "CreateRasterizerState() is Failed!" << std::endl;
return FALSE;
}
if (!CreateDepthStencil())
{
std::cout << "CreateDepthStencil() is Failed!" << std::endl;
return FALSE;
}
SetViewport();
return TRUE;
}
DirectXInit함수 내부에서도 만들어야 하는 것들을 구분해서 만들도록 하였다.
BOOL EngineBase::CreateDevice()
{
//하드웨어 드라이버를 사용할건가 소프트웨어 드라이버를 사용할건가
const D3D_DRIVER_TYPE DriverType = D3D_DRIVER_TYPE_HARDWARE;
//디버그 기능을 사용할 것인가
UINT CreateDeviceFlags = 0;
#if defined(DEBUG) || defined(_DEBUG)
CreateDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
//다이렉트X의 버전 목록 (만약 컴퓨터에 버전이 없다면, 더 낮은 버전으로 Device 생성을 시도
const D3D_FEATURE_LEVEL featureLevels[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_9_3 };
//생성된 Device의 다이렉트X 버전을 저장
D3D_FEATURE_LEVEL featureLevel;
HRESULT Result = D3D11CreateDevice(
nullptr, // nullptr이면 기본 어댑터를 사용
DriverType, // 어떤 드라이버를 사용하여 Device를 만들 것인가
0, // 소프트웨어 드라이버를 사용할 것이라면, 어떤걸 사용할지 선택하는 옵션인듯
CreateDeviceFlags, // 플래그
featureLevels, // 다이렉트X 버전 목록 배열
ARRAYSIZE(featureLevels), // 위의 배열의 사이즈
D3D11_SDK_VERSION, // 무조건 D3D11_SDK_VERSION 쓰라고 써있네
&Device, // 생성된 디바이스를 저장
&featureLevel, // 생성된 디바이스의 DirectX 버전을 저장
&Context // 생성된 디바이스의 Context를 저장
);
if (Result != S_OK)
{
return FALSE;
}
return TRUE;
}
CreateDevice함수는 위와 같다.
Device가 무사히 생성되었다면, TRUE를 리턴할 것이다.
다음은 SwapChain을 만들어보자.
BOOL EngineBase::CreateSwapChain()
{
HRESULT Result = S_OK;
Microsoft::WRL::ComPtr<IDXGIDevice> DXGIDevice;
Result = Device.As(&DXGIDevice);
Microsoft::WRL::ComPtr<IDXGIAdapter> DXGIAdapter;
Result = DXGIDevice->GetAdapter(&DXGIAdapter);
Microsoft::WRL::ComPtr<IDXGIFactory> DXGIFactory;
Result = DXGIAdapter->GetParent(IID_PPV_ARGS(&DXGIFactory));
SwapChain.Reset();
//멀티샘플링 안티에일리어싱 (MSAA)
UINT numQualityLevels;
Device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 4, &numQualityLevels);
if (numQualityLevels <= 0)
{
std::cout << "MSAA not supported!" << std::endl;
}
DXGI_SWAP_CHAIN_DESC SD;
ZeroMemory(&SD, sizeof(SD));
SD.BufferDesc.Width = (UINT)WindowWidth; // 백버퍼 사이즈 (너비)
SD.BufferDesc.Height = (UINT)WindowHeight; // 백버퍼 사이즈 (높이)
SD.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // 색상 포맷
SD.BufferCount = 2; // 백버퍼 개수
SD.BufferDesc.RefreshRate.Numerator = 60; // 갱신률 (분자)
SD.BufferDesc.RefreshRate.Denominator = 1; // 갱신률 (분모)
SD.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // 스왑체인을 어떻게 쓸 것인가
SD.OutputWindow = hWnd; // 스왑체인이 사용될 윈도우
SD.Windowed = TRUE; // 창모드, 전체모드
SD.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // 창모드, 전체모드 전환을 허용할 것인가
SD.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
SD.SampleDesc.Count = 4;
SD.SampleDesc.Quality = numQualityLevels - 1;
Result = DXGIFactory->CreateSwapChain(Device.Get(), &SD, SwapChain.GetAddressOf());
if (Result != S_OK)
{
return FALSE;
}
//백버퍼의 렌더타겟 뷰 생성
ID3D11Texture2D* BackBuffer;
SwapChain->GetBuffer(0, IID_PPV_ARGS(&BackBuffer));
if (BackBuffer)
{
Device->CreateRenderTargetView(BackBuffer, NULL, &RenderTargetView);
BackBuffer->Release();
}
else
{
std::cout << "CreateRenderTargetView() failed!" << std::endl;
return FALSE;
}
return TRUE;
}
스왑체인을 만들면서, 멀티샘플링 설정도 해주었다.
뭔가 길고 복잡해보이지만, 그냥 원하는대로 설정하면 된다.
안에 보면, BackBuffer의 경우엔 Release를 호출해주고 있는데, BackBuffer는 Comptr을 사용해서 선언한 것이 아니라 직접 Release를 호출해주어야 한다.
Comptr로 선언한 애들은 프로세스가 종료될 때 알아서 해제해준다.
BOOL EngineBase::CreateRasterizerState()
{
D3D11_RASTERIZER_DESC RD;
ZeroMemory(&RD, sizeof(D3D11_RASTERIZER_DESC));
RD.FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID;
RD.CullMode = D3D11_CULL_MODE::D3D11_CULL_BACK;
RD.FrontCounterClockwise = false;
HRESULT Result = Device->CreateRasterizerState(&RD, &RasterizerState);
if (Result != S_OK)
{
return FALSE;
}
return TRUE;
}
RasterizerState도 만들어주었다.
후면 컬링도 설정해주었다.
BOOL EngineBase::CreateDepthStencil()
{
D3D11_TEXTURE2D_DESC DepthStencilBufferDesc;
DepthStencilBufferDesc.Width = WindowWidth;
DepthStencilBufferDesc.Height = WindowHeight;
DepthStencilBufferDesc.MipLevels = 1;
DepthStencilBufferDesc.ArraySize = 1;
DepthStencilBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
if (NumQualityLevels > 0)
{
DepthStencilBufferDesc.SampleDesc.Count = 4;
DepthStencilBufferDesc.SampleDesc.Quality = NumQualityLevels - 1;
}
else
{
DepthStencilBufferDesc.SampleDesc.Count = 1;
DepthStencilBufferDesc.SampleDesc.Quality = 0;
}
DepthStencilBufferDesc.Usage = D3D11_USAGE_DEFAULT;
DepthStencilBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
DepthStencilBufferDesc.CPUAccessFlags = 0;
DepthStencilBufferDesc.MiscFlags = 0;
HRESULT Result = Device->CreateTexture2D(&DepthStencilBufferDesc, 0, DepthStencilBuffer.GetAddressOf());
if (Result != S_OK)
{
return FALSE;
}
Result = Device->CreateDepthStencilView(DepthStencilBuffer.Get(), 0, &DepthStencilView);
if (Result != S_OK)
{
return FALSE;
}
D3D11_DEPTH_STENCIL_DESC DepthStencilDesc;
ZeroMemory(&DepthStencilDesc, sizeof(D3D11_DEPTH_STENCIL_DESC));
DepthStencilDesc.DepthEnable = true;
DepthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK::D3D11_DEPTH_WRITE_MASK_ALL;
DepthStencilDesc.DepthFunc = D3D11_COMPARISON_FUNC::D3D11_COMPARISON_LESS_EQUAL;
Result = Device->CreateDepthStencilState(&DepthStencilDesc, DepthStencilState.GetAddressOf());
if (Result != S_OK)
{
return FALSE;
}
return TRUE;
}
뎁스스텐실 버퍼와 뎁스스텐실 뷰도 생성해보았다.
void EngineBase::SetViewport()
{
ZeroMemory(&ScreenViewPort, sizeof(D3D11_VIEWPORT));
ScreenViewPort.TopLeftX = 0;
ScreenViewPort.TopLeftY = 0;
ScreenViewPort.Width = float(WindowWidth);
ScreenViewPort.Height = float(WindowHeight);
ScreenViewPort.MinDepth = 0.0f;
ScreenViewPort.MaxDepth = 1.0f;
Context->RSSetViewports(1, &ScreenViewPort);
}
마지막으로, 뷰포트 세팅까지 해주면서, 기본적인 초기화는 얼추 끝났다..
'프로젝트 > Direct X 그래픽스' 카테고리의 다른 글
프로젝트 : DirectX를 활용한 그래픽스 (6 - 버텍스 쉐이더, 인풋 레이아웃, 픽셀 쉐이더) (1) | 2024.05.01 |
---|---|
프로젝트 : DirectX를 활용한 그래픽스 (5 - 상수 버퍼) (0) | 2024.05.01 |
프로젝트 : DirectX를 활용한 그래픽스(4 - 릭 제거) (0) | 2024.05.01 |
프로젝트 : DirectX를 활용한 그래픽스 (3 - 버텍스 버퍼, 인덱스 버퍼) (0) | 2024.05.01 |
프로젝트 : DirectX를 활용한 그래픽스 (1 - 윈도우 초기화) (0) | 2024.04.30 |