[디자인 패턴] #7_이중 버퍼, Double Buffer
게임 디자인 패턴 중 "이중 버퍼 패턴"에 대해 알아보겠습니다.
"게임 프로그래밍 패턴"의 8 항목, "이중 버퍼"에 해당하는 내용입니다.
이중 버퍼
1. 개념
* 이중 버퍼 패턴?
: 어떠한 클래스는 변경이 가능한 상태를 캡슐화합니다. 해당 상태는 지속적으로 변경되지만, 외부에서 볼 때 한 번에 변경되는 것처럼 보이게 하고 싶습니다. 따라서, 해당 클래스를 "현재" 상태와 "다음" 상태를 갖도록 합니다!
이때, "현재" 상태는 항상 "읽기" 전용이며, "다음" 상태는 항상 "쓰기" 혹은 "변경"에 사용됩니다!
2. 그렇다면, 언제?
1. 순차적으로 변경해야 하는 상태가 있을 때
2. 변경 도중에도 접근 할 수 있는 상태가 있을 때
3. 외부에서 변경 작업 중인 상태에 접근하는 것을 방지할 때
4. 변경 작업 중인 상태에 기다리지 않고 접근해야 할 때
3. 주의 할 점
1. 교체 연산에 걸리는 시간
: 앞서 설명한 것처럼, "다음" 상태에 정보 작성을 완료했다면,
"다음" 상태 -> "현재" 상태 + "현재" 상태 -> "다음" 상태로 변경하는 작업이 필요합니다.
이때, 걸리는 시간이 지연되면 성능에 큰 문제가 될 수 있겠죠.
2. 추가적인 메모리 필요
: 말 그대로 이중 버퍼 패턴은 두 개의 버퍼가 필수적입니다.
1. 코드 예제
1. 프레임 버퍼 클래스
enum Color {
BLACK,
WHITE
};
class FrameBuffer
{
public:
FrameBuffer() { Clear(); }
void Clear()
{
for (int i = 0; i < WIDTH * HEIGHT; i++)
pixels[i] = WHITE;
}
void Draw(int x, int y)
{
pixels[(WIDTH * y) + x] = BLACK;
}
const char* getPixels() { return pixels; }
private:
static const int WIDTH = 160;
static const int HEIGHT = 120;
char pixels[WIDTH*HEIGHT];
};
1. "FrameBuffer::Clear()" 메서드는 전체 픽셀을 흰색으로 덮어 초기화합니다.
2. "FrameBuffer::Draw()" 메서드는 특정 픽셀을 검은색으로 채웁니다.
2. Frame Buffer를 화면에 그려내는 Scene 클래스
class Scene
{
public:
//...
void Draw()
{
buffer.clear(); // Buffer의 모든 픽셀 초기화
buffer.draw(1, 1);
// < ---- 이때, getBuffer()를 통해 버퍼를 읽으면, 문제가 발생!!!
buffer.draw(2, 4);
//...
}
FrameBuffer& getBuffer() { return buffer; }
private:
FrameBuffer buffer;
};
1. Scene 클래스는 "Scene::Draw()" 메서드 내부에서 "FrameBuffer::Draw()"를 호출합니다.
* "FrameBuffer::Draw()" 메서드를 호출하며 한창 Pixel을 그리고 있을때, Buffer를 읽게 되면 Tearing 발생!
3. 수정된 Scene 클래스
class Scene
{
public:
Scene(): currentBuffer(&buffer[0]), nextBuffer(&buffer[1]){}
void Draw()
{
nextBuffer.clear(); // Buffer의 모든 픽셀 초기화
nextBuffer.draw(1, 1);
nextBuffer.draw(2, 4);
//...
Swap(); // 다음 버퍼를 현재 버퍼로 바꿉니다.
}
FrameBuffer& getBuffer() { return currentBuffer; } // 현재 버퍼를 반환합니다.
private:
// 다음 버퍼 -> 현재 버퍼 + 현재 버퍼 -> 다음 버퍼
void Swap()
{
FrameBuffer* tmpBuffer = currentBuffer;
currentBuffer = nextBuffer;
nextBuffer = tmpBuffer;
}
private:
// 버퍼 배열
FrameBuffer buffer[2];
// 이중 버퍼 패턴
FrameBuffer* currentBuffer;
FrameBuffer* nextBuffer;
};
1. 이제 Scene 클래스는 두 개의 Buffer를 데이터 멤버로 갖습니다.
2. "Scene::getBuffer()" 메서드는 "현재" 버퍼만 반환합니다!
* 결과적으로, 이중 버퍼를 활용해 그리기 작업 버퍼와 읽기 전용 버퍼를 따로 두어 매끄러운 프레임 전환!
'언어 > 디자인 패턴' 카테고리의 다른 글
[디자인 패턴]#9_업데이트 패턴, Update Pattern (0) | 2022.09.04 |
---|---|
[디자인 패턴]#8_게임 루프, Game Loop Pattern (0) | 2022.08.28 |
[디자인 패턴]#6_상태 패턴, State Pattern (1) | 2022.08.20 |
[디자인 패턴]#5_싱글턴 패턴, Singleton Pattern (0) | 2022.08.02 |
[디자인 패턴]#4_프로토타입 패턴, Prototype Pattern (0) | 2022.07.22 |