E D R S I H C RSS
ID
Password
Join
전문가보다 더 고약한 사람은 제가 전문가라고 생각하는 사람. ―A.A.C.



Contents

1 개요
2 서피스가 뭐지?
3 이미지 화일에서 서피스로 읽어들이기
3.1 CreateImageSurface()
3.2 D3DXLoadSurfaceFromFile()
4 서피스에서 택스쳐 객체를 생성하자!

1 개요 #

이 글은 D3D를 사용하는데 있어서 화일을 화면에 출력하기 위한 전단계로서 서피스를 만들고 그곳에 화일을 로드한다음, 서피스에서 택스쳐로 변환하는 작업을 설명한다. 예제소스는 ID3DXSprite 인터페이스 분석의 예제 내에서 인용했음을 밝힌다. (주석만 한글화했음)

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 크기의 서피스를 생성했다는 점이다. 실행단계를 보면 다음과 같다.

  1. srcInfo 변수의 값을 얻어내고 D3DXLoadSurfaceFromFile()를 실행하여 srcInfo의 내용을 얻어낸다. 이때에는 이미지화일의 1 픽셀만 읽히게 된다. 그렇더라도 srcInfo에는 이미지화일의 원래 해상도를 담고 있게 된다.
  2. 다시 CreateImageSurface()를 호출하여 이미지 화일의 해상도에 맞는 서피스를 생성한다.
  3. 이제 제대로 생성된 서피스에 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
);

pDestSurfaceIDirect3DSurface8 객체의 포인터. 이미지를 받을 목표 서피스를 의미한다.
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으로 지정한다.
pSrcInfoD3DXIMAGE_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();
}

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2010-10-28 12:42:52
Processing time 0.3684 sec