• Home
  • About
    • 게임 개발자 유정룡 photo

      게임 개발자 유정룡

      포트폴리오

    • Learn More
    • Email
    • Github
    • Bitbucket
  • Projects
    • All Projects
    • All Tags

DirectX11 공부 1일차(세팅 ~ 초기화)

01 Jun 2021

Reading time ~4 minutes

배운것

  1. 기본적인 세팅 (헤더 및 라이브러리)
  2. 초기화 (DirectX의 랜더링에 관한 변수들 초기화)

기본적인 세팅

c++에 헤더와 라이브러리 추가하는것은 처음 해봤음 일단 프로젝트 설정에 들어가 추가 해줌

그 뒤,

// DirectX
#include <d3dcompiler.h>
#include <d3d11.h>
#include <D3DX10math.h>

#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dcompiler.lib")

DirectX에 관한 헤더 파일과 라이브러리 프로젝트에 추가 완료

#pragma comment(lib, “.lib”)를 사용한 이유는 나중에 이 프로젝트를 다른곳에 사용할때 프로젝트 설정에서 추가해야 하는 번거로움을 막기 위함

초기화

Graphics.h

class Graphics final
{
public:
	Graphics();
	~Graphics();

	void Initialize();
	void CreateBackBuffer(const uint& width, const uint& height);

	ID3D11Device* GetDevice() { return device; }
	ID3D11DeviceContext* GetDeviceContext() { return device_context; }

private:
	ID3D11Device* device = nullptr;							// 자원 생성
	ID3D11DeviceContext* device_context	= nullptr;			// 장치 내용, 파이프라인에 세팅
	IDXGISwapChain* swap_chain = nullptr;					// 백버퍼 관리
	ID3D11RenderTargetView* render_target_view = nullptr;	// 그릴 도화지
	D3D11_VIEWPORT viewport	= { 0 };				        
	D3DXCOLOR clear_color = 0xff555566;						// 지우는 역할
};

변수 타입에 I가 붙어있으면 (ex ID3D11Device) Comterface로 직접 생성하는 것이 아는 요청해서 변수 설정해야 됨

변수 타입에 DXGI가 붙어있으면 그래픽 카드의 하부구조와 연결 되어있음

변수

ID3D11Device 인터페이스는 장치로써 기능 지원 점검과 자원 할당에 사용.

ID3D11DeviceContext 인터페이스는 문맥으로써 랜더 대상을 성정하고, 자원을 그래픽 파이프라인에 묶고, GPU가 수행할 랜더링 명령들을 지시하는데 사용

/*

ID3D11Device 인스턴스로 장면에서의 그래픽을 처리하는 GPU 자원으로 구성하고 획득하며, ID3D11DeviceContext로 그래픽 파이프라인에서의 적절한 쉐이더 단계에서 자원들을 처리한다.

ID3D11Device 메소드는 씬을 setup하거나 device가 바뀔때 호출되지만 ID3D11DeviceContext는 매 프레임마다 호출한다.

Device는 독립성을 완벽하게 갖고있는것

DeviceContext는 Device에 대한 각종 정보를 담고 있는 구조체

*/

IDXGISwapChain 인터페이스는 화면을 표시하는 스왑체인 기능 백버퍼 관리를 위해 사용

ID3D11RenderTargetView 인터페이스는 랜더링 파이프라인에서 출력을 할 자원

D3D11_VIEWPORT 뷰포트 랜더링할 대상의 화면 영역

D3DXCOLOR 색상 값이다. 여기서 사용하는 이유는 화면을 지우기 위해 색상값 지정함.

함수

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;
	desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
	desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
	desc.BufferCount = 1;
	desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	desc.SampleDesc.Count = 1;
	desc.SampleDesc.Quality = 0;
	desc.OutputWindow = Window::global_handle;
	desc.Windowed = TRUE;
	desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

	std::vector<D3D_FEATURE_LEVEL> feature_levels
	{
		D3D_FEATURE_LEVEL_11_1,
		D3D_FEATURE_LEVEL_11_0,
		D3D_FEATURE_LEVEL_10_1,
		D3D_FEATURE_LEVEL_10_0
	};

	HRESULT hr = D3D11CreateDeviceAndSwapChain
	(
		nullptr,
		D3D_DRIVER_TYPE_HARDWARE,
		nullptr,
		0,
		feature_levels.data(),
		feature_levels.size(),
		D3D11_SDK_VERSION,
		&desc,
		&swap_chain,
		&device,
		nullptr,
		&device_context
	);
	assert(SUCCEEDED(hr));	
  • HRESULT 이는 32비트의 signed형 정수이며 COM의 규정에 정의된 것은 아니지만 COM 인터페이스에 소속된 대부분의 함수들은 HRESULT형태의 반환값을 가짐

    BOOL과 비슷하지만 BOOL 은 TRUE / FALSE : 1 /0 인데 반해

    HRESULT는 SUCCEEDED / FALSE : 0 / 1 의 값을 갖고있음

    또한 반환형이 HRESULT라고 해서 반드시 값을 리턴받지는 않아도 됨.

DXGI_SWAP_CHAIN_DESC
typedef struct DXGI_SWAP_CHAIN_DESC
{
    DXGI_MODE_DESC BufferDesc;     // 생성하고자 하는 back buffer의 속성들을 서술하는 구조체
    DXGI_SAMPLE_DESC SampleDesc;   // Multisampling을 위해 추출할 표본 개수와 품질 수준을 서술하는 구조체
    DXGI_USAGE BufferUsage;        // 버퍼의 용도를 서술하는 구조체
    UINT BufferCount;              // Swap chain에서 사용할 back buffer의 개수.(이중버퍼링 : 1개, 삼중버퍼링 : 2개)
    HWND OutputWindow;             // 렌더링 결과를 표시할 윈도우 창의 핸들
    BOOL Windowed;                 // 창 모드를 원하면 true, 전체화면 모드를 원하면 false
    DXGI_SWAP_EFFECT SwapEffect;   // Swap 효과를 서술하는 구조체
    UINT Flags;                    // 추가적인 플래그
} DXGI_SWAP_CHAIN_DESC;

로 만들어져 있으며

안에 있는 DXGI_MODE_DESC 는

typedef struct DXGI_MODE_DESC
{
    UINT Width;                                // 원하는 back buffer 너비
    UINT Height;                               // 원하는 back buffer 높이
    DXGI_RATIONAL RefreshRate                  // 디스플레이 모드 갱신율
    DXGI_FORMAT Format;                        // back buffer 픽셀 형식
    DXGI_MODE_SCANLINE_ORDER ScanlineOrdering; // 디스플레이 스캔라인 모드
    DXGI_MODE_SCALING Scaling;                 // 디스플레이 비례 모드
} DXGI_MODE_DESC;

로 되어있다.

처음에 DXGI_SWAP_CHAIN_DESC desc 을 초기화 해주고,

feature_levels 을 초기화 해준다(최신버전순서)

그 뒤에 D3D11CreateDeviceAndSwapChain 을 호출하여 장치와 스왑 체인을 동시에 초기화 해준다.(생성)

HRESULT hr = D3D11CreateDeviceAndSwapChain
	(
		nullptr,                    // 
		D3D_DRIVER_TYPE_HARDWARE,   // 드라이버 타입
		nullptr,                    // 
		0,                          // 디바이스 플래스
		feature_levels.data(),      // 피처레벨 배열
		feature_levels.size(),      // 피처레벨 카운트
		D3D11_SDK_VERSION,          // SDK 버전
		&desc,                      // 스왑 체인 생성 구조체
		&swap_chain,                // 생성된 스왑체인 객체
		&device,                    // 생성된 디바이스 정보
		nullptr,                    // 생성된 치퍼레벨 정보
		&device_context             // 생성된 디바이스 컨텍스트 캑체
	);

이 함수에 자세히 알고싶으면 클릭

CreateBackBuffer(const uint& width, const uint& height)

HRESULT hr = swap_chain->ResizeBuffers
	(
		0,
		width,
		height,
		DXGI_FORMAT_UNKNOWN,
		0
	);

백버퍼 사이즈 갱신

(스왑 체인의 백 버퍼 크기, 형식 및 버퍼 수를 변경합니다. 응용 프로그램 창 크기를 조정할 때 호출해야합니다.)

ID3D11Texture2D* back_buffer = nullptr;
hr = swap_chain->GetBuffer
(
	0,
	__uuidof(ID3D11Texture2D), //IID_ID3D11Texture2D, 와 같음
	reinterpret_cast<void**>(back_buffer)
);

스왑 체인의 백 버퍼 중 하나에 액세스한다.

그 뒤에

hr = device->CreateRenderTargetView
(
	back_buffer,
	nullptr,
	&render_target_view
);

백 버퍼 포인터로 렌더 타겟뷰를 생성

그 뒤에

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;

뷰 포트를 성정해줌! 마지막으로

SAFE_RELEASE(back_buffer);

백버퍼 해제

/*

// Macro Function
#define SAFE_DELETE(p)		{ if(p) { delete (p); p = nullptr; }}
#define SAFE_DELTE_ARRAY(p) { if (p) { delete[] (p); p = nullptr; }}
#define SAFE_RELEASE(p)		{ if(p) { (p)->Release(); (p) = nullptr; }}

*/

따로 매크로 함수 만들어 사용함.

큰틀

디바이스 생성 -> SwapChain 생성 -> 백버퍼 생성



DirectX Share Tweet +1