본문 바로가기

프로그래밍/공부관련

Directx9.0c 버퍼관련..

기하정보 저장 버퍼

 

버퍼사용 이유

배열이 아닌 버퍼에 저장하는 이유는 버퍼를 비디오 메모리에 저장할 수 있기 때문으로, 시스템 메모리의 데이터를 렌더링하는 것보다는 비디오 메모리의 데이터를 렌더링하는 것이 훨씬 빠르기 때문이다.

버텍스 버퍼 

버텍스 데이터를 보관하는 연속적인 메모리 덩어리
HRESULT IDirect3DDevice9::CreateVertexBuffer(
UNIT Length,                   //버퍼에 할당할 바이트 수
DWORD Usage,              //버퍼가 이용되는 몇 가지 부가적인 특성
DWORD FVF,                 //버텍스 보관될 버텍스 포멧
D3DPOOL Pool,             //버퍼가 위치할 메모리 풀
IDirect3DVertexBuffer9** ppVerTexBuffer,
                                   //만들어질 버텍스 버퍼를 받을 포인터
HANDLE* pShareHandle    //이용하지 않는다.0으로 지정
);

ex) 8개 버텍스 정보를 가질수 있는 버퍼 생성
IDirect3DDeviceVertexBuffer9* vb;
Device->CreateVertexBuffer( 8*sizeof(Vertex), 0,
D3DFVF_XYZ, D3DPOOL_MANAGED,
&vb,0 );

인덱스 버퍼

인덱스 데이터를 보관하는 연속적인 메모리 덩어리
HRESULt IDirect3DDevice9::CreateIndexBuffer(
   UNIT Length,
   DWORD Usage,
   D3DFORMAT Format,         //만들어질 인덱스 버퍼를 받을 포인터
   D3DPOOL Pool,
   IDirect3DIndexBuffer9** ppIndexBuffer,
   HANDEL* pShareHandle
};

ex) 8개 버텍스 정보를 가질수 있는 버퍼 생성
IDirect3DDeviceIndexBuffer9* ib;
Device->CreateIndexBuffer( 36*sizeof(WORD),D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16, D3DPOOL_MANAGED,
&ib,0 );
Usage에서 사용되는 플래그
D3DUSAGE_DYNAMIC – 버퍼를 동적으로 만든다.
D3DUSAGE_POINTS – 버퍼가 포인트 기본형을 보관할 것임을 지정
D3DUSAGE_SOFTWAREPROCESSING – 버텍스 프로세싱을 소프트웨어로 처리
D3DUSAGE_WRITEONLY – 애플리케이션이 버퍼에 쓰기만을 수행할 것임을 지정.만약 버퍼를 읽으려고 하면 오류 발생

정적버퍼

비디오 메모리상 효율적인 메모리 처리, 접근속도 제약이 있음 주로 정적 데이터 처리, D3DUSAGE_DYNAMIC 플래그 지정하지 않은 버퍼 해당
ex)
데이터 처리빈도가 적은 지형, 건물 기하정보(애플리케이션 초기화 때 정적버퍼에 기하정보 저장)

동적버퍼

D3DUSAGE_DYNAMIC 플래그 지정, AGP메모리 저장, 메모리 처리속도는 비디오 메모리 전송과정이 필요하므로 정적보다 느림, 그러나 갱신속다가 빠름(고속 CPU쓰기 처리)
ex) 파티클 시스템, 프레임별 기하정보 변환이 필요하므로 동적 필요

Tip

비디오 메모리나 AGP메모리에서의 읽기 작업은 상당히 느리므로 런타임시에 기하정보를 자주 읽어 들여야 한다면 지역 시스템 메모리에 복사본을 남겨두고 이를 읽어들이는 것이 바람직하다.

버퍼 메모리에 접근하기

HRESULT IDirect3DVerTexBuffer9::Lock(
   UNIT OffsetLock,   //잠금을 시작할 버퍼 위치의 오프셋
   UNIT SizeLock,     //잠글 바이트의 수(offsetlock + sizelock)
   BYTE** ppbData,   //잠근 메모리의 시작을 가리키는 포인터 수
   DWORD Flags );    //잠근을 이루어지는 방법 지정. 0을 지정하거나 플래그를 지정

HRESULT IDirect3DIndexBuffer9::Lock(
   UNIT OffsetLock,
   UNIT SizeLock,
   BYTE** ppbData,
   DWORD Flags );

ex)
Vertex* vetice;
Vb->Lock( 0, 0, (void**)&vertice, 0 );
Vertice[0] = Vertex( -1.0f, 0.0f , 2.0f );
Vertice[1] = Vertex( 0.0f, 1.0f, 2.0f );
Vertice[2] = Vertex( 1.0f, 0.0f, 2.0f );
Vb -> Unlock();
DWORD Flag 인자
D3DLOCK_DISCARD – 동적 버퍼에만 이용. 하드웨어에게 버퍼를 버리도록 지시하고 새로 할당된 버퍼의 포인터를 리턴
D3DLOCK_NOOVERWRITE – 이 플래그는 동적 버퍼에만 이용. 버퍼에 데이터를 추가하는 작업만 가능하도록 하는 것
D3DLOCK_READONLY – 읽기 전용으로 버퍼를 잠글 것임을 지정

※D3DLOCK_DISCARD와 D3DLOCK_NOOVERWRITE  이 두 플래그를 이용할 수 있는 상황이라면 버퍼를 잠글 때도 렌더링이 정지되는 것을 막을 수 있다.

버텍스/인덱스 버퍼에 대한 정보

상황에 따라 버텍스/인덱스에 대한 정보를 얻는데 이용되는 메서드 이용의 예이다.

D3DVERTEXBUFFER_DESC vbDescription;
vertexBuffer->GetDesc(&vbDescription);   //버텍스 버퍼 정보를 얻는다.

D3DINDEXBUFFER_DESC ibDescription;
indexBuffer->GetDesc(&ibDescription);   //인덱스 버퍼 정보를 얻는다.

렌더 상태

Direct3D는 기하정보가 렌더링되는 방식을 결정하는 다양한 렌더링 상태를 캡슐화하고 있다. 렌더 상태는 모두 디폴트 값을 가지고 있으므로 여러분의 애플리케이션에서 디폴트가 아닌 다른 동작을 필요로 하는 경우에만 이를 변경하면 된다.
렌더 상태를 알고 싶다면 SDK문서의 D3DRENDERSTATETYPE항목에서 찾을 수 있다
HRESULT IDirect3DDevice9::SetRenderState(
   D3DRENDERSTATETYPE State,         //변경 할 상태
   DWORD Value );                            //새로운 상태 값

ex) 와이어프레임으로 렌더링
device->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );

드로잉

스트림 소스 지정

스트림 소스를 버텍스 버퍼와 연결하여 버퍼의 기하정보를 렌더링파이프라인 보낼 수 있도록 한다.
 HRESULT IDirect3DDevice9::SetStreamSource(
   UNIT StreamNumber,      //버텍스 버퍼를 연결할 스트림
                                    //소스를 지정.
   IDirect3DVertexBuffer9* pStreamData, 
                                    //스트림과 연결하고자 하는 버텍스 버퍼
                                    //로의 포인토
   UNIT offsetInBytes,
                                    //렌더링 파이프라인으로 공급될 버텍스
                                    //데이터의 시작을 지정 스트림의 오프셋
   UNIT Stride
                                   //스트림에 연결하고자 하는 버텍스 버퍼
                                   //내 각 요소의 바이트 수
);
ex)
device->SetStreamSource( 0, vb, 0, sizeof( Vertex ) );

버텍스 포맷을 지정

이후의 드로잉 호출에서 이용될 버텍스포맷을 지정하는 단계
device->SetFVF( D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEXT);

인덱스 버퍼를 지정

인덱스 버퍼는 한 번에 하나의 인덱스 버퍼만 이용할 수 있다. 따라서 인덱스 버퍼를 가진 물체를 그려야한다면 인덱스 버퍼를 전환하는 과정이 필요하다.
device->SetIndices( ib ); //인덱스 버퍼 포인터의 복사본을 전달한다.

버텍스/인덱스 버퍼를 이용한 드로잉

DrawPrimitive나 DrawIndexPrimitive 메서드를 이용해 기하정보를 렌더링 파이프라인으로 보내는 실질적인 드로잉을 수행할 수 있다.
버텍스 정보 이용 그리기
HRESULT IDirect3DDevice9::DrawPrimitive(
   D3DPRIMITIVETYPE PrimitiveType,    //그리고자 하는 기본형 타입
   UNIT StartVertex,                           //버텍스읽기를 시작할 버텍스
                                                    //요소로의 인덱스.
   UNIT PrimitiveCount                       //그리고자 하는 기본형의 수
 );

ex)
device->DrawPrimitive( D3DPT_TRIANGLELIST, 0 , 4 );

인덱스 정보 이용 그리기
HRESULT IDirect3DDevice9::DrawIndexPrimitive(
D3DPRIMITIVETYPE Type,   //그리고자 하는 기본형 타입
INT BaseVetexIndex,          //이번 호출에 이용될 인덱스에 더해질 기
                                     //반 번호를 지정
UNIT MinIndex,                 //참조할 최소 인덱스 값
UNIT NumVertice,              //이번 호출에 참조될 버텍스의 수
UNIT StartIndex                //인덱스 버퍼내에서 읽기를 시작할 요소로
                                    //의 인덱스
UNIT PrimitiveCount          //그리고자 하는 기본형의 수
);

ex)
device->DrawIndexPrimitive( D3DPT_TRIANGLELIST, 0 ,0 ,8 ,0 , 12 );

장면의 시작과 끝

마지막으로 기억해두어야 할 사항으로는 모든 드로앙 메서드가 BeginScene와 EndScene 호출 내부에 포함되어야 한다.
device->BeginScene();
device->DrawPrimitive();
device->EndScene();

D3DX 기하 물체

코드 내에서 각각의 삼각형을 연결하여 3D물체를 구성하는 작업은 상당히 지루할 것이다.
그래서 우리는 편하게 D3DX에서 제공하는 라이브러리는 몇 가지의 간단한 3D 물체 메쉬 데이터를 생성하는 메서드를 제공한다.

D3DXCreateBox, D3DXCreateSphere, D3DXCreateCylinder, D3DXCreateTeapot, D3DXCreatePolygon,  D3DXCreateTours
생성된 기하 물체를 그리려면 다음 함수를 이용한다.

ID3DXMesh::DrawSubset(DWORD AttribId);
// 드로잉(Drawing) 하는 메쉬의 서브 세트를 지정하는 DWORD. 이 값은, 메쉬내의 면을, 1 개 또는 복수의 속성 그룹에 속하고 있다고 하여 구별하기 위해서 사용된다. 
ex) 티포트 생성
HRESULT D3DXCreateTeapot(
LPDIRECT3DDEVICE9  pDevice,   //메쉬와 연계된 장치
LPD3DMESH* ppMesh,            //메쉬를 받을 포인터
LPD3DXBUFFER* ppAdjacency    //현재는 0으로 지정
);        
ID3DXMESH* mesh = 0;
D3DXCreateTeapot( device, &mesh, 0 );

device->BeginScene();
device->DrawSubset(0);
device->EndScene;

//after using
mesh->Release();
mesh = 0;

[출처] Direct3D 그리기 |작성자 아이엠쏭