2 서피스가 뭐지? #
MSDN에서의 정의에 따르면 다음과 같다.
서피스는 화면출력용 선형 메모리를 나타낸다. 서피스는 일반적으로 비디오 카드 메모리에 상주하며, 때로는 시스템 메모리에도 존재할 수 있다. 서피스 객체들은 IDirect3DSurface8 인터페이스를 사용하여 선언할 수 있다.즉, GDI로 비트맵을 사용해서 애니메이션을 구현할 경우 내부적인 메모리 비트맵이나 HBITMAP등의 요소들이, DX에서는 서피스로 사용된다고 볼 수 있다. DX에서 2차원 데이타는 모두 서피스의 형태로 존재한다고 생각해도 된다. 서피스는 여러종류가 있는데 그 종류는 다음과 같다.
- 일반 서피스 : 주 버퍼 서피스 / 백 버퍼 서피스 (화면 출력용 비디오 메모리)
- 이미지 서피스 : 이 아티클에서 사용하는 서피스. 이미지를 담기위한 서피스. 일반적으로 시스템 메모리상에 생성된다.
- 큐브맵 서피스 : 주변 매핑(Environment Mapping)이라는 기법을 사용하는데 필요한 매핑데이타를 담고 있는 서피스.
- 깊이-스텐실 서피스 : 스탠실 효과를 사용하기 위해 필요한 서피스.
3 이미지 화일에서 서피스로 읽어들이기 #
우선 예제 함수를 보도록 하자. d3dx.h와 d3d.h가 include 되어있다고 가정하겠다.
//-----------------------------------------------------------------------------
// 지정된 그래픽 화일로부터 서피스를 생성한다.
//
// ppSurface - 생성될 서피스 객체
// szFileName - 비트맵 이미지 화일명
// colourKey - 투명색. 불투명검정색이 기본색임. (생략가능)
//-----------------------------------------------------------------------------
void CreateSurfaceFromFile(LPDIRECT3DSURFACE8* ppSurface, char szFileName[], D3DCOLOR colourKey = 0xFF000000)
{
const D3DFORMAT SURFACE_FORMAT = D3DFMT_A1R5G5B5;
LPDIRECT3DSURFACE8 pSurface;
D3DXIMAGE_INFO srcInfo; // Optional
PALETTEENTRY palette[256]; // Optional
// 1. 이미지의 폭과 너비를 구하기 위한 트릭.
g_lpD3DDevice->CreateImageSurface(1, 1, SURFACE_FORMAT, &pSurface);
D3DXLoadSurfaceFromFile(pSurface, NULL, NULL, szFileName, NULL, D3DX_FILTER_NONE, 0, &srcInfo);
pSurface->Release();
// 2. 자, 이제 srcInfo에 이미지의 정보가 담겨져 있다. 이에 따라 진짜 서피스 객체를 생성하고 그것의 포인터를 첫번째 인자에 넘긴다.
g_lpD3DDevice->CreateImageSurface(srcInfo.Width, srcInfo.Height, SURFACE_FORMAT, ppSurface);
pSurface = *ppSurface;
// 3. 기본 컬러키는 0xFF000000 (불투명 검정)으로 지정했다. 만일 다른 값이 넘어오면 그것으로 지정될 것이다.
// 이제 생성한 서피스에 이미지 화일을 정말로 읽어온다.
D3DXLoadSurfaceFromFile(pSurface, palette, NULL, szFileName, NULL, D3DX_FILTER_NONE, colourKey, &srcInfo);
}
위에서 주로 쓰이는 함수는 IDirect3DDevice8::CreateImageSurface()와 D3DXLoadSurfaceFromFile() 두가지이다. 각각의 함수 정의는 아래 추가된 함수정의 표를 참고하도록 하자. 우선 여기서 중요한 점은 이미지의 폭을 구하기 위해 1 * 1 크기의 서피스를 생성했다는 점이다. 실행단계를 보면 다음과 같다.
- srcInfo 변수의 값을 얻어내고 D3DXLoadSurfaceFromFile()를 실행하여 srcInfo의 내용을 얻어낸다. 이때에는 이미지화일의 1 픽셀만 읽히게 된다. 그렇더라도 srcInfo에는 이미지화일의 원래 해상도를 담고 있게 된다.
- 다시 CreateImageSurface()를 호출하여 이미지 화일의 해상도에 맞는 서피스를 생성한다.
- 이제 제대로 생성된 서피스에 D3DXLoadSurfaceFromFile()를 호출하여 이미지화일을 로딩한다.
3.1 CreateImageSurface() #
HRESULT CreateImageSurface( UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface );
| Width | 이미지 서피스의 폭을 픽셀단위로 지정한다. |
| Height | 이미지 서피스의 높이를 픽셀단위로 지정한다. |
| Format | 이미지 서피스의 포멧을 가지고 있는 D3DFORMAT 타입의 값. |
| ppSurface | 생성된 이미지 서피스를 나타내는 IDirect3DSurface8 객체의 포인터의 주소. |
3.2 D3DXLoadSurfaceFromFile() #
HRESULT D3DXLoadSurfaceFromFile( LPDIRECT3DSURFACE8 pDestSurface, CONST PALETTEENTRY* pDestPalette, CONST RECT* pDestRect, LPCTSTR pSrcFile, CONST RECT* pSrcRect, DWORD Filter, D3DCOLOR ColorKey, D3DXIMAGE_INFO* pSrcInfo );
| pDestSurface | IDirect3DSurface8 객체의 포인터. 이미지를 받을 목표 서피스를 의미한다. |
| pDestPalette | ↑의 PALETTEENTRY 구조체의 포인터. 256모드의 이미지라면 지정해야하며, 아니면 NULL로 지정. |
| pDestRect | ↑의 출력영역에 대한 RECT 구조체의 포인터. NULL이면 전체 서피스에 대해 출력하게 된다. |
| pSrcFile | 원본 이미지를 담고 있는 이미지 화일명. bmp, dds, dib, jpg, png, tga 형태의 포맷이 사용가능하다. |
| pSrcRect | 원본 이미지상에서 읽어들이려는 영역을 나타내는 RECT 구조체의 포인터. NULL이면 전체 이미지를 읽어들인다는 뜻. |
| Filter | 어떻게 이미지가 필터링되는지 조정하기 위한 D3DX_FILTER 옵션의 한개이상의 조합값. 보통 D3DX_DEFAULT를 지정한다. (이것은 D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER으로 지정한 것과 같다) 이 아티클에서는 D3DX_FILTER_NONE 값을 지정해서 필터링을 사용하지 않는다라고 지정했다. |
| ColorKey | 투명색을 나타내는 D3DCOLOR값. 0을 지정하면 컬러키기능을 사용하지 않는다는 뜻이다. 언제나 이 값은 ARGB형태의 값을 사용해야하며, 이것은 원본 이미지 컬러 포맷과는 독립적이다. 알파값에 주의해야하며, 보통 불투명한 색값을 지정하기위해 FF를 지정한다. 예를 들면, 불투명 검정색은 0xFF000000으로 지정한다. |
| pSrcInfo | D3DXIMAGE_INFO 타입의 구조체 포인터값. 원본 이미지화일 정보를 담게 된다. NULL로 지정하면 사용하지 않는다는 뜻. |
4 서피스에서 택스쳐 객체를 생성하자! #
D3D에서는 택스쳐 자원을 관리하기 위해 IDirect3DTexture8 객체를 지원한다. 우선 예제 소스를 보도록 하자.
//-----------------------------------------------------------------------------
// 서피스의 지정한 영역으로부터 택스쳐를 생성한다.
//
// pSurface - 원본 서피스.
// pSrcRect - 택스쳐를 생성하기위한 원본 서피스에서의 부분 영역.
// ppTexture - 생성될 택스쳐 객체.
//-----------------------------------------------------------------------------
void CreateTextureFromSurface(LPDIRECT3DSURFACE8 pSurface, RECT* pSrcRect, LPDIRECT3DTEXTURE8* ppTexture)
{
// 1. 서피스에서 택스쳐로 사용할 영역의 폭과 너비를 구하고 빈 택스쳐 객체를 생성한다.
int width = pSrcRect->right - pSrcRect->left;
int height = pSrcRect->bottom - pSrcRect->top;
D3DSURFACE_DESC surfDesc;
pSurface->GetDesc(&surfDesc);
D3DXCreateTexture(g_lpD3DDevice, width, height, 1, 0, surfDesc.Format, D3DPOOL_DEFAULT, ppTexture);
// 2. 택스쳐의 서피스 포인터를 구한다.
LPDIRECT3DSURFACE8 pTexSurface;
LPDIRECT3DTEXTURE8 pTexture = *ppTexture;
pTexture->GetLevelDesc(0, &surfDesc);
pTexture->GetSurfaceLevel(0, &pTexSurface);
// 3. 택스쳐를 지울 깨끗한 서피스를 생성한다. (0으로 지운다)
LPDIRECT3DSURFACE8 pCleanSurface;
D3DLOCKED_RECT lockRect;
g_lpD3DDevice->CreateImageSurface(surfDesc.Width, surfDesc.Height, surfDesc.Format, &pCleanSurface);
pCleanSurface->LockRect(&lockRect, NULL, 0);
memset((BYTE*)lockRect.pBits, 0, surfDesc.Height * lockRect.Pitch);
pCleanSurface->UnlockRect();
// 4. 택스쳐를 지운다.
g_lpD3DDevice->CopyRects(pCleanSurface, NULL, 0, pTexSurface, NULL);
pCleanSurface->Release();
// 5. 택스쳐로 이제 원본 이미지가 담긴 서피스를 복사한다.
POINT destPoint = { 0, 0 };
g_lpD3DDevice->CopyRects(pSurface, pSrcRect, 1, pTexSurface, &destPoint);
pTexSurface->Release();
}








![[http]](/wiki/imgs/http.png)
