1. 더블 버퍼링 기초

a. 더블 버퍼링이란?

  1. 목적:

    • 화면 갱신 시 발생할 수 있는 깜빡임을 줄이고 부드럽고 끊김 없는 화면 표시를 가능하게 함.
    • 깜빡임 문제는 화면에 바로 그리기를 반복할 때 발생하는데, 이는 화면 갱신과 렌더링 사이의 불일치 때문.
  2. 사용처:

    • 컴퓨터 게임, 애니메이션, 복잡한 그래픽 작업 등.
    • CPU 또는 GPU 가속과 결합되어 성능 최적화.

b. 진행 과정

  • 두 개의 메모리 영역(버퍼)을 사용:
    1. 프론트 버퍼: 화면에 출력되는 버퍼.
    2. 백 버퍼: 새롭게 그려질 내용을 준비하는 버퍼.
  • 작업 흐름:
    • 백 버퍼에 그림을 그린 뒤, 백 버퍼와 프론트 버퍼를 교환.
    • 빠르게 교환하여 끊김 없는 화면 전환.

2. 더블 버퍼링 구현


a. Game 클래스 설계

파일: Game.h

#pragma once
class Game
{
public:
	Game();
	~Game();

public: 
	void Init(HWND hwnd);
	void Update();
	void Render();

private:
	HWND _hwnd = {};   // 윈도우 핸들
	HDC _hdc = {};     // 기본 디바이스 컨텍스트

private:
	// 더블 버퍼링 관련 변수
	RECT _rect;        // 현재 그리는 영역의 범위
	HDC _hdcBack = {}; // 백 버퍼 디바이스 컨텍스트
	HBITMAP _bmpBack = {}; // 백 버퍼 비트맵 (화면 데이터 저장)
};

분석:
1. HDCHBITMAP:

  • HDC (Device Context): 출력 장치와의 인터페이스.
  • HBITMAP: 이미지 데이터를 저장하는 객체.
  1. 더블 버퍼링:
    • _hdcBack: 백 버퍼에서 그림을 그리는 용도.
    • _bmpBack: 백 버퍼와 연결된 비트맵.

b. Game 초기화

파일: Game.cpp

void Game::Init(HWND hwnd)
{
	_hwnd = hwnd;
	_hdc = ::GetDC(hwnd); // 윈도우 DC 얻기

	// 더블 버퍼링 초기화
	::GetClientRect(hwnd, &_rect); // 클라이언트 영역 크기 얻기

	_hdcBack = ::CreateCompatibleDC(_hdc); // _hdc와 호환되는 DC 생성
	_bmpBack = ::CreateCompatibleBitmap(_hdc, _rect.right, _rect.bottom); // _hdc와 호환되는 비트맵 생성
	HBITMAP prev = (HBITMAP)::SelectObject(_hdcBack, _bmpBack); // _hdcBack과 비트맵 연결
	::DeleteObject(prev); // 이전 비트맵 객체 삭제
}

분석:
1. DC 생성:

  • CreateCompatibleDC: 기존 HDC와 호환되는 새로운 HDC 생성.
  1. 비트맵 생성:
    • CreateCompatibleBitmap: 특정 HDC와 동일한 포맷의 비트맵 생성.
  2. 비트맵 연결:
    • SelectObject: DC에 비트맵을 연결하여 그리기 가능.
  3. GetClientRect:
    • 윈도우 클라이언트 영역의 크기를 얻어 백 버퍼 크기를 결정.

c. 더블 버퍼링 구현

파일: Game.cpp

void Game::Render()
{
	// 두 번째 버퍼(_hdcBack)에 그리기
	{
		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()));
	}

	// SceneManager의 Render 호출
	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);
}

분석:
1. 그리기:

  • 모든 렌더링 작업은 _hdcBack에서 진행.
  1. 화면 갱신:
    • BitBlt: 백 버퍼 내용을 프론트 버퍼로 복사.
      • SRCCOPY: 백 버퍼 내용을 그대로 복사.
  2. 백 버퍼 초기화:
    • PatBlt: 백 버퍼를 흰색으로 초기화.

3. 주요 API 설명

CreateCompatibleDC

  • 기존 DC와 호환되는 새 DC 생성.
  • 백 버퍼 작업용 DC를 생성할 때 사용.

CreateCompatibleBitmap

  • 특정 DC와 동일한 포맷의 비트맵 생성.
  • 백 버퍼로 사용할 비트맵 생성 시 활용.

SelectObject

  • DC와 비트맵을 연결.

BitBlt

  • 고속 비트맵 복사.
  • 백 버퍼와 프론트 버퍼 간 데이터 교환에 사용.

PatBlt

  • DC 영역을 특정 패턴(흰색 등)으로 초기화.

4. 결과

장점:

  • 깜빡임 문제 해결.
  • 부드러운 화면 전환.
  • 복잡한 그래픽 처리에서도 안정적인 출력.

단점:

  • 메모리 사용량 증가.
  • 처리 비용 증가.

profile
李家네_공부방

0개의 댓글