Presentation is loading. Please wait.

Presentation is loading. Please wait.

Chapter 9 DirectDraw 크래용 사용하기

Similar presentations


Presentation on theme: "Chapter 9 DirectDraw 크래용 사용하기"— Presentation transcript:

1 Chapter 9 DirectDraw 크래용 사용하기

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

3 DirectDraw 표면 (Surface)
실제로 비디오 카드의 비디오 메모리와 직접 대응 표면은 어떤 크기도 될 수 있다. 주표면은 현재 화면 해상도와 같은 크기여야 한다. 그러나, 다른 표면은 어떤 크기라도 될 수 있다. 표면은 비디오 메모리에 (VRAM) 또는 시스템 메모리에 생성할 수 있다. 비트깊이와 색상공간이 같은 한, 모든 표면은 같은 속성을 갖는다.

4 DirectDraw Surface

5 Surfaces 주 디스플레이 표면(primary display surface)
보여지는 비디오 화면 자체, 비디오 카드의 비디오 메모리와 직접적으로 대응 보조 디스플레이 표면(secondary display surface) 후면버퍼(back buffer) 주표면과 같은 구조 내용은 화면에 보여지지 않는다. 애니메이션을 위해 다음 프레임을 렌더링 오프스크린 표면(offscreen surface) 이것은 하드웨어 가속을 이용해서 빠르게 그리고 싶은 비트맵, 스프라이트, 또는 스크린 아이템(예들 들어 캐릭터나 우주선 등)을 저장하는 표면이다.

6 Surfaces

7 주표면(Primary Surface) 사용하기
CreateSurface()를 호출 HRESULT CreateSurface( LPDDSURFACEDESC2 lpDDSurfaceDesc, LPDIRECTDRAWSURFACE7 FAR *lplpDDSurface, IUnknown FAR *pUnkOuter); lpDDSurfaceDesc: DirecDraw 표면을 기술하는 구조체의 포인터. 원하는 표면을 기술하는 여러 속성들을 이 포인터에 설정한다. lplpDDSurface: 성공하면 함수로부터 반환될 DirectDraw 표면의 인터페이스의 포인터이다. pUnkOuter: 심화된 기능으로, COM aggregation에 사용된다. 항상 NULL로 놓도록 한다.

8 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

9 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

10 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;

11 dwFlags 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.

12 Fields (1) dwSize: DDSURFACEDESC 구조체의 크기로 개발자가 꼭 설정해야 한다.
dwFlags: 유효한 속성 정보 플래그를 포함한다. 다른 말로 하면, 수정하거나 얻어오고 싶은 모든 속성을 논리적인 OR로 플래그 속성을 설정해야 한다. dwHeight: 픽셀단위의 표면의 높이이다. dwWidth: 픽셀단위의 표면의 폭이다. lpSurface: 표면이 잠그어질 때, 표면 VRAM을 가리키는 포인터이다. 잠그기(locking)는 표면 메모리의 일부분을 수정할 것이라고 DirectDraw에게 알리는 과정이다.

13 Fields (2) dwBackBufferCount: 오프스크린 버퍼나 페이지의 숫자를 지정한다. DirectDraw에서 여러 개의 표면을 생성할 수 있다. 따라서 한 표면을 표시하는 동안 다른 표면에 그림으로써 부드러운 애니메이션을 만들 수 있다. lPitch: 표면의 메모리 피치(memory pitch)로, 한 줄당 바이트 수를 말한다. ddCaps: 표면의 부가적인 기능(capability)들이다. typedef struct _DDSCAPS2 { DWORD dwCaps; DWORD dwCaps2; DWORD dwCaps3; DWORD dwCaps4; } DDSCAPS2, FAR* LPDDSCAPS2;

14 Fields (3) dwCaps: 표면에 부여되길 원하는 기능들을 저장한다. DDSCAPS_BACKBUFFER
표면이 전환 사슬(flipping chain)의 후면버퍼가 된다. DDSCAPS_COMPLEX 표면이 하나의 주표면 이상을 갖는 복잡한 표면의 일부가 된다. DDSCAPS_FLIP 표면이 플립 가능하다. DDSCAPS_FRONTBUFFER 표면이 전환 구조에서 첫번째, 혹은 전면버퍼(frontbuffer)가 된다. DDSCAPS_MODEX 표면이 320x200이나 320x240 모드 X 표면이다. DDSCAPS_OFFSCREENPLAIN 표면이 오버레이, 텍스쳐, z-버퍼, 전면버퍼, 후면버퍼, 알파 표면이 아닌 오프스크린 표면이 된다. 보통 스프라이트나 비트맵에 사용한다.

15 Fields (4) DDSCAPS_OWNDC DDSCAPS_PRIMARYSURFACE
표면이 장시간 윈도우즈 장치 컨텍스트와의 연관을 갖는다. DDSCAPS_PRIMARYSURFACE 표면이 주표면이다. 즉, 보여지고 렌더링된다. DDSCAPS_STANDARDVGAMNODE 표면이 표준 VGA 모드 표면이며, 모드X 표면이 아니다. DDSCAPS_SYSTEMMEMORY 표면이 시스템 메모리에 할당된다.

16 주표면 생성하기 - 1 // pointer to DirectDraw object LPDIRECTDRAW7 lpdd;
// used to hold the DirectDraw surface description DDSURFACEDESC2 ddsd; // where the interface pointer will be placed // when the surface is created LPDIRECTDRAWSURFACE7 lpddsprimary; // create DirectDraw object DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL); // set cooperation level lpdd->SetCooperativeLevel(hwnd, DDSCL_ALLOWREBOOT | DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE ); // now set the display mode; assume constants defined lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT, SCREEN_BPP,0,0);

17 주표면 생성하기 - 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 */ }

18 COM Interface Release // first release the surface, but check for NULL
if (lpddsprimary) lpddsprimary->Release(); // now release the DirectDraw object itself if (lpdd) lpdd->Release();

19 PROG9_1.CPP 800x600x16 모드

20 Linear 640 x 480 x 256-color mode.

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 *y] = color;

22 The memory mapping of the primary surface

23 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;

24 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 바이트

25 주표면 렌더링 DirectDraw는 디자인상 렌더링을 아주 조금 지원한다.
대부분의 게임 프로그래머는 자신의 그래픽스 엔진과 라이브러리를 작성한다. 따라서 DirectDraw는 게임 프로그래머에게 기본적인 색상 지원, 비디오 버퍼 접근, 하드웨어를 이용한 고속 채움(filling) 및 블리팅(blitting)을 제공한다.

26 팔레트 모드 각 픽셀은 한 바이트로 표현 각 바이트는 실제 RGB 값을 가지고 있는 색상조사표(CLUT)의 인덱스 순서
Lock() Write or Read Unlock() Lock HRESULT Lock( LPRECT lpDestRect, // rectangle to lock; use NULL to lock // the entire surface LPDDSURFACEDESC2 lpDDSD, // returns the properties of the surface being locked DWORD dwFlags, // control flags HANDLE hEvent); // unused; set to NULL

27 Flags for Lock() Table 9-3 Flags for Lock() Value Meaning
DDLOCK_READONLY The surface locked is readable only. DDLOCK_SURFACEMEMORYPTR The surface locked 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.

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

29 8-bit Example (1) 표준 DirectDraw 호출로 (x,y) 픽셀에 col 색상으로 점을 찍는 예제
// pointer to DirectDraw object LPDIRECTDRAW7 lpdd; // you use this function to access the surface memory UCHAR video_buffer = NULL; // used to hold the DirectDraw surface description DDSURFACEDESC2 ddsd; // primary surface LPDIRECTDRAWSURFACE7 lpddsprimary; // create DirectDraw object DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL); // set cooperation level lpdd->SetCooperativeLevel(hwnd, DDSCL_ALLOWREBOOT | DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE );

30 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);

31 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);

32 PROG9_2.CPP

33 16bit Mode 형식 alpha 1 bit red, green, blue 각각 5 bits 5.6.5 형식 red 5 bits green 6 bits (사람의 눈은 green에 가장 민감) blue 5 bits 일반적으로 90% 이상의 video card들은 형식을 사용한다.

34 RGB Mode Macro (1) Result = _RGB16BIT(red,green,blue) // 5.5.5 format
#define _RGB16BIT(r,g,b) ((b%32)+((g%32)<<5)+((r%32)<<10)) example) UCHAR red = 0x // UCHAR green = 0x // UCHAR blue = 0x1b // Result = _RGB16BIT(red,green,blue) (blue % 32) = (green % 32) << 5 = ( ) << 5 = (red % 32) << 10 = ( ) << 10 = Result = = 0 (11000) (00101) (11011)

35 RGB Mode Macro (2) Result = _RGB16BIT555(red,green,blue)
// this builds a 16 bit color value in format (1-bit alpha mode) #define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10)) example) UCHAR red = 0x // UCHAR green = 0x // UCHAR blue = 0x1b // Result = _RGB16BIT555(red,green,blue) (blue & 31) = ( ) & ( ) = (green & 31) << 5 = ( ) << 5 = (red & 31) << 10 = ( ) << 10 = Result = = 0 (11000) (00101) (11011)

36 RGB Mode Macro (3) // this builds a 16 bit color value in format (green dominate mode) #define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))

37 16bit Mode로 그리기 640x480x16 모드에서 (x, y) 위치에 (r, g, b) 색상으로 그리는 예제
memset(&ddsd,0,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); // lock the primary surface lpddsprimary->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL); // get video pointer video_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 USHORT // pointers and lPitch is always in bytes video_buffer[x + (y*ddsd.lPitch >> 1)]= (USHORT)_RGB16BIT565(r,g,b); // unlock the surface lpddsprimary->Unlock(NULL);

38 Why lPitch >> 1 // pointers and lPitch is always in bytes
video_buffer[x + (y*ddsd.lPitch >> 1)]= (USHORT)_RGB16BIT565(r,g,b); USHORT를 사용할 때 모든 포인터 연산은 16비트로 이루어지지만, lPitch는 항상 바이트로 표현되기 때문이다.

39 DEMO: PROG9_3.CPP PROG9_2_16.cpp 와 다른 점은 무엇인가?

40 24비트나 32비트 표면 #define _RGB24BIT(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) ) 24bit 는 32bit 중 최상위 8bit가 사용되지 않을 뿐이다. 따라서 bpp를 32로 하는 것이 좋다.

41 24, 32bit 이용 (1) In Game_Init()
if (lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT,32,0,0)!=DD_OK) return(0);

42 24, 32bit 이용 (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);

43 보조표면(Secondary Surface)
보조 표면(또는 후면버퍼) 의 사용 부드러운 애니메이션 1. 주표면을 생성하고, 주표면으로부터 하나의 보조표면을 생성한다. 2. 주표면이 보여지는 동안 보조표면에 그린다. 3. 순간적으로 표면을 바꾸어서(switch or flip), 보조표면이 주표면이 되게 하여, (그 반대로도 마찬가지) 부드러운 애니메이션을 만든다.

44 Page Flipping

45 보조표면의 생성 (1) // DirectDraw surface description DDSURFACEDESC2 ddsd;
// device capabilities structure, used to query for // secondary backbuffer, among other things DDSCAPS2 ddscaps; LPDIRECTDRAWSURFACE7 lpddsprimary, // primary surface lpddssecondary; // secondary backbuffer surface // prepare to create primary surface with one backbuffer memset((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 field ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; // you need to let dd know that you want a complex flippable surface structure;

46 보조표면의 생성 (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);

47 주표면과 부표면

48 Rendering 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);

49 Flipping // flip the primary and secondary surfaces
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);

50 Flipping 전후

51 오프스크린 표면(off-screen surface)
시스템 메모리나 VRAM에 모두 존재할 수 있음 주표면과 같은 색상깊이와 속성을 가지는 비트맵 스프라이트 간단히 말해서 비디오 게임 화면에서 움직이는 작은 물체를 뜻한다. 대부분의 경우, 스프라이트는 비트맵일 뿐 애플 II 프로그래머들에 의해 사용된 용어

52 VRAM에 오프스크린 표면 생성 // .. assume DirectDraw has been set up and so on
DDSURFACEDESC2 ddsd; // a DirectDraw surface descriptor LPDIRECTDRAWSURFACE7 lpwork; // the working surface // set the size parameter as always memset(&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 valid ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; // set dimensions of the new surface ddsd.dwWidth = width; ddsd.dwHeight = height; // what kind of offscreen surface, system memory, or VRAM // default is VRAM ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; // now create the surface and check for error if (lpdd->CreateSurface(&ddsd,&lpwork,NULL)!=DD_OK) { /* error */ }

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 */ }

54 팔레트… 생략.


Download ppt "Chapter 9 DirectDraw 크래용 사용하기"

Similar presentations


Ads by Google