'프로그래밍/DirectX 9'에 해당되는 글 1건

  1. 2016.05.03 :: Vertex(정점) 버퍼
프로그래밍/DirectX 9 2016. 5. 3. 03:00

버텍스(Vertex) - 정점

  • 버텍스는 3D 공간에서 위치를 가지는 정점 -> 벡터라고 함
  • 버텍스들이 모여서 Direct3D의 Primitive에 의하여 선이나 삼각형을 형성하면서 3D 모델을 형성함
  • 버텍스의 물리적인 특성으로써 위치만 존재하고 크기는 무시됨
  • Direct3D에서 사용되는 버텍스는 위치 값 이외에도 색상이나 텍스쳐 좌표 가질 수 있는 다양한 부가적인 특성 가지고 있음
  • Direct3D에서는 FVF라는 개념을 사용하여 필요에 따라 버텍스의 특성을 지정하여 사용할 수 있음

버텍스 포맷

 정점의 좌표

RHW 

결합 가중치 

정점의 법선 벡터 

정점의 점 크기 

확산광 색 

반사광 색 

텍스쳐 좌표 1 



FVF


  • Direct3D에서 지원하는 FVF 방식은 메모리와 실행 시간 절약 할 수 있는 효율적인 방법임


FVF 사용의 효율성


  • 1 프레임안에서의 버텍스 출력

- 버텍스 1개

80(Byte) - 16(Byte) = 64(Byte)

- 버텍스 1000개
64,000(Byte) 차이가 발생
  •  초당 60프레임을 보여줄때 (표준)
- 버텍스 1000개
60 (프레임) * 64,000 (Byte) = 3,840,000(Byte) 의 차이가 발생

FVF를 사용하는 이유
  • 메모리 낭비와 처리 속도의 저하로 인하여 Direct3D에서는 FVF(Flexible Vertex Format)라는 방식을 사용하여 다양한 경우에 적절한 버텍스 포맷을 구성하여 사용하도록 함

  • CUSTOMVERTEX 구조체
 - 이름 관계없음
 - 버텍스 버퍼라는 버텍스들을 보관하기 위한 메모리 영역을 생성할 때 사용

ex) struct CUSTOMVERTEX
{    
float x,y,z;       // 3D 공간상에 위치하는 좌표
DWORD color; // 버텍스의 색상
};
  • D3DFVF_XYZ  (버텍스의 위치) | D3DFVF_DIFFUSE (버텍스의 색상) – Direct3D에 미리 정의되어 있음 – 이 값은 Direct3D에게 전달되어 구조체 CUSTOMVERTEX가 어떤 구조를 가지고 있는지를 알려준다.
ex) #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)

버텍스 버퍼


  • 버텍스 버퍼란
- 버텍스의 구조를 Direct3D로 전달하기 위한 버퍼
- 필요한 수의 버텍스를 저장할 수 있는 메모리를 생성하고, 이 곳에 버텍스의 위치, 색상등과 같은 특성들을 저장하는 메모리 영역
- 버텍스의 수가 얼마가 될지 모르므로 포인터로 생성해 놓고
CreateVertexBuffer()라는 함수를 사용하여 메모리를 할당 받는다.
- 전역변수
LPDIRECT3DVERTEXBUFFER g_pVB = NULL; // 버텍스 버퍼

임시 배열 생성
  • 버텍스 버퍼 생성 후 버텍스로 채움

- vertices[] 라는 배열은 버텍스 버퍼에 넣을 버텍스들을 임시로 보관하기 위한 배열


ex) CUSTOMVERTEX vertices[] =
    {

{150.0f,50.0f,0.5f,0xffff0000,},    //버텍스의 위치와 색상

{250.0f,250.0f,0.5f,0xff00ff00,},

{50.0f,250.0f,0.5f,0xff00ffff,},

    };

{50.0f , 250.0f, 0.5f,   0x     ff        00        ff        ff    }
 x좌표  y좌표  z좌표      투명도    Red    Green    Blue

                                0~255   0~255  0~255  0~255 (10진수)


CreateVertexBuffer( ) 함수

  • 정점 버퍼를  생성하는 함수 – 3*sizeof(CUSTOMVERTEX) : 버텍스 버퍼의 크기가 3개 들어갈 만큼의 양 명시
  • 버퍼를 사용하는 방법 : 0 (USAGE방법을 사용하지 않겠다) – 정적 버퍼 / 동적 버퍼 설정
  • D3DFMT_CUSTOMVERTEX : 버텍스의 포맷을 알려줌 
  • D3DPOOL_DEFAULT : 비디오 메모리 사용 – 가장 적절한 메모리 역을 할당. 대부분 비디오 메모리 된다. 비디오 메모리 내에 버텍스 버퍼가 생성되면 출력 속도가 매우 빨라짐
  • 버텍스 버퍼 변수 g_pVB의 포인터를 넘겨줌

ex) if(FAILED(g_pd3dDevice->CreateVertexBuffer(

3*sizeof(CUSTOMVERTEX),

0,

D3DFMT_CUSTOMVERTEX,

D3DPOOL_DEFAULT,

&g_pVB,

NULL)))

{

return E_FAIL;

}


버텍스 버퍼 채우기

  • 버텍스 버퍼 채우기 단계
– ① 버텍스 버퍼에 락을 건다. (Lock( ) 함수 사용)
– ② 접근용 포인터를 사용하여 버텍스의 내부에 버텍스들을 복사한다. (memcpy( ) 함수 사용)
– ③ 버텍스 버퍼에 락을 푼다. (Unlock( ) 함수 사용)
– Lock()과 Unlock()을 사용하는 이유는 그래픽카드라는 하드웨어를 접근하기 위해, 다른 응용프로그램들이 사용하지 않도록 방지함이 목적

ex)
VOID* pVertices; // 버텍스 버퍼의 접근용 포인터
if(FAILED(g_pVB->Lock(0,sizeof(vertices),(void**)&pVertices,0)))
// Lock함수를 사용하는 이유는 버텍스 버퍼를 할당 받은 메모리가 비디오 메모리이기 때문
// pVertices 변수는 버텍스 버퍼에 락을 걸기 위하여 Lock()함수를 호출할 때 전달되어 락
이 걸린후 접근할 수 있는 포인터를 받아온다.
return E_FAIL;
memcpy(pVertices,vertices,sizeof(vertices));
// Vertices[]안에 있던 버텍스들을 모두 버텍스 버퍼로 복사한다.
g_pVB->Unlock();


  • 버텍스 출력 단계 (크기,구조,그린다)

– ① 출력 대상이 되는 버텍스와 각 버텍스의 크기 지정하여 디바이스에 바인딩 한다.

– ② 버텍스의 구조 디바이스에 지정 (앞에서 지정한 D3DFVF_CUSTOMVERTEX 값)

– ③ DrawPrimitive( ) 함수를 사용하여 버텍스 버퍼안의 내용을 폴리곤 형태로 그린다.


ex)
VOID Render()
{
if(NULL == g_pd3dDevice) return;

//후면 버퍼를 파란색(0,0,255)로 채운다.
g_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,255),1.0f,0);

//렌더링 시작
if(SUCCEEDED(g_pd3dDevice->BeginScene()))
{
g_pd3dDevice->SetStreamSource(0,g_pVB,0,sizeof(CUSTOMVERTEX));
//g_pVB : 버텍스 버퍼
//sizeof(CUSTOMVERTEX : 버텍스 버퍼의 크기
g_pd3dDevice->SetFVF(D3DFMT_CUSTOMVERTEX);
g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,1);
//버텍스 3개를 사용하여 D3DPT_TRIANGLELIST로 그리라고 하였으므로, 한개의 삼각형이 그려진다.

g_pd3dDevice->EndScene();
//렌더링 종료
}


g_pd3dDevice->Present(NULL,NULL,NULL,NULL);

// 후면 버퍼를 보이는 화면으로

}


  • (1) 스트림 소스 지정
- 스트림 소스를 버텍스 버퍼와 연결
- 버퍼의 기하정보를 랜더링 파이프라인에 전달

ex)
HRESULT SetStreamSource(
UINT StreamNumber, // 버텍스 버퍼를 연결할 스트림 소스
IDirect3DVertexBuffer9 * pStreamData, // 스트림과 연결될 VB
UINT OffsetInBytex, // 버텍스 데이터의 시작 오프셋, 0 이외의 값일 경우 장치 지원여부를 확인 필요
UINT Stride // 버텍스 버퍼 내 요소의 바이트 수
);
- Device->SetStreamSource(0,VB,0,sizeof(Vertex));


  • (2) 버텍스 포멧 지정 – 이후의 드로잉 과정에서 이용될 버텍스 포멧 – Device->SetFVF(Vertex::FVF);
  • (3) 인덱스 버퍼 지정 – 이후의 드로잉 과정에서 이용될 인덱스 버퍼 – Device->SetIndices(IB);
  • (4) 폴리곤 그리는 방식 지정
DrawPrimitive( ) : 일반적인 방법
DrawIndexedPrimitive( ) : 중복되는 버텍스를 없애 속도를 높임(가장 빠름)
– DrawPrimitiveUP( ) : 버텍스 버퍼를 생성하지 않고 그림 (속도가 느림)
– DrawIndexedPrimitiveUP( ) : DrawPrimitiveUP()에 인덱스 기능을 추가함

  • D3DFVF_XYZRHW

- 고정 파이프라인을 거치지 않고 x,y 좌표가 바로 윈도우 좌표로 된다.

- 즉, 행렬변환이나 좌표계 설정을 해주어도 먹히지 않는다.

• 월드 이동 자체가 안됨.

- 윈도우 창에 2D 좌표값을 사용하고 싶을 때 사용하는 값

• 인터페이스를 위한 2D 코딩할 때 반드시 사용됨.

  • D3DFVF_XYZ

- 정점 포맷이 변환되지 않은 정점의 위치 좌표를 포함한다.

- 윈도우 창을 로컬 좌표계처럼 사용하겠다.



posted by 천마서생
: