1 / 54

Chapter 9 DirectDraw 크래용 사용하기

Chapter 9 DirectDraw 크래용 사용하기 . 이 장에서는 ... . 표면 생성하기 색상 팔레트 다루기 DirectDraw 로 그리기. DirectDraw 표면 (Surface). 실제로 비디오 카드의 비디오 메모리와 직접 대응 표면은 어떤 크기도 될 수 있다 . 주표면은 현재 화면 해상도와 같은 크기여야 한다 . 그러나 , 다른 표면은 어떤 크기라도 될 수 있다 . 표면은 비디오 메모리에 (VRAM) 또는 시스템 메모리에 생성할 수 있다 .

dewei
Télécharger la présentation

Chapter 9 DirectDraw 크래용 사용하기

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 9DirectDraw 크래용 사용하기

  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_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 + 1024*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 • 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 형식을 사용한다.

  34. 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)

  35. 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)

  36. 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))

  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 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 전후

More Related