본문 바로가기

Programing/direct3D

텍스쳐

DirectX는 2D, 3D 모든 이미지를 텍스처(ID3DXTexture9)라는 객체를 이용합니다.

2D는 이텍스쳐 객체를 스프라이트Draw()함수에 인수로 받아 출력합니다.

 
텍스쳐는 디바이스를 통해서 생성됩니다. 

만약 텍스처가 
파일로 되어 있다 D3DXCreateTextureFromFileEx()  

메모리에 저장된 이미지 D3DXCreateTextureFromMemory() 

리소스에 있다면 D3DXCreateTextureFromResource()  

그리고 실시간으로 메모리에 생성하려면 D3DXCreateTexture()  

간혹 D3DXCreateTextureFromFile() 함수를 이용하는 것도 볼 수 있는데 이 함수는 
D3DXCreateTextureFromFileEx() 함수의 간소화된 사용이라고 볼 수 있습니다. (도움말 참조). 
그런데 이 D3DXCreateTextureFromFile() 함수는 2D에서는 사용을 안 하는 것이 좋습니다. 
왜냐하면 2D인 경우 픽셀을 대부분 도트 작업을 통해서 만들고, 또한 텍스처를 확대하거나 
축소해도 픽셀 사이를 보간 하는 필터링을 안 거치게 하는 것이 보통인데 
D3DXCreateTextureFromFile() 함수는 생성할 때 필터링 옵션이 디폴트로 설정이 되어 있어서 
2D 게임 제작에서는 적합하지 않습니다. 
D3DXCreateTextureFromFileEx() 함수는 많은 수의 인수(argument)들을 사용하고 있는데 
2D에서는 이중에 몇 가지만 설정하고 나머지는 디폴트 값으로 설정하는 것이 보통입니다. 
앞으로 3D 게임 제작에서도 텍스처에 관련해서 이 함수를 계속 사용할 것이니 지금부터 잘 
알아 두는 것이 좋습니다. 


D3DXCreateTextureFromFileEx()  로 텍스쳐 생성
먼저 텍스처를 만들기 위해서 다음과 같이 인스턴스를 NULL로 초기화합니다. 

//(LPDIRECT3DTEXTURE9는 IDirect3DTexture9 * (포인터) 의 또 다른 표현입니다.) LPDIRECT3DTEXTURE9 m_pTx1 = NULL; D3DXCreateTextureFromFileEx() 함수로 텍스처 인스턴스를 생성합니다. D3DXIMAGE_INFO pImgInf;//이미지정보 변수 생성 if( FAILED( D3DXCreateTextureFromFileEx( m_pd3dDevice // 디바이스 포인터 , "Texture/earth.bmp" // 텍스처 파일 이름 , D3DX_DEFAULT , D3DX_DEFAULT , 1 // 밉 레벨(2D에서는 반드시 1) , 0 , D3DFMT_UNKNOWN , D3DPOOL_MANAGED , 0x0000001 // 필터링 , 0x0000001 // 밉 필터링 , 0x00FFFFFF // 컬러 키 , &pImgInf // 텍스처 인포메이션 , NULL , &m_pTx1 // 텍스처 포인터 { MessageBox(m_hWnd , "dx5_logo.bmp" "file Could not find" , "Err" , 0); m_pTx1 = NULL; return -1; } 밉(MIP) 레벨의 경우 3D게임에서는 D3DX_DEFAULT 로 둡니다.필터링(Filtering)과 밉 필터는 3D에서 D3DX_DEFAULT 로 설정합니다. 텍스처 인포메이션의 경우 파일에서의 이미지의 가로, 세로, 깊이의 크기를 가지고 있습니다. 나중에 애니메이션을 하려면 이 부분을 텍스처 포인터와 함께 같이 저장해 두는 것이 좋습니다. 

이 함수에서 중요한 부분이 컬러 키입니다. 컬러 키는 일종의 투명 키라고 생각하면 됩니다. 
투명 키는 실제 화면에서 색상이 탈색 되듯이 아무것도 그리지 않는 부분의 색상을 지정하는 
것입니다. 만약 여러분이 분홍색(0xFFFF00FF)을 컬러 키로 지정했다면 분홍색은 화면에 
그리지 않게 됩니다. (이 부분은 정밀하게 작업을 해야 하니까 포토샵과 같은 그래픽 툴을 
이용해서 작업을 한 다음, 올려 보기 바랍니다.) 

텍스쳐 객체 메모리해제 앞서 DirectX는 COM을 상속 받는다고 했습니다. 따라서 텍스처 객체 또한 메모리 해제는 
Release() 함수를 통해서 합니다. 다음과 같이 텍스처 객체를 해제합니다. 
<pre style="font-family: 'Courier New'; font-size: 13px; "> if(m_pTx1) { m_pTx1->Release(); m_pTx1 = NULL; } </pre>

 

그리기

스프라이트의 Draw()함수를 통해서 다음과 같이 화면에 렌더링 합니다. 

if( FAILED( m_pd3dDevice->BeginScene() ) ) return -1; m_pd3dSprite->Begin(D3DXSPRITE_ALPHABLEND); RECT rt1 = {0,0,600, 400}; m_pd3dSprite->Begin(D3DXSPRITE_ALPHABLEND); D3DXVECTOR3 vcCenter(200, 100, 0); D3DXVECTOR3 vcPos( 300, 200, 0); m_pd3dSprite->Draw(m_pTx1, &rt1, &vcCenter, &vcPos, D3DXCOLOR(1,1,1,1)); // m_pd3dSprite->Draw(…); // m_pd3dSprite->Draw(…); m_pd3dSprite->End(); m_pd3dDevice->EndScene();

스프라이트의 Draw() 함수를 사용하려면 반드시 디바이스의 BeginScene() 이후 EndScene() 함수 
사이에 스프라이트 객체의 Begin()함수와 End()함수 사이에 Draw() 함수를 호출해야 합니다.

 
만약 여러 번 Draw()를 호출 한다면 BeginScene()… Begin() … Draw(), …, Draw() … End(), 
..EndScene() 으로 BeginScene()/EndScene()는 한번만 하고 

이 사이에서 여러 번 Begin()/Draw()/End() 함수를 호출 하면 됩니다. 

또한 스프라이트의 Begin()함수의 옵션이 동일하다면 Begin()/End() 함수는 한 번만 호출해도 됩니다. 

Draw() 함수를 살펴보면 처음 인수는 텍스처 포인터 입니다. 

 다음 인수는 그리고 싶은 텍스처의 영역입니다. 만약 영역이 텍스처의 크기보다 크다면 텍스처의 각 x, y의 마지막 
색상으로 채워 집니다. 


세 번째 인수는 중심 위치 인데 자료구조가 D3DXVECTOR3 구조체인 변수의 주소 값을 주는데 
D3DXVECTOR3 구조체는 float x, float y, float z가 들어 있는 구조체 입니다. 

Draw에 이 구조체 인스턴스의 주소 값 대신 NULL을 줄 수도 있는데 이렇게 하면 중심 위치가 
자동으로 (0,0,0)이 설정이 됩니다. 만약 중심 위치가 설정되어 있다면 화면에 그림은 이 
중심 위치를 상대로 이동을 하게 됩니다. 
결과적으로 최종 위치 = 입력 값 위치 - 중심 위치가 됩니다. 

네 번째 인수는 위치 입니다. 최종 위치는 이 위치 값과 중심 위치를 가지고 구합니다. 
만약 NULL을 설정하면 (0,0,0)위치 값으로 결정이 됩니다. 위치, 중심 위치의 z 값은 모두 
0.0F 값으로 설정합니다. 


마지막 인수는 칼라 값입니다. 이 값은 텍스처 전체에 어떤 색상을 곱할 것인가 하는 것입니다. 
이 값은 반투명 처리나 특정 색 만 추출 할 때 사용되니 꼭 기억하기 바랍니다. 
위의 코드 중에서 D3DXCOLOR 구조체가 보이는데 이 구조체는 

float r, float g, float b, float a로 구성된 구조체 입니다. 보통 색상 값이 0~255 이지만 
이 구조체에서는 색상 값을 0~1.F 사이의 값으로 설정해야 합니다. 또한 DWORD 형 캐스팅 연산자가 
재 정의 되어 있어서 DWORD값으로 자동으로 계산을 통한 형 변환을 해줍니다. 
앞으로 이 구조체를 사용하는 것이 편리할 때가 많고 3D 게임제작에서 쉐이더를 사용한다면 
이 구조체가 유리합니다. 

 

 

 

[출처] 

http://3dapi.com/bs11_2d_basic/