게임 엔진 개발

[게임 엔진 개발] - 더블버퍼링 기법 (화면 그리기)

LKBaekjoon 2024. 7. 1. 13:08
반응형

앞서 공부하고 정리한 내용은 무료 배포된 유튜브 "얌얌코딩"님의 강의를 시청한 후임을 밝힙니다.

LV06 Input (youtube.com)

 

얌얌코딩 (게임 개발)

어려운 게임 개발을 쉽게 배우는 방법!

www.youtube.com


사진 출처 : Double Buffering - 더블 버퍼링 기법 :: Move Fast (tistory.com)

 

Double Buffering - 더블 버퍼링 기법

더블 버퍼링(Double Buffering)은 이중 버퍼링이라 불리기도 하며, 그래픽 객체에 이미지를 그릴 때 사용되는 기법이다. Q) 왜 사용하는가 ? A) API를 시작하다보면 비트맵 이미지를 사용하게 된다. 그

movefast.tistory.com

  • 실제로 우리가 캐릭터를 움직이거나 어떤 객체의 움직임을 화면에서 표현하고자 할 때, 그 화면 자체를 지우고 새로 그리는 작업이 필요하다.
  • 헌데 그걸 하나의 Bitmap 내에서 수행하게 될 경우, Flicking 현상이 발생할 수 있다.
    • 위의 적용 전 화면 전환을 보면, 그림이 그려지기 전에 동일 Bitmap를 사용한 화면이 여전히 유저에게 보여져야 하므로 순간적으로 화면이 깜빡거리게 되는데, 유저로써는 매우 불편한 경험을 하게 할 수 있다.
  • 위 문제를 해결하기 위해, 아래의 경우처럼 새로운 Bitmap를 하나 더 만들어서, 거기서 그린다음 화면 전환 자체를 다른 Bitmap로 딸깍 바꿔주는 것이다.

 

구현 Trade - Off [메모리 vs 연산]


  • 허나 생각하기에 다음의 Trade - off가 있을 수 있다고 생각했다.
  • 우선 비트맵 (그림을 그리는 도화지) 자체가 두 개이고, 계속 Change해주면서 왔다갔다 하는 것은 연산은 줄어들 수 있으나 메모리 자체를 좀 잡아먹을 수 있다.
  • 이를 해결하기 위해 필자의 본 코드에서는 DC 자체를 왔다갔다 하면서 비트맵을 지우고 그려주는 방식으로 구현하여 연산양은 좀 많을 수 있으나 메모리 사용량을 줄였다.
void Application::Initialize(HWND hwnd, UINT width, UINT height)
{
    mHwnd = hwnd;
    mHdc = GetDC(hwnd);

    RECT rect = { 0, 0, width, height };
    AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, false);

    mWidth = rect.right - rect.left;
    mHeight = rect.bottom - rect.top;
    SetWindowPos(hwnd, nullptr, 0, 0, mWidth, mHeight, 0);

    ShowWindow(hwnd, true);

    // 윈도우 해상도에 맞는 백버퍼 생성
    mBackBuffer = CreateCompatibleBitmap(mHdc, width, height);

    //백버퍼를 가리킬 DC 생성
    mBackHdc = CreateCompatibleDC(mHdc);

    HBITMAP oldBitmap = (HBITMAP)SelectObject(mBackHdc, mBackBuffer);
    DeleteObject(oldBitmap);


    mPlayer.setPosition(0, 0);

    Input::Initialize();

    Time::Initialize();
}
  • 매 Tick마다 호출되는 Render 함수 자체에서는 BackBuffer에 그려진 것을 원본 버퍼로 복사해주는 Bitㅠlt 함수를 호출한다.
///백버퍼에 있는걸 원본 버퍼에 복사(그려준다)
BitBlt(mHdc, 0, 0, mWidth, mHeight, mBackHdc, 0, 0, SRCCOPY);
반응형