1. 더블 버퍼링 (Double Buffering)

프론트 버퍼 하나로 그래픽을 표현하면 잔상, 혹은 이미지가 갱신되지 않는 문제, 입력이 지연되는 문제가 발생한다.

이 문제를 해결하기 위해 백 버퍼(Back buffer)를 추가하여 출력하는 더블 버퍼링이 생기게 되었다.

그래픽 출력 순서는 아래와 같다.

 

1) 프론트 버퍼에 그림

2) 백 버퍼에 그림을 복사 ; 이 과정에서 그림이 그려지는 과정이 숨겨지게 된다(잔상 방지)

3) 프론트 버퍼와 백 버퍼를 서로 교체

4) 프론트 버퍼의 내용을 화면에 표시

5) 백 버퍼에 그림

6) 프론트 버퍼에 그림을 복사 ...

 

 

2. Game.h, Game.cpp

기존의 _hdc가 프론트 버퍼에 해당한다.

private:
	RECT _rect;
    // 백 버퍼 추가
	HDC _hdcBack = {};
	HBITMAP _bmpBack = {};
}

 

1) 비트맵과 DC

- DC(Device Context) ; 그래픽 디바이스 정보와 그림을 그리는 영역이 저장되어 있음.

- 비트맵(Bitmap) ; 메모리에 생성되는 이미지 또는 그림(픽셀 단위로 표현되어 저장).

 

1-2) 비트맵 표시 절차

(1) 메모리에 비트맵 할당

(2) DC 생성, 비트맵과 DC 연결

(3) 비트맵을 DC 위에 그림

(4) 화면에 표시

void Game::Init(HWND hwnd)
{
	_hwnd = hwnd;
	_hdc = ::GetDC(hwnd);

	::GetClientRect(hwnd, &_rect);

	_hdcBack = ::CreateCompatibleDC(_hdc); // _hdc와 호환되는 DC를 생성
	_bmpBack = ::CreateCompatibleBitmap(_hdc, _rect.right, _rect.bottom); // _hdc와 호환되는 비트맵 생성
	HBITMAP prev = (HBITMAP)::SelectObject(_hdcBack, _bmpBack); // DC와 비트맵 연결
	::DeleteObject(prev);
void Game::Render()
{
	uint32 fps = GET_SINGLE(TimeManager)->GetFps();
	float deltaTime = GET_SINGLE(TimeManager)->GetDeltaTime();


	{ // 마우스 위치 출력
		POINT mousePos = GET_SINGLE(InputManager)->GetMousePos();
		wstring str = std::format(L"Mouse({0}, {1})", mousePos.x, mousePos.y);
		::TextOut(_hdcBack, 20, 10, str.c_str(), static_cast<int32>(str.size()));
	}

	{ // FPS, Delta Time 출력
		wstring str = std::format(L"FPS({0}), DT({1} ms)", fps, static_cast<int32>(deltaTime * 1000));
		::TextOut(_hdcBack, 650, 10, str.c_str(), static_cast<int32>(str.size()));
	}

	// 액터 출력
	GET_SINGLE(SceneManager)->Render(_hdcBack);

	// 더블 버퍼링, 비트 블릿 ; 고속 복사
	::BitBlt(_hdc, 0, 0, _rect.right, _rect.bottom, _hdcBack, 0, 0, SRCCOPY);

	// 복사 이후 백 버퍼 클리어
	::PatBlt(_hdcBack, 0, 0, _rect.right, _rect.bottom, WHITENESS);
}

먼저 _hdcBack으로 명명되어 있는 백버퍼에 렌더링하고 프론트 버퍼인 _hdc로 넘겨줄 것이다.

기존에 마우스 위치와 FPS, Delta Time을 _hdc에 그리고 있었던 것을 _hdcBack으로 수정한다.

이후에 비트블릿 함수를 사용하여 백버퍼를 프론트버퍼에 고속 복사한다.

복사 이후에 백 버퍼를 클리어한다.