62
Chapter 11 Chapter 11 DirectDraw DirectDraw 의 의의 의 의 의의 의 : : 의의 의의의 의의의 의의 의의의 의의의

Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

Embed Size (px)

Citation preview

Page 1: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

Chapter 11Chapter 11

DirectDrawDirectDraw 의 깊은 곳의 깊은 곳 : : 보다 발전된 기능들보다 발전된 기능들

Page 2: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

2

이 장에서는이 장에서는

• - 비트맵 그래픽으로 고급 작업 수행하기• - 오프스크린 표면 사용하기• - 색상 애니메이션 기법 알아보기• - DirectDraw 와 GDI 결합하기• - 윈도우 모드에서 DirectDraw 사용하기• - DirectDraw 에서 정보 얻어오기

Page 3: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

3

투명도투명도

Page 4: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

4

Black-transparent 8-bit versionBlack-transparent 8-bit version

// 32 x 32 bitmap 을 화면 (x,y) 에 뿌리는 예제// (x, y) 는 bitmap 의 왼쪽 위 꼭지점이 된다 . // (index_x, index_y) 는 32x32 bitmap 을 따라간다 .

for (int index_y=0; index_y<32; index_y++) { for (int index_x=0; index_x<32; index_x++) { UCHAR pixel = image[index_x+index_y*32]; if (pixel!=0) primary_buffer[x+index_x+(y+index_y)*ddsd.lPitch] = pixel; } // end for index_x} // end for index_y

Page 5: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

5

Black-transparent 16-bit versionBlack-transparent 16-bit version

// these two loops blit a 32 x 32 bitmapfor (int index_y=0; index_y<32; index_y++){// copy next row of pixelsfor (int index_x=0; index_x<32; index_x++) { // get the next pixel USHORT pixel = image[index_x+index_y*32]; // test if pixel is transparent if (pixel!=_RGB16BIT565(0,0,0)) primary_buffer[x+index_x+(y+index_y)*(ddsd.lPitch/2)] = pixel; // else do nothing } // end for index_x} // end for index_y

Page 6: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

6

Black-transparent 8-bit Black-transparent 8-bit (without multiply)(without multiply)UCHAR *src_ptr = image;UCHAR *dest_ptr = primary_buffer + x + y * ddsd.lPitch;

for (int index_y=0; index_y<32; index_y++) { for (int index_x=0; index_x<32; index_x++) { UCHAR pixel = *src_ptr; if (pixel!=0) *dest_ptr = pixel; src_ptr++; dest_ptr++; } // end for index_x // move destination pointer to start of next line dest_ptr+=(ddsd.lPitch - 32); } // end for index_y

Page 7: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

7

Black-transparent 16-bit Black-transparent 16-bit (without multiply)(without multiply)

• Try it !

Page 8: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

8

Multiplication/Division by shift Multiplication/Division by shift

• player_x*64 = player_x <<6

• player_x*96 = player_x*64 + player_x*32 = (player_x << 6) + (player_x << 5)

Page 9: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

9

색상키색상키 (color keying)(color keying)

• 원본키 (source key)– 투명한 색상의 범위를 설정하고 , 블리터에게 이 범위를

복사하지 말도록 지시

HRESULT SetColorKey(DWORD dwFlags, // what kind of key

LPDDCOLORKEY lpDDColorKey); // range of key

typedef struct _DDCOLORKEY {

DWORD dwColorSpaceLowValue; // starting color (inclusive)

DWORD dwColorSpaceHighValue;// ending color (inclusive)

} DDCOLORKEY,FAR* LPDDCOLORKEY;

Page 10: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

10

Source Key ExampleSource Key Example

DDCOLORKEY key; // color key

// set transparent color range to 0

key.dwColorSpaceLowValue = 0;

key.dwColorSpaceHighValue = 0;

// set color key now on the source surface, which is usually the backbuffer

lpddsback->SetColorKey(DDCKEY_SRCBLT, &key);

// perform the blit from backbuffer to primary buffer

lppddsprimary->Blt(...);

Page 11: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

11

Source KeySource Key 의 예의 예

+Blitting

Source Key = R

Source

Destination

Result

R

GB

Y

Y

B G

Page 12: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

12

목적키목적키 (destination key)(destination key)

• 그려질 목적 표면에 색상키 범위를 설정 • Dest key 와 같은 색이 먼저 깔려 있으면 그 곳에는 bli

tting 되지 않는다 .

DDCOLORKEY key; // color key

// set writable values from 0 to 249

key.dwColorSpaceLowValue = 0;

key.dwColorSpaceHighValue = 249;

// set color key now on the destination surface

lpddsprimary->SetColorKey(DDCKEY_DESTCBLT, &key);

// perform the blit from backbuffer to primary buffer

// or whatever is the source surface...

lppddsprimary->Blt(...);

Page 13: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

13

Destination KeyDestination Key 의 예의 예

+Blitting

Dest Key = B

Source

Destination

Result

R

GB

Y

Y

G

R

B

Page 14: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

14

템플릿으로부터 비트맵 추출 템플릿으로부터 비트맵 추출

Page 15: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

15

BOB(Bitmapped Object Bitmap) BOB(Bitmapped Object Bitmap) 사용사용

1. DirectDraw 를 설정한다 .

2. 10 장에서처럼 8 비트 또는 16 비트 색상의 비트맵 이미지에 객체들을 불러온다 .

3. Create_BOB() 또는 Create_BOB16() 으로 BOB 를 생성한다 .

4. Load_BOB() 또는 Load_BOB16() 으로 이미지를 BOB 에 불러온다 .

5. Draw_BOB() 또는 Draw_BOB16() 으로 BOB 를 그린다 .

6. 완료하면 , Destroy_BOB() 또는 Destroy_BOB16()으로 BOB 을 제거한다 .

Page 16: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

16

BOB StructureBOB Structure

typedef struct BITMAP_OBJ_TYP

{

int state; // the state of the object (general)

int attr; // attributes pertaining to the object (general)

int x,y; // position bitmap will be displayed at

int xv,yv; // velocity of object

int width, height; // the width and height of the bitmap

LPDIRECTDRAWSURFACE7 image; // the bitmap surface itself

} BITMAP_OBJ, *BITMAP_OBJ_PTR;

#define BOB_STATE_DEAD 0 // this is a dead BOB

#define BOB_STATE_ALIVE 1 // this is a live BOB

#define BOB_STATE_LOADED 2 // the BOB has been loaded

Page 17: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

17

죽은죽은 (dead) BOB(dead) BOB 와 살아있는와 살아있는 (live) BOB (live) BOB

• 살아있다는 것은 BOB 가 게임 로직에 의해 처리되고 있음을 뜻한다 .

• BOB 가 죽었다는 것은 게임 로직에 의해 처리되지 않는다는 것을 의미한다 .

Page 18: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

18

BOB BOB 생성 생성 (1)(1)

int Create_BOB(BITMAP_OBJ_PTR bob, // the BOB to create int width, int height, // size of BOB int attr, // attrs int flags = 0) // memory flag{// create the BOB object; note that all BOBs are created as off-screen// surfaces in VRAM as the default; if you want to use system memory,// set flags equal to DDSCAPS_SYSTEMMEMORYDDSURFACEDESC2 ddsd; // used to create surface// set state and attributes of BOBbob->state = BOB_STATE_ALIVE;bob->attr = attr;bob->image = NULL;// set position and velocity to 0bob->x = bob->y = bob->xv = bob->yv = 0;// set to access caps, width, and heightmemset(&ddsd,0,sizeof(ddsd));ddsd.dwSize = sizeof(ddsd);ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;

Page 19: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

19

BOB BOB 생성 생성 (2)(2)

// set dimensions of the new bitmap surfaceddsd.dwWidth = bob->width = width;ddsd.dwHeight = bob->height = height;// set surface to off-screen plainddsd.ddsCaps.dwCaps = DDSCAPS_OFF_SCREENPLAIN | flags;// create the surfaceif (lpdd->CreateSurface(&ddsd,&(bob->image),NULL)!=DD_OK) return(0);// set color key to color 0DDCOLORKEY color_key; // used to set color keycolor_key.dwColorSpaceLowValue = 0;color_key.dwColorSpaceHighValue = 0;// now set the color key for source blitting(bob->image)->SetColorKey(DDCKEY_SRCBLT, &color_key);// return successreturn(1);} // end Create_BOB

Page 20: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

20

비트맵 데이터로 비트맵 데이터로 BOB BOB 로딩하기 로딩하기 (1) (1)

• 목적 BOB 와 읽어올 원본 비트맵 파일을 인수로 받는다 .

• (cx, cy) 와 mode 에 의해서 읽어올 위치가 결정된다 . • Cell Mode (0): (cx, cy) 는 셀 좌표로 해석된다 . • Absolute Mode (1): (cx, cy) 는 원본 비트맵의 절대

좌표로 해석된다 . • 읽을 비트맵의 크기는 BOB 와 정확하게 맞으며 ,

이것은 bob->width 와 bob->height 에 정의된다 .

Page 21: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

21

비트맵 데이터로 비트맵 데이터로 BOB BOB 로딩하기 로딩하기 (2)(2)

Page 22: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

22

비트맵 데이터로 비트맵 데이터로 BOB BOB 로딩하기 로딩하기 (3)(3)

int Load_BOB(BITMAP_OBJ_PTR bob, // BOB to load with dataBITMAP_FILE_PTR bitmap, // bitmap to scan image data from int cx,int cy, // cell or absolute pos to scan image from int mode) // if 0, then cx,cy is cell position; else // cx,cy are absolute coordinates{// this function extracts a bitmap out of a bitmap fileUCHAR *source_ptr, // working pointers *dest_ptr;DDSURFACEDESC2 ddsd; // DirectDraw surface description// test the mode of extraction, cell-based or absoluteif (mode==0) { // re-compute x,y cx = cx*(bob->width+1) + 1; cy = cy*(bob->height+1) + 1; } // end if

Page 23: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

23

비트맵 데이터로 비트맵 데이터로 BOB BOB 로딩하기 로딩하기 (4)(4)

// extract bitmap data

source_ptr = bitmap->buffer +

cy*bitmap->bitmapinfoheader.biWidth+cx;

// get the addr to destination surface memory

// set size of the structure

ddsd.dwSize = sizeof(ddsd);

// lock the display surface

(bob->image)->Lock(NULL,

&ddsd,

DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,

NULL);

// assign a pointer to the memory surface for manipulation

dest_ptr = (UCHAR *)ddsd.lpSurface;

Page 24: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

24

비트맵 데이터로 비트맵 데이터로 BOB BOB 로딩하기 로딩하기 (5)(5)

// iterate through each scanline and copy bitmapfor (int index_y=0; index_y<bob->height; index_y++) { // copy next line of data to destination memcpy(dest_ptr, source_ptr,bob->width); // advance pointers dest_ptr += (ddsd.lPitch); source_ptr += bitmap->bitmapinfoheader.biWidth; } // end for index_y// unlock the surface(bob->image)->Unlock(NULL);// set state to loadedbob->state |= BOB_STATE_LOADED;// return successreturn(1);} // end Load_BOB

Page 25: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

25

BOB BOB 그리기그리기int Draw_BOB(BITMAP_OBJ_PTR bob, // BOB to draw LPDIRECTDRAWSURFACE7 dest) // surface to draw the BOB on{// draw a BOB at the x,y defined in the BOB// on the destination surface defined in destRECT dest_rect, // the destination rectangle source_rect; // the source rectangle// fill in the destination rectdest_rect.left = bob->x;dest_rect.top = bob->y;dest_rect.right = bob->x+bob->width;dest_rect.bottom = bob->y+bob->height;// fill in the source rectsource_rect.left = 0;source_rect.top = 0;source_rect.right = bob->width;source_rect.bottom = bob->height;// blt to destination surfacedest->Blt(&dest_rect, bob->image, &source_rect,(DDBLT_WAIT | DDBLT_KEYSRC), NULL);// return successreturn(1);} // end Draw_BOB

Page 26: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

26

BOB BOB 소멸하기 소멸하기

int Destroy_BOB(BITMAP_OBJ_PTR bob)

{

// destroy the BOB; simply release the surface

if (bob->image)

(bob->image)->Release();

else

return(0);

// return success

return(1);

} // end Destroy_BOB

Page 27: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

27

BOBBOB 를 움직이게 하는 함수들 를 움직이게 하는 함수들 (16bit)(16bit)

BITMAP_FILE bitmap; // working bitmap fileBITMAP_OBJ car; // the bitmapped object// load the bitmapLoad_Bitmap_File(&bitmap,”cars16.bmp”);// create a 32 x 32 VRAM BOBCreate_BOB16(&car,32,32,0,0,0);// load the BOB with first cell of bitmap template imageLoad_BOB16(&car,0,0,0);// unload the bitmap; you’re done with itUnload_Bitmap_File(&bitmap);// set position of BOBcar.x = 100;car.y = 200;// draw BOB on primary surfaceDraw_BOB16(&car, lppdsprimary);// your game code goes here...// delete the BOBDestroy_BOB16(&car);

Page 28: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

28

DEMO: PROG11_1_16DEMO: PROG11_1_16

Page 29: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

29

색상을 이용한 기술들 색상을 이용한 기술들

• 게임 프로그래머는 기교 (trick) 를 써서 – 그래픽 시스템이 실제보다 더 많은 색상이 있는 것처럼 보이게 하고 , – 또한 기존 하드웨어로는 불가능한 것처럼 보이는 광원 (lighting)

효과를 적용하기도 했다 .

• 요즘에는 이런 trick 을 쓰지 않아도 된다 . • 휴대폰이나 PDA 게임 프로그래밍에 여전히 적용 가능하다 .

Page 30: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

30

팔레트 애니메이션팔레트 애니메이션

• 8 비트 색상 모드에서만 적용 • 하나 혹은 이상의 팔레트 항목을 실시간에 새로운 데이터로

갱신하는 것이다 . • 이 방법으로 이들 색상으로 그려진 픽셀은 시간에 따라

변한다 . • 깜빡이는 빛이나 , 에너지 펄스 , 폭발 등에 이 기법을

사용한다 .

Page 31: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

31

DEMO: PROG11_2DEMO: PROG11_2

Page 32: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

32

색상 회전색상 회전 (color rotation) (color rotation)

• 움직임을 잘 시뮬레이션 한다 • 폭포수나 흐르는 샘물 , 또는 컨베이어 벨트

Page 33: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

33

DEMO: PROG11_3DEMO: PROG11_3

Page 34: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

34

클리핑클리핑 (clipping) (clipping)

• 이미지에서 보이지 않는 부분을 그리지 않는 것을 의미

Page 35: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

35

두가지 클리핑 방법두가지 클리핑 방법

• 이미지 - 공간 (image-space) 클리핑– 픽셀 단위로 그리는 것처럼 클리핑하는 방법이다 . – 시간이 많이 걸리고 , 때로는 하드웨어 가속기능이 있을

때에만 잘 동작한다 . – 물체의 각 픽셀을 그릴 때에 그것이 클리핑 영역에 그려지지

않는 것을 확인해야 한다는 것이다 .

• 오브젝트 - 공간 (object-space) 클리핑 – 매 픽셀마다 클리핑 영역과 비교하는 것이 아니라 , 그려질

물체의 형태를 분석하여 , 어느 정도의 부분을 그려야 하는지 계산

– 이미지 - 공간 클리핑보다 조금 더 수학적이다 .

Page 36: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

36

Clipping CasesClipping Cases

Page 37: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

37

오브젝트오브젝트 -- 공간 클리핑의 간단한 예 공간 클리핑의 간단한 예

// trivial rejections test first// is the rectangle totally off the screen?if (x1 > MAX_X || x2 < MIN_X || y1 > MAX_Y || y2 < MIN_Y) { /* totally clipped, do nothing */ }// check x coordsif (x1 < MIN_X) x1 = MIN_X;else if (x2 > MAX_X) x2 = MAX_X;// now y coordsif (y1 < MIN_Y) y1 = MIN_Y;else if (y2 > MAX_Y) y2 = MAX_Y;// at this point, (x1,y1) through (x2,y2) contain the clipped rectangle...

Page 38: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

38

DirectDrawClipperDirectDrawClipper 의 소개 의 소개

• DirectDraw 는 블리트하고자 하는 어떤 표면에도 추가할 수 있는 DirectDrawClipper 를 지원한다 .

• 클리퍼는 여러 개의 클리핑 영역을 가질 수 있다 .

Page 39: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

39

DirectDrawClipperDirectDrawClipper 를 생성하는 단계 를 생성하는 단계

1. DirectDrawClipper 객체를 생성한다 .

2. 클리핑 사각형의 목록을 생성하고 그것을 클리퍼 (clipper) 에 할당한다 .

3. 클리퍼를 표면 (surface) 에 추가한다 .

Page 40: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

40

DirectDrawClipper DirectDrawClipper 생성 생성

// Prototype

HRESULT CreateClipper(DWORD dwFlags, // unused; make 0

LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, // ptr to result

IUnknown FAR *pUnkOuter); // always NULL

// Example

LPDIRECTDRAWCLIPPER lpddclipper; // the clipper

if ((lpdd->CreateClipper(0,&lpddclipper,NULL))!=DD_OK)

return(NULL);

Page 41: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

41

클리핑 목록 채우기 클리핑 목록 채우기 (1) (1)

• RGNDATA typedef struct _RGNDATA { // rgnd

RGNDATAHEADER rdh; // the header

char Buffer[1]; // a list of RECTs defining clipping

} RGNDATA;

typedef struct _RGNDATAHEADER { // rgndh

DWORD dwSize; // size of this header

DWORD iType; // must be RDH_RECTANGLES

DWORD nCount; // number of rectangles in buffer

DWORD nRgnSize; // size of the buffer

RECT rcBound; // a bounding box around all the rects

} RGNDATAHEADER;

Page 42: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

42

클리핑 목록 채우기 클리핑 목록 채우기 (2) (2)

HRESULT SetClipList(

LPRGNDATA lpClipList, // ptr to RGNDATA

DWORD dwFlags); // unused; must be 0

RGNDATA region_data; // holds the RECTs and data header

// fill in region_data...

// set clipping list

if ((lpddclipper->SetClipList(&region_data, 0))!=DD_OK)

{ /* error */ }

Page 43: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

43

클리퍼를 표면에 추가하기 클리퍼를 표면에 추가하기

if ((lpdds->SetClipper(lpddclipper))!=DD_OK)

{ /* error */ }

Page 44: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

44

Wrapper Fn: DD_Attach_Clipper (1)Wrapper Fn: DD_Attach_Clipper (1)

LPDIRECTDRAWCLIPPERDD_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds, int num_rects, LPRECT clip_list){// this function creates a clipper from the sent clip list// and attaches it to the sent surfaceint index; // looping varLPDIRECTDRAWCLIPPER lpddclipper; // pointer to the newly created dd clipperLPRGNDATA region_data; // pointer to the region data that contains // the header and clip list// first create the DirectDraw clipperif ((lpdd->CreateClipper(0,&lpddclipper,NULL))!=DD_OK) return(NULL);// now create the clip list from the sent data// first allocate memory for region dataregion_data = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER) + num_rects*sizeof

(RECT));// now copy the rects into region datamemcpy(region_data->Buffer, clip_list, sizeof(RECT)*num_rects);

Page 45: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

45

Wrapper Fn: DD_Attach_Clipper (2)Wrapper Fn: DD_Attach_Clipper (2)

// set up fields of headerregion_data->rdh.dwSize = sizeof(RGNDATAHEADER);region_data->rdh.iType = RDH_RECTANGLES;region_data->rdh.nCount = num_rects;region_data->rdh.nRgnSize = num_rects*sizeof(RECT);region_data->rdh.rcBound.left = 64000;region_data->rdh.rcBound.top = 64000;region_data->rdh.rcBound.right = -64000;region_data->rdh.rcBound.bottom = -64000;// find bounds of all clipping regionsfor (index=0; index<num_rects; index++) { // test whether the next rectangle unioned with the current bound is larger if (clip_list[index].left < region_data->rdh.rcBound.left) region_data->rdh.rcBound.left = clip_list[index].left; if (clip_list[index].right > region_data->rdh.rcBound.right) region_data->rdh.rcBound.right = clip_list[index].right; ….

Page 46: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

46

Wrapper Fn: DD_Attach_Clipper (3)Wrapper Fn: DD_Attach_Clipper (3)

// set up fields of header// you’ve computed the bounding rectangle region and// set up the data; now set the clipping listif ((lpddclipper->SetClipList(region_data, 0))!=DD_OK) { // release memory and return error free(region_data); return(NULL); } // end if// now attach the clipper to the surfaceif ((lpdds->SetClipper(lpddclipper))!=DD_OK) { // release memory and return error free(region_data); return(NULL); } // end if// all is well, so release memory and send back the pointer// to the new clipperfree(region_data);return(lpddclipper);} // end DD_Attach_Clipper

Page 47: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

47

클리핑 목록을 설정하는 방법 클리핑 목록을 설정하는 방법

// create clip list (4) rectangles

RECT cliplist[4] = { {0,0,100,100}, {200,200,300,300},

{400,100,500,200}, {500,400,550,450}};

// attach clipper and save in lpddclipper

lpddclipper = DD_Attach_Clipper(lpddsprimary,4,cliplist);

Page 48: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

48

DEMO: PROG11_4_16BDEMO: PROG11_4_16B

Page 49: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

49

GDIGDI 와 와 DirectDrawDirectDraw 의 사용 의 사용

• 윈도우즈와 DirectDraw 의 고수준 ( 메시지 상자 , 메뉴 등 ) 과 저수준 ( 물체 그리기 , 텍스트 그리기 ) 혼합

Page 50: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

50

DirectDrawDirectDraw 에서 에서 GDIGDI 를 사용하기 위해 를 사용하기 위해 세 가지 선택 세 가지 선택 • 고수준 컨트롤의 경우

– GDC(Graphics Device Context; 그래픽 장치 컨텍스트 ) 를 이용하지 않고 , GDI 를 이용하는 가장 간단한 방법이다 . 대신 , 메시지 상자 , 대화상자 , 메뉴와 같은 고수준 컨트롤을 사용한다 . GDC 는 HDC(Handle to Device Context) 의 특수한 경우이다 .

• GDC 를 이용하는 경우– 임의의 표면에 그리기 위해 GDC( 비디오 모드 , 메모리 ,

해상도 , 색상 공간 등의 기술 ) 를 사용할 수 있다 . IDIRECTDRAWSURFACE7 의 함수를 이용하여 DirectDraw 로부터 GDC 를 요청한다 .

• 윈도우 모드의 경우– 표준 윈도우 모드를 이용하여 GDI 와 함께 DirectDraw 를

사용할 수 있다 . 이 책에 나오는 대부분의 그래픽을 이용하는 코드는 전체 비디오 표면을 위임받고 그래픽 모드를 변경한다 . 그러나 때때로 그렇게 하고 싶지 않을 수도 있고 , 표준 윈도우 모드에서 DirectDraw 를 이용하여 그릴 수도 있다 .

Page 51: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

51

연결하기연결하기

• 목적 표면의 GDI 작업을 위한 윈도우 핸들과 DirectDraw, 그리고 나머지를 해주는 윈도우즈가 필요하다 .

• 메시지 박스를 주표면의 비트맵 이미지 위에 표시하고 싶다면 // this will pop up a message box on top of the image

if (KEY_DOWN(‘M’))

{

// show the mouse cursor

ShowCursor(TRUE);

// display the GDI message box

MessageBox(main_window_handle,”What’s Up Baby!”,

“Message Box Test”,MB_OK);

// hide the mouse cursor

ShowCursor(FALSE);

} // end if

Page 52: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

52

DEMO: PROG11_5DEMO: PROG11_5

• Press ‘M’ for showing Message Box

Page 53: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

53

그리기 그리기 (1)(1)

• 그래픽 장치 컨텍스트 (GDC) 가 필요 • GDC 는 비디오 모드 , 메모리 , 해상도 , 색상 공간

등의 기술 (description) 에 불과 • 주표면이든 , 보조표면이든 혹은 작은 오프스크린

표면이든지 , 어느 표면에서든 GDC 를 얻을 수 있다 . • GDC 를 얻은 다음에는 표준 GDI 함수들을 이용해서

그 표면에 어떤 것이든 그릴 수 있다 .

Page 54: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

54

그리기 그리기 (2)(2)

HDC xdc; // a DirectX GDC handleHPEN old_pen, hpen; // pens used to drawlpddsback->GetDC(&xdc); // get the DirectDraw GDC handle from the surface// draw some linesfor (int index=0; index<100; index++) { // create a random colored pen hpen = CreatePen(PS_SOLID,1, RGB(rand()%256,rand()%256,rand()%256)); // select the pen into context old_hpen = (HPEN)SelectObject(xdc,hpen); // move to a random position MoveToEx(xdc, rand()%WINDOW_WIDTH, rand()%WINDOW_HEIGHT, NULL); // draw a line LineTo(hdc,rand()%WINDOW_WIDTH, rand()%WINDOW_HEIGHT); // now delete the pen SelectObject(xdc,old_hpen); DeleteObject(hpen);} // end for index// release the DirectDraw-compatible GDClpddsback->ReleaseDC(xdc);

Page 55: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

55

DEMO: PROG11_6DEMO: PROG11_6

• BOB 개체를 왼쪽에서 오른쪽으로 움직이고 , 그리고 GDI를 써서 BOB 개체 위에 문자열을 그린다 .

Page 56: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

56

윈도우 모드의 사용 윈도우 모드의 사용 (1) (1)

• 그저 하나의 주표면을 생성하고 , 그리고 윈도우의 클라이언트 영역에만 그린다 .

// create DirectDraw object

DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL);

// set cooperation level to windowed mode normal

lpdd->SetCooperativeLevel(main_window_handle,DDSCL_NORMAL);

// create the primary surface

memset(&ddsd,0,sizeof(ddsd));

ddsd.dwSize = sizeof(ddsd);

ddsd.dwFlags = DDSD_CAPS;

ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE ;

lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL);

Page 57: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

57

윈도우 모드의 사용 윈도우 모드의 사용 (2) (2)

• 윈도우의 좌표 얻기

Page 58: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

58

윈도우 모드의 사용 윈도우 모드의 사용 (3)(3)

• 256 색상 800x600 인 윈도우 모드에서 돌아가는 DirectDraw 응용 프로그램이 있다고 하자 .

• 윈도우 클라이언트 영역에만 그리고자 할 때

RECT ddclient; // holds the client area of the window// get the client rectangle of the DirectDraw windowGetWindowRect(main_window_handle, &ddclient);// lock the primary buffer into primary_buffer....// the starting address of the client area at pixel (0,0) isprimary_buffer[ddclient.left+ (ddclient.top*ddsd.lPitch)] = color;// and the bottom-right corner isprimary_buffer[ddclient.right+ (ddclient.bottom*ddsd.lPitch)] = color;// unlock primary surface....

Page 59: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

59

DEMO: PROG11_7DEMO: PROG11_7

• 윈도우 모드 DirectDRaw 윈도우에 랜덤하게 픽셀을 그린다 .

• 이 프로그램은 8 비트 , 16 비트 , 24 비트 , 그리고 32비트 그래픽 모드를 자동으로 감지한다 .

• 각 비트 깊이에 대한 픽셀을 그리는 코드를 살펴보도록 한다 .

Page 60: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

60

DirectDrawDirectDraw 가 알려주는 것들가 알려주는 것들

• Get_ 함수들 : GetCaps(), …. • GetCaps()

– 거의 모든 DirectDraw 인터페이스와 객체에는 GetCaps() 가 있다 .

HRESULT GetCaps(

LPDDCAPS lpDDDriverCaps, // hardware capabilities

LPDDCAPS lpDDHELCaps); // software-emulation capabilities

// these variables will store all the capabilities

DDCAPS HELddcaps, HALddcaps;

// get the capabilities

lpdd->GetCaps(&HALddcaps, &HELddcaps);

HALddcaps.dwVidMemTotal // total video memory

HALddcaps.dwVidMemFree // video memory free

Page 61: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

61

DirectDraw DirectDraw 표면 표면 GetCaps() GetCaps() 사용하기사용하기

DDSCAPS2 primaryddscaps; // used to hold the capabilities

// get the data

lpddsprimary->GetCaps(&primaryddscaps);

• 8 장에서 표면을 기술하는 DDSCAP2 구조체에 대해서 언급했다 .

Page 62: Chapter 11 DirectDraw 의 깊은 곳 : 보다 발전된 기능들. 2 이 장에서는 - 비트맵 그래픽으로 고급 작업 수행하기 - 오프스크린 표면 사용하기 -

62

DirectDraw DirectDraw 팔레트 객체에 팔레트 객체에 GetCaps() GetCaps()

DWORD pal_flags;

// make the call

lpddpal->GetCaps(&pal_flags);

// test the flags for 8-bit

if (pal_flags && DDPCAPS_8BIT)

{ /* do the dew */ }

Table 11-1: 팔레트 GetCaps Flags