본문 바로가기
Develop/Win32 API와 게임 엔진

[개발] 공부하며 정리한 "Double Buffering"

by Tarra 2023. 10. 22.

 


개인 공부 후 자료를 남겨놓기 위한 목적이므로,
생략되거나 오류가 있을 수 있음을 알립니다.

잘못된 부분이 있다면 댓글로 상냥하게 가르쳐주시면 감사하겠습니다!

 

 

이전 문서에서 화면이 깜빡였던 이유와 그 해결법인 더블 버퍼링에 대해서 알아보도록 하자.

 

 

보며 공부한 곳! // 어소트락 아카데미 Win32 API 무료강의

https://youtu.be/dlFr-OnHlWU?si=K8UpK8CwSOddqFZ5


이전 문서에서 사각형이 움직이기는 했지만, 형체를 알아보지 못할 정도로 잘 보이지 않았다.

 

이 문제가 발생하는 이유는 현재 화면을 표시하고 있는 방법인 "싱글 버퍼링"이 화면을 그리는 작업과 화면을 표시하는 작업이 서로 분리되어 있어 화면에 그림을 그리기도 전에 렌더링을 해버리기 때문이라고 보면 된다.

 

따라서 우리는 "더블 버퍼링"이라는 기법을 사용하여 이 문제를 해결할 것이다.

 

더블 버퍼링이란 위의 문제를 해결하기 위한 방법 중 하나로, 그림을 그리는 버퍼를 하나 더 사용하는 것이다.

 

그림이 그려진 버퍼를 보여주는 동안 또 하나의 버퍼에 다음 프레임의 그림을 그리고 이 두 버퍼를 교체하게 되면 깜빡임이 없이 

부드럽게 화면이 갱신되는 것을 느낄 수 있게 된다.

 

+ 만약 그리기 연산에 문제가 생겨 지연이 생기게 되면, 더블 버퍼링 또한 화면이 밀리는 등 문제가 발생한다.
이를 해결하기 위한 방법으로 수직 동기화 방법과 삼중 버퍼링 기법이 존재한다.

 

자 이제 win32 api를 이용하여 이중 버퍼링을 구현해보자.

 

이전에 작성했던 Core 헤더에 이중 버퍼링을 위한 멤버 변수 두가지를 추가해준다.

 

 

이후 Core 객체가 생성되면서 위의 변수를 준비할 수 있도록 init() 함수에서 해당 변수들의 값을 채워준다.

 

Core::init() 함수

이중 버퍼링을 위한 DC와 비트맵을 준비해놓았으므로 이제 이전 문서에서 그렸던 Rectangle을 m_hDC가 아닌 m_memDC에 그려준다.

 

그림을 그리는 작업을 따로 render() 로 옮겨주었다.

이제 우리는 기존의 m_hDC에 그림을 그리지 않고 m_memDC에 그림을 그리기 때문에 화면에 사각형이 나오지 않게 된다.

 

이 문제를 해결하기 위해 마지막으로 m_hDC와 m_memDC를 교체하는 작업을 해줄 것이다.

 

InvalidateRect()은 처음에 화면 크기의 사각형을 그리는 것으로 대체되었음.

 

이렇게 이제 화면이 제대로 출력되는 것을 확인할 수 있을 것이다.

 

 

이제 이전에 만들어 놓은 KeyMgr을 이용해 사각형을 이동시켜보자.

 

 

사각형이 매우 빠른 속도로 이동하는 것을 볼 수 있는데

 

이는 컴퓨터의 처리속도가 매우 빠르기 때문에 위 코드에서의 +1이 저렇게 빠르게 처리되기 때문이다.

 

우리는 컴퓨터의 성능에 좌우되지 않고 프로그램속의 오브젝트를이 작동하기를 바란다.

 

이때 사용되는것이 "Delta Time (델타 타임)"으로 다음 문서에서 다뤄볼 개념이다.

 

델타 타임을 이용하여 프로그램이 어떠한 상황에서든 균일한 움직임을 보일 수 있도록 해보자.