54
Chapter 9 Chapter 9 DirectDraw DirectDraw 크크크 크크크크 크크크 크크크크

Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

Embed Size (px)

Citation preview

Page 1: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

Chapter 9Chapter 9

DirectDraw DirectDraw 크래용 사용하기 크래용 사용하기

Page 2: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

2

이 장에서는이 장에서는 ... ...

• 표면 생성하기• 색상 팔레트 다루기• DirectDraw 로 그리기

Page 3: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

3

DirectDraw DirectDraw 표면 표면 (Surface)(Surface)

• 실제로 비디오 카드의 비디오 메모리와 직접 대응 • 표면은 어떤 크기도 될 수 있다 . 주표면은 현재 화면

해상도와 같은 크기여야 한다 . 그러나 , 다른 표면은 어떤 크기라도 될 수 있다 .

• 표면은 비디오 메모리에 (VRAM) 또는 시스템 메모리에 생성할 수 있다 .

• 비트깊이와 색상공간이 같은 한 , 모든 표면은 같은 속성을 갖는다 .

Page 4: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

4

DirectDraw SurfaceDirectDraw Surface

Page 5: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

5

SurfacesSurfaces

• 주 디스플레이 표면 (primary display surface)– 보여지는 비디오 화면 자체 , 비디오 카드의 비디오 메모리와

직접적으로 대응

• 보조 디스플레이 표면 (secondary display surface)– 후면버퍼 (back buffer) – 주표면과 같은 구조– 내용은 화면에 보여지지 않는다 . – 애니메이션을 위해 다음 프레임을 렌더링

• 오프스크린 표면 (offscreen surface)– 이것은 하드웨어 가속을 이용해서 빠르게 그리고 싶은 비트

맵 , 스프라이트 , 또는 스크린 아이템 ( 예들 들어 캐릭터나 우주선 등 ) 을 저장하는 표면이다 .

Page 6: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

6

SurfacesSurfaces

Page 7: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

7

주표면주표면 (Primary Surface) (Primary Surface) 사용하기 사용하기

• CreateSurface() 를 호출 HRESULT CreateSurface(

LPDDSURFACEDESC2 lpDDSurfaceDesc,

LPDIRECTDRAWSURFACE7 FAR *lplpDDSurface,

IUnknown FAR *pUnkOuter);

– lpDDSurfaceDesc: DirecDraw 표면을 기술하는 구조체의 포인터 . 원하는 표면을 기술하는 여러 속성들을 이 포인터에 설정한다 .

– lplpDDSurface: 성공하면 함수로부터 반환될 DirectDraw 표면의 인터페이스의 포인터이다 .

– pUnkOuter: 심화된 기능으로 , COM aggregation 에 사용된다 . 항상 NULL 로 놓도록 한다 .

Page 8: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

8

DDSURFACEDESC structure (1)DDSURFACEDESC structure (1)

typedef struct _DDSURFACEDESC2 { DWORD dwSize; // the size of this structure in bytes // this field must be set by you DWORD dwFlags; // flags field indicating which fields // of this structure are valid with data DWORD dwHeight; // width of surface DWORD dwWidth; // height of surface union { LONG lPitch; // number of bytes per line DWORD dwLinearSize; // used for compression } DUMMYUNIONNAMEN(1); DWORD dwBackBufferCount; // number of back buffers

Page 9: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

9

DDSURFACEDESC structure (2) DDSURFACEDESC structure (2)

union

{

DWORD dwMipMapCount; // number of mip levels

DWORD dwRefreshRate; // refresh rate in hz

} DUMMYUNIONNAMEN(2);

DWORD dwAlphaBitDepth; // number of bits for alpha

DWORD dwReserved;

LPVOID lpSurface; // pointer to surface memory

Page 10: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

10

DDSURFACEDESC structure (3)DDSURFACEDESC structure (3)

union { DDCOLORKEY ddckCKDestOverlay; // color key for // destination overlay DWORD dwEmptyFaceColor; // 3d stuff } DUMMYUNIONNAMEN(3); DDCOLORKEY ddckCKDestBlt; // color key for // destination blit DDCOLORKEY ddckCKSrcOverlay; // color key for overlay DDCOLORKEY ddckCKSrcBlt; // color key for source blit DDPIXELFORMAT ddpfPixelFormat; // general pixel format DDSCAPS2 ddsCaps; // capabilities bits DWORD dwTextureStage; // 3d stuff} DDSURFACEDESC2, FAR* LPDDSURFACEDESC2;

Page 11: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

11

dwFlagsdwFlags

• DDSD_ALL All input members are valid.• DDSD_ALPHABITDEPTH dwAlphaBitDepth member is valid.• DDSD_BACKBUFFERCOUNT dwBackBufferCount member is valid.• DDSD_CAPS ddsCaps member is valid.• DDSD_CKDESTBLT ddckCKDestBlt member is valid.• DDSD_CKDESTOVERLAY ddckCKDestOverlay member is valid.• DDSD_CKSRCBLT ddckCKSrcBlt member is valid.• DDSD_CKSRCOVERLAY ddckCKSrcOverlay member is valid.• DDSD_HEIGHT dwHeight member is valid.• DDSD_LINEARSIZE Unused.• DDSD_LPSURFACE lpSurface member is valid.• DDSD_MIPMAPCOUNT dwMipMapCount member is valid.• DDSD_PITCH lPitch member is valid.• DDSD_PIXELFORMAT ddpfPixelFormat member is valid.• DDSD_REFRESHRATE dwRefreshRate member is valid.• DDSD_WIDTH dwWidth member is valid.• DDSD_ZBUFFERBITDEPTH dwZBufferBitDepth member is valid.

Page 12: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

12

Fields (1)Fields (1)

• dwSize: DDSURFACEDESC 구조체의 크기로 개발자가 꼭 설정해야 한다 .

• dwFlags: 유효한 속성 정보 플래그를 포함한다 . 다른 말로 하면 , 수정하거나 얻어오고 싶은 모든 속성을 논리적인 OR 로 플래그 속성을 설정해야 한다 .

• dwHeight: 픽셀단위의 표면의 높이이다 .• dwWidth: 픽셀단위의 표면의 폭이다 .• lpSurface: 표면이 잠그어질 때 , 표면 VRAM 을

가리키는 포인터이다 . 잠그기 (locking) 는 표면 메모리의 일부분을 수정할 것이라고 DirectDraw 에게 알리는 과정이다 .

Page 13: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

13

Fields (2)Fields (2)

• dwBackBufferCount: 오프스크린 버퍼나 페이지의 숫자를 지정한다 . DirectDraw 에서 여러 개의 표면을 생성할 수 있다 . 따라서 한 표면을 표시하는 동안 다른 표면에 그림으로써 부드러운 애니메이션을 만들 수 있다 .

• lPitch: 표면의 메모리 피치 (memory pitch) 로 , 한 줄당 바이트 수를 말한다 .

• ddCaps: 표면의 부가적인 기능 (capability) 들이다 .typedef struct _DDSCAPS2 {

DWORD dwCaps;

DWORD dwCaps2;

DWORD dwCaps3;

DWORD dwCaps4;

} DDSCAPS2, FAR* LPDDSCAPS2;

Page 14: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

14

Fields (3)Fields (3)

• dwCaps: 표면에 부여되길 원하는 기능들을 저장한다 . – DDSCAPS_BACKBUFFER

• 표면이 전환 사슬 (flipping chain) 의 후면버퍼가 된다 .

– DDSCAPS_COMPLEX• 표면이 하나의 주표면 이상을 갖는 복잡한 표면의 일부가 된다 .

– DDSCAPS_FLIP• 표면이 플립 가능하다 .

– DDSCAPS_FRONTBUFFER• 표면이 전환 구조에서 첫번째 , 혹은 전면버퍼 (frontbuffer) 가

된다 .

– DDSCAPS_MODEX• 표면이 320x200 이나 320x240 모드 X 표면이다 .

– DDSCAPS_OFFSCREENPLAIN• 표면이 오버레이 , 텍스쳐 , z- 버퍼 , 전면버퍼 , 후면버퍼 , 알파

표면이 아닌 오프스크린 표면이 된다 . 보통 스프라이트나 비트맵에 사용한다 .

Page 15: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

15

Fields (4)Fields (4)

– DDSCAPS_OWNDC• 표면이 장시간 윈도우즈 장치 컨텍스트와의 연관을 갖는다 .

– DDSCAPS_PRIMARYSURFACE• 표면이 주표면이다 . 즉 , 보여지고 렌더링된다 .

– DDSCAPS_STANDARDVGAMNODE• 표면이 표준 VGA 모드 표면이며 , 모드 X 표면이 아니다 .

– DDSCAPS_SYSTEMMEMORY• 표면이 시스템 메모리에 할당된다 .

Page 16: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

16

주표면 생성하기 주표면 생성하기 - 1 - 1

// pointer to DirectDraw objectLPDIRECTDRAW7 lpdd;// used to hold the DirectDraw surface descriptionDDSURFACEDESC2 ddsd;// where the interface pointer will be placed// when the surface is createdLPDIRECTDRAWSURFACE7 lpddsprimary;// create DirectDraw objectDirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL);// set cooperation levellpdd->SetCooperativeLevel(hwnd, DDSCL_ALLOWREBOOT | DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE );// now set the display mode; assume constants definedlpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT, SCREEN_BPP,0,0);

Page 17: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

17

주표면 생성하기 주표면 생성하기 - 2- 2

// create the primary surface

// manually set the size; very important

ddsd.dwSize = sizeof(ddsd);

// the only field you modify, so you must indicate in the flags

// that you want a primary drawing surface; in this case, you don’t have

// to define anything else, because DirectDraw already knows the

// resolution and color of the video mode

ddsd.dwFlags = DDSD_CAPS;

// set the capabilities to what you want, a primary surf

ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

// create the surface and check for an error

if (lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL)!=DD_OK)

{ /* error */ }

Page 18: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

18

COM Interface ReleaseCOM Interface Release

// first release the surface, but check for NULL

if (lpddsprimary)

lpddsprimary->Release();

// now release the DirectDraw object itself

if (lpdd)

lpdd->Release();

Page 19: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

19

PROG9_1.CPP PROG9_1.CPP

• 800x600x16 모드

Page 20: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

20

Linear 640 x 480 x 256-color mode.Linear 640 x 480 x 256-color mode.

Page 21: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

21

비디오의 다음 줄을 얻기 위해서 비디오의 다음 줄을 얻기 위해서

• 640 을 더하는 대신에 , 1,024 같은 숫자를 더해야 할 수도 있다 . ( 이 수를 lpitch 라고 하며 video card 마다 다르다 .)

UCHAR *video_buffer;

// point video buffer to primary surface...

// (check out the section “The details of rendering to the primary surface”

// for this code)

// write a single pixel; color is a palette index

video_buffer[x + 1024*y] = color;

Page 22: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

22

The memory mapping of the primary The memory mapping of the primary surface surface

Page 23: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

23

640 x 480 x 8 mode 640 x 480 x 8 mode

// used to access data

UCHAR *video_buffer;

// point video_buffer to primary surface...

// check out the section “The details of rendering to the primary surface”

// for this code

// write a single pixel; color is a palette index

video_buffer[x + 640*y] = color;

Page 24: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

24

640 x 480 x 16-bit color mode 640 x 480 x 16-bit color mode

// this time, use a 16-bit short

USHORT *video_buffer;

// point video buffer to primary surface...

// write a single pixel; color is a palette index

video_buffer[x + 640*y] = color;

• RGB 값 ( 각각 5 비트 ) • 픽셀당 2 바이트 • 각 줄은 1,280 바이트

Page 25: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

25

주표면 렌더링 주표면 렌더링

• DirectDraw 는 디자인상 렌더링을 아주 조금 지원한다 . • 대부분의 게임 프로그래머는 자신의 그래픽스 엔진과

라이브러리를 작성한다 . • 따라서 DirectDraw 는 게임 프로그래머에게 기본적인

– 색상 지원 , – 비디오 버퍼 접근 , – 하드웨어를 이용한 고속 채움 (filling) 및 블리팅 (blitting) 을

제공한다 .

Page 26: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

26

팔레트 모드팔레트 모드

• 각 픽셀은 한 바이트로 표현 • 각 바이트는 실제 RGB 값을 가지고 있는 색상조사표

(CLUT) 의 인덱스 • 순서

– Lock()– Write or Read– Unlock()

• LockHRESULT Lock(LPRECT lpDestRect, // rectangle to lock; use NULL to lock // the entire surfaceLPDDSURFACEDESC2 lpDDSD, // returns the properties of the su

rface being lockedDWORD dwFlags, // control flagsHANDLE hEvent); // unused; set to NULL

Page 27: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

27

Flags for Lock()Flags for Lock()

• Table 9-3 Flags for Lock()• Value Meaning• DDLOCK_READONLY The surface locked is reada

ble only.• DDLOCK_SURFACEMEMORYPTR The surface l

ocked returns a memory pointer to the surface memory in lpSurface. This default action takes place if you don’t send any flags.

• DDLOCK_WAIT If the surface can’t be locked, wait until it can be.

• DDLOCK_WRITEONLY The surface being locked is written to only.

Page 28: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

28

UnlockUnlock

• HRESULT Unlock(LPRECT lpRect); // pointer to rectangle to unlock

Page 29: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

29

8-bit Example (1)8-bit Example (1)

• 표준 DirectDraw 호출로 (x,y) 픽셀에 col 색상으로 점을 찍는 예제

// pointer to DirectDraw objectLPDIRECTDRAW7 lpdd;// you use this function to access the surface memoryUCHAR video_buffer = NULL;// used to hold the DirectDraw surface descriptionDDSURFACEDESC2 ddsd;// primary surfaceLPDIRECTDRAWSURFACE7 lpddsprimary;// create DirectDraw objectDirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL);// set cooperation levellpdd->SetCooperativeLevel(hwnd, DDSCL_ALLOWREBOOT | DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE );

Page 30: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

30

8-bit Example (2)8-bit Example (2)

// now set the display mode to 800 x 600 x 256

lpdd->SetDisplayMode(800,600,8,0,0);

// set up data structure to create the primary surface

ddsd.dwSize = sizeof(ddsd);

ddsd.dwFlags = DDSD_CAPS;

ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

// create the primary surface

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

// set up the surface description to lock the surface

// zero out the data structure and set its size

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

ddsd.dwSize = sizeof(ddsd);

Page 31: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

31

8-bit Example (3)8-bit Example (3)

// lock the primary surface

lpddsprimary->Lock(NULL,&ddsd,

DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);

// get video pointer

video_buffer = (UCHAR *)ddsd.lpSurface;

//.. use video pointer to write to memory

// notice the use of lPitch (linear pitch)

video_buffer[x + y*ddsd.lPitch] = col;

// unlock the surface

lpddsprimary->Unlock(NULL);

Page 32: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

32

PROG9_2.CPPPROG9_2.CPP

Page 33: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

33

16bit Mode16bit Mode

• 1.5.5.5 형식– alpha 1 bit– red, green, blue 각각 5 bits

• 5.6.5 형식 – red 5 bits– green 6 bits ( 사람의 눈은 green 에 가장 민감 )– blue 5 bits

• 일반적으로 90% 이상의 video card 들은 5.6.5 형식을 사용한다 .

Page 34: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

34

RGB Mode Macro (1)RGB Mode Macro (1)

// 5.5.5 format

#define _RGB16BIT(r,g,b) ((b%32)+((g%32)<<5)+((r%32)<<10))

example)

UCHAR red = 0x08 // 0000 1000

UCHAR green = 0x05 // 0000 0101

UCHAR blue = 0x1b // 0001 1011

Result = _RGB16BIT(red,green,blue)– (blue % 32) = 0001 1011

– (green % 32) << 5 = (0000 0101) << 5 = 1010 0000

– (red % 32) << 10 = (0001 1000) << 10 = 0110 0000 0000 0000

Result = 0110 0000 1011 1011 = 0 (11000) (00101) (11011)

Page 35: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

35

RGB Mode Macro (2)RGB Mode Macro (2)

// this builds a 16 bit color value in 1.5.5.5 format (1-bit alpha mode)

#define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10))

example)

UCHAR red = 0x08 // 0000 1000

UCHAR green = 0x05 // 0000 0101

UCHAR blue = 0x1b // 0001 1011

Result = _RGB16BIT555(red,green,blue)– (blue & 31) = (0001 1011) & (0001 1111) = 0001 1011

– (green & 31) << 5 = (0000 0101) << 5 = 1010 0000

– (red & 31) << 10 = (0001 1000) << 10 = 0110 0000 0000 0000

Result = 0110 0000 1011 1011 = 0 (11000) (00101) (11011)

Page 36: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

36

RGB Mode Macro (3)RGB Mode Macro (3)

// this builds a 16 bit color value in 5.6.5 format (green dominate mode)

#define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))

Page 37: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

37

16bit Mode16bit Mode 로 그리기로 그리기• 640x480x16 모드에서 (x, y) 위치에 (r, g, b) 색상으로 그리는 예제

memset(&ddsd,0,sizeof(ddsd));ddsd.dwSize = sizeof(ddsd);// lock the primary surfacelpddsprimary->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);// get video pointervideo_buffer = (USHORT *)ddsd.lpSurface;// use video pointer to write to memory..// notice the use of lPitch (linear pitch) and the division by 2 (>>1);// this is needed to keep the addressing correct because you’re using USHO

RT// pointers and lPitch is always in bytesvideo_buffer[x + (y*ddsd.lPitch >> 1)]= (USHORT)_RGB16BIT565(r,g,b);// unlock the surfacelpddsprimary->Unlock(NULL);

Page 38: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

38

Why lPitch >> 1Why lPitch >> 1

// pointers and lPitch is always in bytes

video_buffer[x + (y*ddsd.lPitch >> 1)]=

(USHORT)_RGB16BIT565(r,g,b);

• USHORT 를 사용할 때 모든 포인터 연산은 16 비트로 이루어지지만 , lPitch 는 항상 바이트로 표현되기 때문이다 .

Page 39: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

39

DEMO: PROG9_3.CPPDEMO: PROG9_3.CPP

• PROG9_2_16.cpp 와 다른 점은 무엇인가 ?

Page 40: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

40

2424 비트나 비트나 3232 비트 표면 비트 표면

#define _RGB24BIT(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) )

24bit 는 32bit 중 최상위 8bit 가 사용되지 않을 뿐이다 .

따라서 bpp 를 32 로 하는 것이 좋다 .

Page 41: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

41

24, 32bit 24, 32bit 이용 이용 (1)(1)

• In Game_Init()if (lpdd->SetDisplayMode(SCREEN_WIDTH,

SCREEN_HEIGHT,32,0,0)!=DD_OK) return(0);

Page 42: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

42

24, 32bit 24, 32bit 이용 이용 (2)(2)

• Game_Main()

UINT *video_buffer = NULL;

video_buffer = (UINT *)ddsd.lpSurface;

int words_per_line = (ddsd.lPitch >> 2);

UCHAR red = rand()%256;

UCHAR green = rand()%256;

UCHAR blue = rand()%256;

video_buffer[x + (y*words_per_line)] = _RGB24BIT(red,green,blue);

Page 43: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

43

보조표면보조표면 (Secondary Surface) (Secondary Surface)

• 보조 표면 ( 또는 후면버퍼 ) 의 사용– 부드러운 애니메이션

– 1. 주표면을 생성하고 , 주표면으로부터 하나의 보조표면을 생성한다 .

– 2. 주표면이 보여지는 동안 보조표면에 그린다 .– 3. 순간적으로 표면을 바꾸어서 (switch or flip), 보조표면이

주표면이 되게 하여 , ( 그 반대로도 마찬가지 ) 부드러운 애니메이션을 만든다 .

Page 44: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

44

Page Flipping Page Flipping

Page 45: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

45

보조표면의 생성 보조표면의 생성 (1)(1)

// DirectDraw surface descriptionDDSURFACEDESC2 ddsd;// device capabilities structure, used to query for// secondary backbuffer, among other thingsDDSCAPS2 ddscaps;LPDIRECTDRAWSURFACE7 lpddsprimary, // primary surface lpddssecondary; // secondary backbuffer surface// prepare to create primary surface with one backbuffermemset((void *)&ddsd,0,sizeof(ddsd));ddsd.dwSize = sizeof(ddsd); // DDSURFACEDESC would work, too// set the flags to validate both the capabilities// field and the backbuffer count fieldddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;// you need to let dd know that you want a complex flippable surface

structure;

Page 46: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

46

보조표면의 생성 보조표면의 생성 (2)(2)

// set flags for that

ddsd.ddsCaps.dwCaps =

DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;

// set the backbuffer count to 1

ddsd.dwBackBufferCount = 1;

// create the primary surface

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

// query for the backbuffer or secondary surface

// notice the use of ddscaps to indicate what you’re requesting

ddscaps.dwCaps = DDSCAPS_BACKBUFFER;

// get the surface

lpddsprimary->GetAttachedSurface(&ddscaps,&lpddsback);

Page 47: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

47

주표면과 부표면주표면과 부표면

Page 48: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

48

Rendering BackbufferRendering Backbuffer

// used to access secondary video buffer

UCHAR *video_buffer;

// lock the secondary surface

lpddsback->Lock(NULL,&ddsd,

DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);

// draw on the surface: ddsd.lpSurface and

// ddsd.lPitch are valid as before

video_buffer = (UCHAR *)ddsd.lpSurface;

// unlock the surface

lpddsback->Unlock(NULL);

Page 49: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

49

FlippingFlipping

HRESULT Flip(

LPDIRECTDRAWSURFACE7 lpDDSurfaceOverride, // always NULL

DWORD dwFlags); // always DDFLIP_WAIT

// flip the primary and secondary surfaces

while(lpddsprimary->Flip(NULL, DDFLIP_WAIT)!=DD_OK);

Page 50: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

50

Flipping Flipping 전후전후

Page 51: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

51

오프스크린 표면오프스크린 표면 (off-screen surface) (off-screen surface)

• 시스템 메모리나 VRAM 에 모두 존재할 수 있음• 주표면과 같은 색상깊이와 속성을 가지는 비트맵 • 스프라이트

– 간단히 말해서 비디오 게임 화면에서 움직이는 작은 물체를 뜻한다 . 대부분의 경우 , 스프라이트는 비트맵일 뿐

– 애플 II 프로그래머들에 의해 사용된 용어

Page 52: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

52

VRAMVRAM 에 오프스크린 표면 생성에 오프스크린 표면 생성

// .. assume DirectDraw has been set up and so onDDSURFACEDESC2 ddsd; // a DirectDraw surface descriptorLPDIRECTDRAWSURFACE7 lpwork; // the working surface// set the size parameter as alwaysmemset(&ddsd,0,sizeof(ddsd));ddsd.dwSize = sizeof(ddsd);// set the flags; very important// remember that you must set the flags of the fields that will be validddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;// set dimensions of the new surfaceddsd.dwWidth = width;ddsd.dwHeight = height;// what kind of offscreen surface, system memory, or VRAM// default is VRAMddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;// now create the surface and check for errorif (lpdd->CreateSurface(&ddsd,&lpwork,NULL)!=DD_OK){ /* error */ }

Page 53: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

53

시스템 메모리에 시스템 메모리에

// set flags for an offscreen plain system memory surface

ddsd.ddsCaps.dwCaps =

DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;

// now create the surface and check for error

if (lpdd->CreateSurface(&ddsd,&lpwork,NULL)!=DD_OK)

{ /* error */ }

Page 54: Chapter 9 DirectDraw 크래용 사용하기. 2 이 장에서는... 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기

54

팔레트…팔레트…

• 생략 .