Software Development/Graphics

5. Vertices_2)정점

huiyu 2014. 10. 17. 22:59

2. Direct3D 정점

Direct3D는 유연한 정점 포맷이라고 해서 프로그래머가 정점의 최적 정보만을 가질 수 있도록 그 형식을 설정할 수 있습니다.

1) 1단계 : float x, y, z 좌표값

2) 2단계 : float rhw (이미 변환된 정점에만 사용)

3) 3단계 : 블랜딩 값

4) 4단계 : 정점 법선

5) 5단계 : 정점 포인트의 크기

6) 6단계 : diffuse 값

7) 7단계 : specular 색

8) 1~8까지 텍스쳐 좌표쌍(u, v  float 값)

멤버 변수의 순서가 바뀌면 렌더링이 않되므로 순서를 지켜서 정의해야 합니다.

정점의 구조체가 어떤 정보를 포함하는지에 대한 것은 아래의 값을 비트 OR연산하여 설정합니다.

D3DFVF_DIFFUSE, D3DFVF_NORMAL, D3DFVF_SPECULAR, D3DFVF_XYZ, D3DFVF_XYZRHW, D3DFVF_XYZW, D3DFVF_TEX0~ D3DFVF_TEX7


예시)x, y,z의 위치값과 정점의 색상을 한 개의 정점에 포함 시킨 것입니다.

struct CUSTOMVERTEX
{
	FLOAT x,y,z;
	DWORD color;
};

#define D3DFVF_CUSTOMVERTEX	(D3DFVF_XYZ | D3DFVF_DIFFUSE)

정점의 형식은 #define을 통해 정의한 D3DFVF_CUSTOMVERTEX으로 설정하게 됩니다.


*rhw의 설정은 현재의 정점을 2D좌표처럼 사용하는 것


다양한 사용예시 1)

struct CUSTOMVERTEX
{
	D3DXVECTOR3 position;
	D3DXVECTOR3 normal;
	DWORD		diffuse;
	float tu, tv;
};

#define D3DFVF_CUSTOMVERTEX	(D3DFVF_XYZ | D3DFVF_NORMAL| D3DFVF_DIFFUSE | D3DFVF_TEX1)


다양한 사용예시 2)

struct CUSTOMVERTEX
{
	FLOAT x,y,z, rhw;
	DWORD color;
};

#define D3DFVF_CUSTOMVERTEX	(D3DFVF_XYZRHW | D3DFVF_DIFFUSE)


- 정점의 생성과 초기화

struct CUSTOMVERTEX
{
	FLOAT x,y,z;
	DWORD color;
};

#define D3DFVF_CUSTOMVERTEX	(D3DFVF_XYZ | D3DFVF_DIFFUSE)

CUSTOMVERTEX vertices[] = 
{
	{150.0f,  50.0f, 0.5f, 1.0f, 0xffff0000,},
	{250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00,},
	{ 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff,},
};

구조체에 맞춰 데이터를 설정하면 됩니다.


- 정점버퍼

출력할 정점을 저장하는 버퍼, 출력할 정점을 모두 정점 버퍼에 넣은 후 버퍼 안에 있는 정점을 한꺼번에 출력합니다.

1) 생성

HRESULT CreateVertexBuffer(
  [in]           UINT Length,
  [in]           DWORD Usage,
  [in]           DWORD FVF,
  [in]           D3DPOOL Pool,
  [out, retval]  IDirect3DVertexBuffer9 **ppVertexBuffer,
  [in]           HANDLE *pSharedHandle
);

- Length : 정점 구조체의 크기 설정

- Usage : 항상 0으로 설정

- FVF    : 정점 구조에 대한 값인 D3DFVF_CUSTOVERTEX가 설정

- Pool   : 정점을 메모리에 생성하는 방법을 설정합니다. 기본값은 D3DPOOL_DEFAULT

정점 버퍼의 객체형은 LPDIRECT3DVERTEXBUFFER9이므로, 이 포인터 변수의 메모리 주소를 설정합니다.

pSharedHandle은 아직 사용하지 않으니 NULL을 입력

LPDIRECT3DVERTEXBUFFER9 m_pVB;
	m_pd3dDevice->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_pVB, NULL);


2) 정점을 정점 버퍼에 복사

 - 정점 버퍼를 사용하기 위해서는 먼저 정점 버퍼의 메모리를 Lock()하여 독점합니다

 - Lock()을 하게 되면 해당 메모리는 다른 자원에서 접근할 수 없으며 정점을 저장하기 위한 시작 메모리주소를 얻습니다.

 - memcpy()를 통해 메모리 주소로 복사합니다.

 - 끝난 후 UnLock()

VOID* pVertices; m_pVB->Lock(0, sizeof(vertices), (void**)&pVertices, 0); memcpy(pVertices, vertices, sizeof(vertices)); m_pVB->Unlock();


3) 렌더링

- 렌더링은 다음의 과정으로 진행됩니다.

m_pd3dDevice->SetStreamSource(0, m_pVB, 0, sizeof(CUSTOMVERTEX)); m_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,1);

-SetStreamSorce() : 정점 버퍼와 정점의 포맷을 d3d device에게 알려주는 함수

HRESULT SetStreamSource(
  [in]  UINT StreamNumber,
  [in]  IDirect3DVertexBuffer9 *pStreamData,
  [in]  UINT OffsetInBytes,
  [in]  UINT Stride
);

     - SetFVF : 정점 구조가 어떻게 되는지 device에 설정

HRESULT SetFVF(
  [in]  DWORD FVF
);

-DrawPrimitive : 정점 출력

HRESULT DrawPrimitive(
  [in]  D3DPRIMITIVETYPE PrimitiveType,
  [in]  UINT StartVertex,
  [in]  UINT PrimitiveCount
);


PrimitiveType은 다음과 같습니다.

-D3DPT_POINTLIST


-D3DPT_LINELIST


-D3DPT_LINESTRIP


-D3DPT_TRIANGLELIST


-D3DPT_TRIANGLESTRIP


-D3DPT_TRIANGLEFAN


4) 정점 버퍼와 Direct3D 해제

VOID CD3DApp::Cleanup()
{
	if(pVB != NULL)
		pVB->Release();
	if(m_pd3dDevice != NULL)
		m_pd3dDevice->Release();

	if(m_pD3D != NULL)
		m_pD3D->Release();
}



728x90