본문 바로가기

MS/DirectX

DirectDraw - SetClipper (1)

Clipper의 필요성에 대해선 조금 그림을 통한 부가 설명이 필요 할 것 같아서 제가 이미지를 하나 또 준비했습니다.

하하^^;

사용자 삽입 이미지


 

, 위 그림을 한번 보세요.

만약 위처럼 블리팅을 시도했다면, 화면에는 두더지가 반밖에 그려지지 않았겠죠.

그러나 사실 알고보면 메모리상에는 나머지 반의 부분도 존재합니다.


두더지 이미지의 사이즈는 총 11KB입니다.

그런데 딱 절반밖에 보이질 않으므로, 나머지 5.5KB... 보이지도 않는데 괜히 메모리만 낭비하고 있는 셈이 되겠군요.

문제는 그것뿐이 아닙니다.


, 두더지의 이미지 크기를 계산하기 쉽게 100*100이라고 생각해 봅시다.

블리팅을 할때, 1 픽셀을 그려주는데 1초가 걸린다고 치면...

100*100
의 이미지를 그려주는데는 무려 10000초가 걸리게 됩니다! (물론 이렇게 느린 블리팅은 없겠죠-_-)

그러나, 만약에 화면에 보이지 않는 50*100을 그려주지 않는다면?

우리는 나머지 50*100의 이미지만을 그려주면 되므로,블리팅 시간은 5000초로 단축이 될 수가 있는 것입니다.

어떠세요? 클리핑의 필요성이 확확 와닿지 않나요?


클리핑에는 먼저 크게 나누면 두가지의 클리핑이 있습니다.

Software Clipping
Hardware Clipping이 바로 그것인데요.

S/W
클리핑이 안 좋고, H/W 클리핑은 좋다. 뭐 이렇게 딱 정해진 것은 없습니다.

물론 S/W 클리핑이 H/W 클리핑에 비해 속도가 느린것은 사실이지만,

클리핑의 필요성이 별로 없는 프로그램에서는 H/W 클리핑을 쓰는 것보다 S/W 클리핑을 사용할때의 이득이 더 많을 때가 있습니다.

, 그런건 프로그래머가 경험으로 판단하는 것이겠구요.


우리는 S/W 클리핑은 다루고 넘어가진 않을 것이지만, 결국엔 다 같으니 S/W 클리핑은 조금만 생각해보시면 다 구현해내실수 있으리라고 믿습니다.


DirectDraw
를 이용한 H/W 클리핑.

DirectDraw
에는 IDirectDrawClipper라는 인터페이스가 있습니다.

S/W
클리핑의 경우, 픽셀 클리핑, 2D 클리핑, 3D 클리핑 등등...

클리핑 할 객체의 종류에 따라 방법이 나뉘어져 있습니다.

그러나 DirectDraw Clipper를 이용한 클리핑 시에는, 같은 방법으로 2D/3D를 가리지 않고 동일하게 사용될수 있습니다.

좋죠?^^;


DirectDraw
클리핑을 세팅 하기 위해서는 다음과 같은 순서로 코딩하시면 됩니다.

1. DirectDraw Clipper
객체를 생성한다.
2. Clipping List
를 작성한다.
3. IDIRECTDRAWCLIPPER::SetClipList()
를 이용하여 작성한 Clipping List를 클리퍼에게 넘겨준다.
4. IDIRECTDRAWCLIPPER::SetClipper)
를 이용하여 클리퍼를 Windows나 특정 표면에 적용시킨다.

간단하죠?


DirectDraw Clipper
는 고맙게도 매개변수가 Direct Draw 함수 중 가장 쉽기때문에 쉽게 적용시킬수 있습니다.


그럼 1번 단계부터 살펴보도록 할까요?

IDIRECTDRAW7::CreateClipper()
함수의 원형을 보면,

HRESULT CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER* lplpDDClipper, IUnknown* pUnkOuter);

와 같이 되어 있습니다.

dwFlags
에는 플래그 값이 들어가는 필드인데, 아직 우리는 사용하지 않으므로 단순히 0으로 지정해주시면 됩니다.

lplpDDClipper
는 당연히 LPDIRECTDRAWCLIPPER의 주소값을 넣어주시면 되겠구요.

마지막 Unknown은 이전과 마찬가지로 NULL을 넘겨주시면 됩니다^^

쉽죠! 쉽죠?


그런데 DDClipper를 이해하는데 조금 걸림돌이 되는 녀석이 바로 2번입니다.

2
과정은 바로 Clipping List를 작성하는 것이라고 말씀 드렸습니다.

Clipping List, 클리핑을 할 영역의 리스트를 의미하는 것이 당연하겠죠.

이 말은 바꿔 말하면, 클리핑을 한군데만 하는 것이 아니라, 여러군데를 클리핑 할수도 있다는 의미가 되겠죠.


어쨋든 Clipping List를 작성하려면 조금 이상한 형태의 구조체에 정보를 기입해주어야 하는데요.


typedef struct _RGNDATA
{
RGNDATAHEADER rdh;
char Buffer[1];
} RGNDATA;

먼저 RGNDATAHEADER를 살펴보면,

typedef struct _RGNDATAHEADER
{
DWORD dwSize;
DWORD iType;
DWORD nCount;
DWORD nRgnSize;
RECT rcBound;
} RGNDATAHEADER;

dwSize
는 당연히 RGNDATAHEADER의 크기를 넣어주시면 되고,

iType
RGNDATA Type을 넣어주시는 건데,

사각형 형식으로 클리핑을 할것이므로 보통 RDH_RECTANGLES를 넣어줍니다.

nCount
는 클리핑 영역이 몇개나 되는지를 기록해 주시면 되구요.

rcBound
는 클리핑 영역의 경계 라인을 의미합니다. rcBound에 대해서는 다음시간에 자세히 알아볼 것입니다.


그런데
char Buffer[1]부분은,

C/C++
에 익숙하신 분들도 약간은 어리둥절 할 만한 형태를 띄고 있습니다.

Buffer
라는 기본적으로
길이에 제한이 없는 가변 크기의 변수 입니다.


아마 대부분의 분들은

char Buffer[1]이 문자 배열 1개를 선언한거지, 무슨 가변 크기의 구조체야!

라고 생각하시며 의아해 하실 겁니다.


그러나
char Buffer[1]을 다르게 써보면...

char* Buffer;

와 같다는 사실을 염두해 두셔야 합니다.


그렇다면 c
har Buffer char Buffer[1]과 같을까요? 정답은 No 입니다.

그러나
char* Buffer char Buffer[1]의 시작 주소를 의미하는 것이므로,

정확히 같지는 않지만, 구현시, 결과는 동일하게 됩니다.

그래서
char Buffer[1]과 같이 변수를 선언 한 것이구요.


그렇다면,
char Buffer[1]과 같이 char형 변수로 선언한 것은 어떤 이유가 있을까요?

바로,
char 형 변수가 1Byte 크기의 변수이기 때문입니다.

예를 들어 5바이트를 메모리 할당하고 싶다면,
char형 변수 5개를 만들면 되므로,

계산이 편하겠죠^^ 그래서
char형 변수로 선언을 한 것입니다.


만약
char Buffer[1]부분이 이해가 안가신다면 그냥 건너 뛰시고 설명을 들으셔도 상관이 없습니다.

쉽긴 하지만, 나름대로 고급 개념이기 때문에, 다음 기회에 자세히 알아보도록 하겠구요.

어쨋든 중요한 것은
char Buffer[1]이 아니라, RGNDATA라는 구조체 그 자체이므로 아래 그림을 한번 보시길 바랍니다.

사용자 삽입 이미지


 

RECT #1, RECT #2, RECT #3, .... ,RECT #X 와 같이 메모리상에 할당만하면, 얼마든지 늘어날 수 있다는 걸 볼수가 있습니다.

Buffer
를 다루는 건 다음시간에 알아보도록 하죠.


이제 다시 본론으로 돌아와서 아까 3번 과정을 기억하시나요?

Clipping List
를 설정했다면, 어떤 서페이스에 클리핑 영역을 추가 시킬 것인지,

SetClipper()
함수를 이용해서 서페이스에 클리핑 영역을 추가시키면 됩니다.


SetClipper
의 원형은 아래와 같구요.

HRESULT SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper);

그냥 단순히, 이런식으로 설정해 주시면 되겠죠.

if( FAILED(lpddSuface->SetClipper( &lpddClipper )) )
return ERR;

이런식으로 해주시면 DDClipper의 세팅이 끝나는 거죠^^


어떠세요? 사실 어려운 것 같지만, 별것도 아닙니다.

다음시간에 직접 이번시간에 배운 내용을 토대로 소스를 작성해 볼 것인데요.

DDClipper
Video Mode 세팅과 함께DDraw의 꽃이라고 불리는 녀석이므로, 반드시 알고 넘어가야 합니다.

 

출처 : http://aptinfo.tistory.com/87

'MS > DirectX' 카테고리의 다른 글

D3DFont 성능  (0) 2012.07.10
DX Sprite 사용법  (0) 2012.06.26
D3DXFont::DrawText 완전 느림...  (0) 2012.06.26
DirectDraw - SetClipper (2)  (0) 2012.06.01