KoreanFoodie's Study
DirectX 11 2D 게임 프로그래밍 - 3, 4. ID3D11Device, SwapChain, Resource View 개념 및 간단한 초기화 본문
Game Dev/DirectX
DirectX 11 2D 게임 프로그래밍 - 3, 4. ID3D11Device, SwapChain, Resource View 개념 및 간단한 초기화
GoldGiver 2021. 10. 23. 06:58
DirectX 11 2D 게임 프로그래밍 - 3. ID3D11Device, SwapChain, Resource View 개념 및 간단한 초기화
Grahpics.h, Graphics.cpp 파일을 이용하여 백버퍼를 만들고 ID3D11Device(Context)등의 파일들을 초기화해 보자.
알아두어야 할 개념 :
1. Device와 DeviceContext, SwapChain 초기화하면서 사용한 옵션 정리 : 주석으로 정리
2. bpc(bit per color), Anti Aliasing
Graphics.h
#pragma once
// final : 더는 상속될 수 없다
class Graphics final
{
public:
Graphics();
~Graphics();
void Initialize();
void CreateBackBuffer(const uint& width, const uint& height);
// -> type : 부분은 생략해도 괜찮다. auto를 쓰는 거는 정렬을 위해 사용...
auto GetDevice() -> ID3D11Device* { return device; }
auto GetDeviceContext() -> ID3D11DeviceContext* { return device_context; }
private:
// 멤버 변수 선언과 동시에 초기화가 가능 : c++ 11 이상 버전부터!
// I가 붙은 녀석들 - COM interface(Component Object Model), 내가 만든 게 아니라 가져다 쓰는 것만 가능 (4개)
// (동적할당 불가능, Release 함수로 메모리 해제해야함)
// COM Interface는 Description을 가진다!
// device : 자원 생성 -> RenderTargetView를 쓰려면 필요...
ID3D11Device* device = nullptr;
// 장치 내용
// Rendering Pipeline에 세팅을 한다!
ID3D11DeviceContext* device_context = nullptr;
// DXGI : DirectX Graphics Infrastructure : 하부구조, 제조사마다 GPU 구조가 다른데, 프로그래머가 편하게 기능을 사용할 수 있게 해 준다.
// SwapChain : 여러 DXGI 객체 중 하나. 두 개의 버퍼를 번갈아 가며 렌더링하여 깜빡임, 찢어짐 현상 방지! (더블 버퍼링) -> 이게 사슬처럼 생김
// 백 버퍼를 관리한다고 보면 편함
// 지지대, 판자 역할. 판자에 끼워지는 녀석이 RenderTargetView
IDXGISwapChain* swap_chain = nullptr;
// RenderTarget 이 도화지라고 보면 된다. View는 ResourceView라는 의미
ID3D11RenderTargetView* render_target_view = nullptr;
// viewport : 어떤 영역에 그릴 것인가. 이미지의 방향이나 위치 등
D3D11_VIEWPORT viewport = { 0 };
// {r, g, b, a} 의 구조체. a는 투명도 정보 (각 타입은 float임 -> 그래서 정규화라는 과정을 거친다.)
// 뭔가 지울 만한 것이 생겼다? -> 같은 색깔로 칠하는 것이 더 빠르다. 그래서 clear라고 이해하자.
// 내부에서 16진수를 처리하는 녀석이 있다. unsigned int 형식임!
// 직관적으로 4바이트임을 잘 알 수 있다.
D3DXCOLOR clear_color = 0xff555566;
};
// Rendering Pipeline : 렌더링을 하기 위해 수행되어야 하는 단계들
// IA - VS - RS - PS - OM
// DirectX - API들의 집합, 그런데 렌더링에 관여를 함
// OpenGL
// GPU
Graphics.cpp
#include "stdafx.h"
#include "Graphics.h"
#include "Window.h"
Graphics::Graphics()
{
}
Graphics::~Graphics()
{
// 먼저 할당된 포인터를 제일 나중에 해제해 주자! (dangling pointer 상황 방지)
SAFE_RELEASE(render_target_view);
SAFE_RELEASE(device);
SAFE_RELEASE(device_context);
SAFE_RELEASE(swap_chain);
}
void Graphics::Initialize()
{
DXGI_SWAP_CHAIN_DESC desc;
ZeroMemory(&desc, sizeof(DXGI_SWAP_CHAIN_DESC));
desc.BufferDesc.Width = 0; // 백버퍼 크기를 잡아줌
desc.BufferDesc.Height = 0;
desc.BufferDesc.RefreshRate.Numerator = 60;
desc.BufferDesc.RefreshRate.Denominator = 1;
// R8.. 하나의 채널에 몇비트 할당할 것인지. RED : 8비트! (0~255)
// UNORM : 정규화된 ... (0~255의 값을 0~1로 오도록 정규화한 것)
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; // 한 라인을 Scanline... Unpecified : 미확인
desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; // 화면이 확대될 때 어떤 효과를 줄 것인지?
desc.BufferCount = 1;
// Aliasing : 계단 현상. Anti-Aliasing을 하는 방법에는 보통 SSA와 MSAA가 있다.
// SSAA : 이미지 하나를 k배로 늘리고 줄인다 + 보정 -> 비용이 커서 잘 안쓰임
// MSAA : 특정 부분(예 : 외각선)만 처리해서 상대적으로 저렴함.
// MSAA 에서 샘플링을 어떻게 할 것인가, 변수를 결정.
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.OutputWindow = Window::global_handle;
desc.Windowed = TRUE;
// 더블 버퍼링할 때 잉여 버퍼를 어떻게 할지..? DISCARD : 폐기!
desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
std::vector<D3D_FEATURE_LEVEL> feature_levels
{
//D3D_FEATURE_LEVEL_11_1, // Undefined... Maybe deprecated?
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
};
// Device, Device Context, SwapChain까지 한꺼번에 만들 수 있다.
// return type이 HRESULT임. HRESULT는 함수의 결과가 성공했는지 실패했는지의 정보를 담고 있다.
auto hr = D3D11CreateDeviceAndSwapChain
(
nullptr,
D3D_DRIVER_TYPE_HARDWARE, // 하드웨어 가속을 사용할 수 있게 해준다.
nullptr,
0, // 어떤 API를 사용할 것인지
feature_levels.data(), // &feature_levels[0] 와 같다. 첫 시작 지점의 포인터를 반환
feature_levels.size(),
D3D11_SDK_VERSION,
&desc,
&swap_chain,
&device,
nullptr,
&device_context
);
// 함수의 결과가 성공했는지 실패했는지의 정보를 받아 assert
assert(SUCCEEDED(hr));
}
void Graphics::CreateBackBuffer(const uint& width, const uint& height)
{
auto hr = swap_chain->ResizeBuffers
(
0, // ResizeBuffers 함수에는 초기값다 다른, 변형할 값만 넣어주면 된다.
width,
height,
DXGI_FORMAT_UNKNOWN, // 포맷을 모르겠다... (위에 정의된 기본 값 사용)
0
);
assert(SUCCEEDED(hr));
// ID3D11SwapChain을 통해서 BackBuffer 정보를 얻어낼 수 있다
ID3D11Texture2D* back_buffer = nullptr;
hr = swap_chain->GetBuffer
(
0,
// UUID : Universally Unique ID GUID : Globally Unique ID
// ID3D11Texture2D의 정의로 가보면, MIDL_INTERFACE("6f15aaf2-d208-4e89-9ab4-489535d34f9c") 가 UID에 해당한다!
// UUID, GUID 는 중복될 경우가 없기에 고유 ID라고도 부른다 (MS에서 GUID 사용, 전역적으로는 UUID 사용)
__uuidof(ID3D11Texture2D), //IID_ID3D11Texture2D, // IID : Interface Identifier
reinterpret_cast<void**>(&back_buffer)
);
assert(SUCCEEDED(hr));
hr = device->CreateRenderTargetView
(
back_buffer,
nullptr,
&render_target_view
);
assert(SUCCEEDED(hr));
// 시작점
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
viewport.Width = static_cast<float>(width);
viewport.Height = static_cast<float>(height);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
// delete말고, Release()함수를 이용해서 메모리 해제를 해 주어야 한다!
SAFE_RELEASE(back_buffer);
}
// ID3D11Resource
// 모든 ID3D11은 이 Resource 녀석을 상속 받는다. (Buffer와 Texture로 나뉨)
// ID3D11Buffer : 구조체를 만들어 넘기는 자원(Buffer) ID3D11Texture1D, ID3D11Texture2D, ID3D11Texture3D : 이미지화된 자원(Texture)
// // Resource View : Texture 자원의 사용 용도를 명확히 해주는 개념
// - ID3D11RenderTargetView(화면 그리기), ID3D11ShaderResourceView(이미 만들어진 이미지 넘기기), ID3D11DepthStencilView(깊이 관련...), ID3D11UnorderedAccessView(읽고 쓰기가 다 된다)
더 자세한 내용이 궁금하시다면 직접 들어보시는 걸 추천드립니다!
'Game Dev > DirectX' 카테고리의 다른 글
DirectX 11 2D 게임 프로그래밍 - 7. Vertex Shader Stage (0) | 2021.10.25 |
---|---|
DirectX 11 2D 게임 프로그래밍 - 6. Input Assembler Stage 세팅하기 (0) | 2021.10.24 |
DirectX 11 2D 게임 프로그래밍 - 5. Window 창에 DirectX 연결(연동)하기 (0) | 2021.10.24 |
DirectX 11 2D 게임 프로그래밍 - 2. Direct SDK 연결, Double Buffering (0) | 2021.10.22 |
DirectX 11 2D 게임 프로그래밍 - 1. Window 창 띄우기, Calling Convention, Casting, inline (0) | 2021.10.22 |
Comments