Copyright by In-Kwon Lee 2003 2
In this Chapter…In this Chapter…
• - 하드웨어 가속을 위한 DirectDraw 사용하기• - 애니메이션• - 비트맵 불러오기• - 블리터 (blitter) 사용하기
Copyright by In-Kwon Lee 2003 3
부드러운 애니메이션 테크닉부드러운 애니메이션 테크닉
• 페이지 전환 ( 플리핑 ;flipping)• 더블 버퍼링 (double bufferin
g)
Copyright by In-Kwon Lee 2003 4
Double BufferingDouble Buffering
• 충분한 비디오 메모리가 없다면 DirectX 가 대신 페이지 전환을 시뮬레이트하여 double buffering 을 사용
• 우리들은 그 차이를 알지 못한다 .
Copyright by In-Kwon Lee 2003 5
DEMO: PROG10_1DEMO: PROG10_1
• Double buffering 을 프로그래머가 해 준 경우 . • Lpitch = screenwidth 인 경우와 아닌 경우를 달리
처리하였음 .
Copyright by In-Kwon Lee 2003 6
페이지 전환페이지 전환 (flipping) - 1 (flipping) - 1
• DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX 사용
• 후면버퍼 카운트를 1 로 DDSURFACEDESC2 ddsd;DDSCAPS2 ddscaps;LPDIRECTDRAWSURFACE7 lpddsprimary, // primary surface lpddssecondary; // secondary backbuffer surfacememset(ddsd,0,sizeof(ddsd));ddsd.dwSize = sizeof(ddsd);ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_
COMPLEX;ddsd.dwBackBufferCount = 1;lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL);
Copyright by In-Kwon Lee 2003 7
페이지 전환페이지 전환 (flipping) - 2(flipping) - 2
// 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);
….
// flip the primary and secondary surfaces
while(lpddsprimary->Flip(NULL, DDFLIP_WAIT)!=DD_OK);
Copyright by In-Kwon Lee 2003 8
DEMO PROG10_2DEMO PROG10_2
• PROG10_1 의 double buffering 에 비해 한결 간단하다 .
Copyright by In-Kwon Lee 2003 9
블리터블리터 (Blitter)(Blitter)
• 이미지를 한 곳에서 다른 곳으로 ( 보통 주표면 ) 비트맵 이미지를 복사하기 위해 비트 블리터 (bit blitter) 하드웨어를 사용 .
• 비트맵이 스케일 되고 회전되거나 , 혹은 다른 효과들을 처리하도록 요청할 수 있다 .
• 메모리의 일부분을 특정한 값으로 간단하게 채울 수 있다 .
Copyright by In-Kwon Lee 2003 10
Blitter Blitter 함수함수
• Blt(): 화면의 모서리에 클리핑되는 것을 고려하지 않을 때
• BltFast(): 화면의 모서리에 클리핑되는 것을 고려할 때
Copyright by In-Kwon Lee 2003 11
Blt()Blt()
HRESULT Blt(
LPRECT lpDestRect, // the destination rectangle
LPDIRECTDRAWSURFACE7 lpDDSrcSurf, // the source surface
LPRECT lpSrcRect, // the source rectangle
DWORD dwFlags, // control flags
LPDDBLTFX lpDDBltFx); // the special fx structure
Copyright by In-Kwon Lee 2003 13
Blt FlagsBlt FlagsValue Meaning
DDBLT_COLORFILL Uses the dwFillColor member of the DDBLTFX structure as the RGB color that fills the destination rectangle on the destination surface.
DDBLT_DDFX Uses the dwDDFX member of the DDBLTFX structure to specify the effects to use for this blit.
DDBLT_DDROPS Uses the dwDDROPS member of the DDBLTFX structure to specify the raster operations (ROPs) that are not part of the Win32 API.
DDBLT_KEYDEST Uses the color key associated with the destination surface.
DDBLT_KEYSRC Uses the color key associated with the source surface.
DDBLT_ROP Uses the dwROP member of the DDBLTFX structure for the ROP for this blit; these ROPs are the same as those defined in the Win32 API.
DDBLT_ROTATIONANGLE
Uses the dwRotationAngle member of the DDBLTFX structure as the rotation angle (specified in 1/100 of a degree) for the surface.
DDBLT_WAIT Instructs the blitter to keep trying the blit operation until the blit operation is successful; this way, you don’t get errors back if the blitter is busy.
Copyright by In-Kwon Lee 2003 14
DDBLTFX Structure (1)DDBLTFX Structure (1)
typedef struct _DDBLTFX{ DWORD dwSize; // the size of this structure in bytes DWORD dwDDFX; // type of blitter fx DWORD dwROP; // Win32 raster ops that are supported DWORD dwDDROP; // DirectDraw raster ops that are supported DWORD dwRotationAngle; // angle for rotations DWORD dwZBufferOpCode; // z-buffer fields used for 3D DWORD dwZBufferLow; // advanced parameter DWORD dwZBufferHigh; // advanced parameter DWORD dwZBufferBaseDest; // advanced DWORD dwZDestConstBitDepth; // advancedunion { DWORD dwZDestConst; // advanced... LPDIRECTDRAWSURFACE lpDDSZBufferDest; // advanced... }; DWORD dwZSrcConstBitDepth; // advanced...
Copyright by In-Kwon Lee 2003 15
DDBLTFX Structure (2)DDBLTFX Structure (2)
union { DWORD dwZSrcConst; // advanced... LPDIRECTDRAWSURFACE lpDDSZBufferSrc; // advanced... }; DWORD dwAlphaEdgeBlendBitDepth; // alpha stuff (advanced) DWORD dwAlphaEdgeBlend; // advanced... DWORD dwReserved; // advanced... DWORD dwAlphaDestConstBitDepth; // advanced... union { DWORD dwAlphaDestConst; // advanced... LPDIRECTDRAWSURFACE lpDDSAlphaDest; // advanced... }; DWORD dwAlphaSrcConstBitDepth; // advanced...
Copyright by In-Kwon Lee 2003 16
DDBLTFX Structure (3)DDBLTFX Structure (3)
union { DWORD dwAlphaSrcConst; // advanced... LPDIRECTDRAWSURFACE lpDDSAlphaSrc; // advanced... }; union // the following are very important{ DWORD dwFillColor; // color word used for fill DWORD dwFillDepth; // z filling (advanced) DWORD dwFillPixel; // color fill word for RGB(alpha) fillsLPDIRECTDRAWSURFACE lpDDSPattern; }; // the following are very importantDDCOLORKEY ddckDestColorkey; // destination color key DDCOLORKEY ddckSrcColorkey; // source color key} DDBLTFX,FAR* LPDDBLTFX;
Copyright by In-Kwon Lee 2003 17
한가지 한가지 colorcolor 로 칠하기로 칠하기
• DDBLT_COLORFILL • DDBLT_WAIT
– 블리터가 요청을 수행하지 못하면 계속 하도록 지시하는 일반적인 예방책을 둔다 .
Copyright by In-Kwon Lee 2003 18
ExampleExample
DDBLTFX ddbltfx; // this contains the DDBLTFX structureRECT fill_area; // this contains the destination rectanglememset(&ddbltfx,0,sizeof(DDBLTFX));ddbltfx.dwSize = sizeof(DDBLTFX);ddbltfx.dwFillColor = color; // your data 8,16,24 bit// fill in the destination-rectangle data (your data)fill_area.top = top;fill_area.left = left;fill_area.bottom = bottom;fill_area.right = right;// ready to blit to surface; in this case, blit to primarylpddsprimary->Blt(&fill_area, // pointer to dest rectangle NULL, // pointer to source surface, NA NULL, // pointer to source rectangle, NA DDBLT_COLORFILL | DDBLT_WAIT, // fill and wait &ddbltfx); // pointer to DDBLTFX structure
Copyright by In-Kwon Lee 2003 19
DEMO: PROG10_3DEMO: PROG10_3
• 640x480 16 비트 모드 윈도우를 생성하고 주표면을 랜덤한 크기의 색깔 있는 사각형을 블리트로 채운다
Copyright by In-Kwon Lee 2003 20
벡터 디스플레이벡터 디스플레이
• 70 년대 후반과 80 년대 초반에는 테일거너 (Tail Gunner) 같은 많은 게임들은 디스플레이가 선으로 이루어지는 벡터 그래픽 디스플레이를 사용
Copyright by In-Kwon Lee 2003 23
Bitmap OperationsBitmap Operations
• 보조표면이나 주표면의 어디에든 비트맵을 불러와서 표시
• 비트맵을 애니메이션 • 움직이고 • 충돌 검사 • …
Copyright by In-Kwon Lee 2003 25
Bitmap Bitmap 생성시 주의할 점생성시 주의할 점
• 색상 : 비트맵이 얼마나 많은 색상을 사용할 것인지 결정해야 하며 , 그리고 모두 같은 색상 공간에서 그려야 한다 .
• 크기 : 모든 비트맵을 2 의 거듭제곱 크기로 그리도록 한다 . 즉 , 2x2, 4x4, 8x8, 16x16, 32,x32 와 같이 이다 . 이렇게 하면 , 블리터와 게임에서 수행하는 여러 최적화에 유리하다 . 정사각형이 되어야 하는 것은 아니다 . 그러나 각 축은 2 의 거듭제곱이 되도록 한다 . 8x16 은 좋지만 7x5 는 좋지 않다 .
• 하나의 이미지 페이지에 여러 비트맵 크기를 섞지 않도록 한다 .
• Bitmap color space 바꾸기 ! How?
Copyright by In-Kwon Lee 2003 27
BITMAPFILEHEADER structureBITMAPFILEHEADER structure
typedef struct tagBITMAPFILEHEADER { // bmfh
WORD bfType; // type of bitmap; 0x4D42 means .BMP
DWORD bfSize; // the total size of the file, in bytes
WORD bfReserved1; // always 0
WORD bfReserved2; // always 0
DWORD bfOffBits; // number of bytes from this structure to access the
// BITMAPINFO; basically an offset
} BITMAPFILEHEADER;
Copyright by In-Kwon Lee 2003 29
BITMAPINFO structureBITMAPINFO structure
• 팔레트가 파일에 있다면 , bmiColors[] 배열은 팔레트를 포함하다 . 그렇지 않으면 bmiColors[] 배열은 비어있다 .
typedef struct tagBITMAPINFO
{
BITMAPINFOHEADER bmiHeader; // contains all the data field definitions of the
// .BMP file
RGBQUAD bmiColors[1]; // the color palette
} BITMAPINFO;
Copyright by In-Kwon Lee 2003 30
BITMAPINFOHEADER structureBITMAPINFOHEADER structure
typedef struct tagBITMAPINFOHEADER{ DWORD biSize; // number of bytes in this structure LONG biWidth; // width of bitmap LONG biHeight; // height of bitmap WORD biPlanes; // number of color planes (always 1) WORD biBitCount // bits per pixel (1,4,8,16,24, or 32) DWORD biCompression; // type of compression; always BI_RGB for // noncompressed bitmaps DWORD biSizeImage; // size of image in bytes LONG biXPelsPerMeter; // x res of target display LONG biYPelsPerMeter; // y res of target display DWORD biClrUsed; // how many colors are used DWORD biClrImportant; // number of important colors; only for Windows a
pps} BITMAPINFOHEADER;
Copyright by In-Kwon Lee 2003 32
Bitmap File StructureBitmap File Structure
typedef struct BITMAP_FILE_TAG
{
BITMAPFILEHEADER bitmapfileheader;
BITMAPINFOHEADER bitmapinfoheader;
PALETTEENTRY palette[256]; // the 256-color palette
UCHAR *buffer; // pointer to data
} BITMAP_FILE, *BITMAP_FILE_PTR;
Copyright by In-Kwon Lee 2003 33
비트맵을 불러오기 두 개의 함수 비트맵을 불러오기 두 개의 함수
int Load_Bitmap_File(BITMAP_FILE_PTR bitmap,
char *filename)
int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
Copyright by In-Kwon Lee 2003 34
DEMO: PROG10_4 DEMO: PROG10_4
• Bitmap file loading• 비트맵은 8 비트 . 16 비트 , 또는 24 비트 형식이 될 수
있다 . 그리고 그 함수는 24 비트 이미지를 16 비트 RGB 이미지로 변환한다 .
Copyright by In-Kwon Lee 2003 36
블리터로 비트 채우기 블리터로 비트 채우기 (1)(1)
// create the primary surfacememset(&ddsd,0,sizeof(ddsd));ddsd.dwSize = sizeof(ddsd);ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;// you need to tell DirectDraw that you want a complex// flippable surface structure; set flags for thatddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_
COMPLEX;// set the backbuffer count to 1ddsd.dwBackBufferCount = 1;// create the primary surfacelpdd->CreateSurface(&ddsd,&lpddsprimary,NULL);// query for the backbuffer; that is, the secondary surfaceddscaps.dwCaps = DDSCAPS_BACKBUFFER;lpddsprimary->GetAttachedSurface(&ddscaps,&lpddsback);
Copyright by In-Kwon Lee 2003 37
블리터로 비트 채우기 블리터로 비트 채우기 (2)(2)
// load the bitmapLoad_Bitmap_File(&bitmap16bit, “ANDRE16.BMP”);// lock the secondary surfacememset(&ddsd,0,sizeof(ddsd));ddsd.dwSize = sizeof(ddsd);lpddsback->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NUL
L);// get video pointersecondary_buffer = (UCHAR *)ddsd.lpSurface;// copy the bitmap data into secondary surface; this time, assume lin
ear memorymemcpy(secondary_buffer, bitmap16bit.buffer, 640*480);// unlock the secondary backbufferlpddsback->Unlock(NULL);
Copyright by In-Kwon Lee 2003 38
블리터로 비트 채우기 블리터로 비트 채우기 (3)(3)
// select source position to grab bitmap fromint source_x = rand()%640;int source_y = rand()%480;// select destination position to blit toint dest_x = rand()%640;int dest_y = rand()%480;// select width and height of rectangleint width = rand()%640;int height = rand()%480;// set up rectanglesRECT source_rect, dest_rect;source_rect.left = source_x;source_rect.top = source_y;source_rect.right = source_x + width;source_rect.bottom = source_y + height;dest_rect.left = dest_x;dest_rect.top = dest_y;dest_rect.right = dest_x + width;dest_rect.bottom = dest_y + height;
Copyright by In-Kwon Lee 2003 39
블리터로 비트 채우기 블리터로 비트 채우기 (4)(4)
// set up the color key so that color index 0 is transparent. If you’re using a
// 16/24 bit mode then you would build the actual RGB values for the transparent
// color and place the SAME value in both the low and high color key
DDCOLORKEY col_key;col_key.dwColorSpaceLowValue = 0; // RGB16BIT565(0,0,0) for
16 bitcol_key.dwColorSpaceHighValue = 0; // RGB16BIT565(0,0,0) for
16 bit// set the keylpddsback->SetColorKey(DDCKEY_SRCBLT, &col_key);// perform the blitlpddsprimary->Blt(&dest_rect, lpddsback, &source_rect, DDBLT_KE
YSRC | DDBLT_WAIT, NULL);