인덱스버퍼

 <인덱스 버퍼>

1.인덱스 버퍼의 기초
 
 인덱스 버퍼란 정점의 인덱스를 보관하기 위한 전용 버퍼를 말한다.

메모리 소모량이 적고 캐시를 이용해 높은 효율을 낼 수 있다.(인덱스버퍼를 사용하는 이유)
캐시를 통한 최적화는 인덱스 버퍼를 사용할 때만 가능한 것으로 통상 출력 속도가 두 배 정도 빨라진다.
인덱스 버퍼는 DirectX 8.0에서 새롭게 등장한 것으로서, 인덱스된 렌더링에 사용할 인덱스를 저장합니다. 
인덱스 버퍼는 복사 작업을 제거(하거나 최소한 줄이기 위해) 제공된 것으로서,
DirectX 7.0에 비해 성능 상의 향상을 가져 왔습니다.
인덱스 버퍼는 16비트나 32비트로 할당됩니다. 
최대 인덱스 값에 해당하는 제한 값이 있는데, 2**16이며, 모든 2**32는 아직 사용할 수 없습니다.

 

//뭐, 남는건 아~ 빠르구나~  이것 밖에는 <(o.o)>

 

2. 인덱스버퍼 사용순서

1. SetFVF()함수로 정점 버퍼의 정보를 D3D에 전달한다.
2. SetStreamSource()함수로 정점 버퍼사용할 준비를 한다.
3. SetIndices()함수를 사용하여 인덱스 버퍼를 사용할 준비를한다.
4. 기존에 사용했던 DrawPrimitive()함수가 아닌
   DrwaIndexedPrimitive()함수를 사용하여 정점 버퍼 + 인덱스 버퍼로 폴리곤을 출력한다.

   입니다.

 

 
3.인덱스버퍼와 그냥 버텍스버퍼의 차이 


버텍스(정점)버퍼에 관한 사항은 자료가 충분하므로 공부하시기 편할 겁니다.

 

뭐, 제가 이해한 위의 그림을 설명하자면 

평소의 정점출력(DrawPrimitive)은 2,1,6정점과 10,-3,0 정점 4,8,6좌표의 정점들 등등...을 이어서 삼각형을 만들어가면서 원하는 대상물을 출력합니다.

삼각형들이 모여서 물체가 이루어 진다는 것은 다들 아시죠?

두번째 그림에서 버택스버퍼이외에 하나의 인덱스버퍼가 더 추가됩니다. 2,1,6은 0번 인덱스

10,-3,0은 1번인덱스 4,8,6은 2번 인덱스 입니다.

인덱스로 출력(DrawIndexedPrimitive)을 하면 인덱스버퍼를거쳐 버텍스버퍼를 참조하여 출력을 하게됩니다.

 

또다른 장점은 하나의 버텍스버퍼에 종류별로 인덱스를 묶어

인덱스 번호로 원하는 버텍스를 찍을 수 있는 장점이 있겠습니다.

LOD쓸때 편하죠

  


출저:.Across The Universe :: 네이버 블로그



/*********************************************************************
* 인덱스 버퍼 생성
* 파일 : IndexBuffer.cpp
*
* 설명 : 인덱스 버퍼란 정점을 보관하기 위한 정점 버퍼처럼 인덱스를
*        보관하기 위한 전용 객체입니다. D3D 학습 예제에는 이렇게 IB를
*        사용한 예제가 없기 때문에 추가했습니다.
*********************************************************************/

#include <d3d9.h>
#include <d3dx9.h>


/*********************************************************************
* 전역 변수
*********************************************************************/

LPDIRECT3D9	 	 g_pD3D = NULL;           //D3D 디바이스를 생성할 D3D 객체 변수
LPDIRECT3DDEVICE9	 g_pd3dDevice = NULL;     //렌더링에 사용될 D3D 디바이스
LPDIRECT3DVERTEXBUFFER9  g_pVB = NULL;      //정점을 보관할 정점 버퍼
LPDIRECT3DINDEXBUFFER9	 g_pIB = NULL;      //인덱스를 보관할 인덱스 버퍼


//사용자 정점을 정의할 구조체
struct CUSTOMVERTEX
{
	FLOAT x, y, z;    //정점의 변환된 좌표
	DWORD color;      //정점의 색깔
};

//사용자 정점 구조체에 관한 정보를 나타내는 FVF값
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)

struct MYINDEX
{
	WORD _0, _1, _2;   //DWORD 형인것을 주의하자.(16비트)
//일반적으로 인덱스는 16비트의 크기를 갖는다.
//32비트의 크기도 가능하지만 구형 그래픽카드에서는 지원하지 않는다.
};
/********************************************************************* * Direct3D 초기화 *********************************************************************/ HRESULT InitD3D(HWND hWnd) { //디바이스를 생성하기 위한 D3D 객체 생성 if(NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION))) { return E_FAIL; } //디바이스를 생성할 구조체 //복잡한 오브젝트를 그릴 것이므로 이번에는 Z 버퍼가 필요 D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; //디바이스 생성 if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice))) { return E_FAIL; } //컬링 기능을 끈다. g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); //Z 버퍼 기능을 켠다. g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE); //정점에 색깔값이 있으므로 광원 기능을 끈다. g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE); return S_OK; }
/********************************************************************* * 정점 버퍼를 생성하고 정점값을 채워넣는다. * 정점 버퍼란 기본적으로 정점 정보를 갖고 있는 메모리 블록이다. * 정점 버퍼를 생성한 다음에는 반드시 Lock()과 Unlock()으로 포인터를 * 얻어내서 정점 정보를 정점 버퍼에 써 넣어야 한다. * 또한 D3D는 인덱스 버퍼도 사용 가능하다는 것을 명심하자. * 정점 버퍼나 인덱스 버퍼는 기본 시스템 메모리 외에 디바이스 메모리 * (비디오카드 메모리)에 생성될 수 있는데, 대부분의 비디오카드에서는 * 이렇게 할 경우 엄청난 속도의 향상을 얻을 수 있다. *********************************************************************/
HRESULT InitVB() { //상자(cube)를 렌더링하기 위해 8개의 정점 선언 CUSTOMVERTEX vertices[] = { { -1, 1, 1, 0xffff0000 }, //v0 { 1, 1, 1, 0xff00ff00 }, //v1 { 1, 1, -1, 0xff0000ff }, //v2 { -1, 1, -1, 0xffffff00 }, //v3 { -1, -1, 1, 0xff00ffff }, //v4 { 1, -1, 1, 0xffff00ff }, //v5 { 1, -1, -1, 0xff000000 }, //v6 { -1, -1, -1, 0xffffffff } //v7 }; //정점 버퍼 생성 //8개의 사용자 정점을 보관할 메모리를 할당한다. //FVF를 지정하여 보관할 데이터의 형식을 지정한다. if(FAILED(g_pd3dDevice->CreateVertexBuffer(8*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL))) { return E_FAIL; } //정점 버퍼를 값으로 채운다. //정점 버퍼의 Lock() 함수를 호출하여 포인터를 얻어온다. VOID* pVertices; if(FAILED(g_pVB->Lock(0, sizeof(vertices), (void**)&pVertices, 0))) { return E_FAIL; } memcpy(pVertices, vertices, sizeof(vertices)); g_pVB->Unlock(); return S_OK; }
//InitIB()함수 추가 HRESULT InitIB() { //상자(cube)를 렌더링하기 위해 12개의 면 선언 MYINDEX indices[] = { { 0, 1, 2 }, { 0, 2, 3 }, //윗면 { 4, 6, 5 }, { 4, 7, 6 }, //아랫면 { 0, 3, 7 }, { 0, 7, 4 }, //왼면 { 1, 5, 6 }, { 1, 6, 2 }, //오른면 { 3, 2, 6 }, { 3, 6, 7 }, //앞면 { 0, 4, 5 }, { 0, 5, 1 } //뒷면 }; //인덱스 버퍼 생성 //D3DFMT_INDEX16은 인덱스의 단위가 16비트라는 것이다. //우리는 MYINDEX 구조체에서 WORD형으로 선언했으므로 D3DFMT_INDEX16을 사용 if(FAILED(g_pd3dDevice->CreateIndexBuffer(12*sizeof(MYINDEX), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &g_pIB, NULL))) { return E_FAIL; } //인덱스 버퍼를 값으로 채운다. //인덱스 버퍼의 Lock() 함수를 호출하여 포인터를 얻어온다. VOID* pIndices; if(FAILED(g_pIB->Lock(0, sizeof(indices), (void**)&pIndices, 0))) { return E_FAIL; } memcpy(pIndices, indices, sizeof(indices)); g_pIB->Unlock(); return S_OK; } /********************************************************************* * 행렬 설정 *********************************************************************/ VOID SetupMatrices() { //월드 행렬 D3DXMATRIXA16 matWorld;
//월드 행렬을 단위 행렬로 설정 
D3DXMatrixIdentity(&matWorld); 
//Y축을 중심으로 회전 행렬 생성 
D3DXMatrixRotationY(&matWorld, GetTickCount()/500.0f);
//디바이스에 월드 행렬 설정  g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld); //뷰 행렬 설정 D3DXVECTOR3 vEyePt(0.0f, 3.0f, -5.0f); D3DXVECTOR3 vLookatPt(0.0f, 0.0f, 0.0f); D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f); D3DXMATRIXA16 matView; D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUpVec); g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView); //프로젝션 행렬 설정 D3DXMATRIXA16 matProj; D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f); g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj); } /********************************************************************* * 초기화 객체들 소거 *********************************************************************/ VOID Cleanup() { if(g_pIB != NULL) { g_pIB->Release(); } if(g_pVB != NULL) { g_pVB->Release(); } if(g_pd3dDevice != NULL) { g_pd3dDevice->Release(); } if(g_pD3D != NULL) { g_pD3D->Release(); } } /********************************************************************* * 화면 그리기 *********************************************************************/ VOID Render() { //후면 버퍼와 Z버퍼 초기화 g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0); //행렬 설정 SetupMatrices(); //렌더링 시작 if(SUCCEEDED(g_pd3dDevice->BeginScene())) { //정점 버퍼의 삼각형을 그린다. //1. 정점 정보가 담겨 있는 정점 버퍼를 출력 스트림으로 할당한다.
// (여기서 버택스정보를 넘기기때문에 인덱스정보로만 출력이 가능한것)
g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));
 
//2. D3D에게 정점 셰이더 정보를 지정한다. 대부분의 경우에는 FVF만 지정 g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
 
//3. 인덱스 버퍼를 지정한다. g_pd3dDevice->SetIndices(g_pIB);
 
//4. DrawIndexedPrimitive()를 호출한다. g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12); //렌더링 종료 g_pd3dDevice->EndScene(); } //후면 버퍼를 보이는 화면으로 g_pd3dDevice->Present(NULL, NULL, NULL,NULL); } /********************************************************************* * 윈도우 프로시저 *********************************************************************/ LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_DESTROY: Cleanup(); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, msg, wParam, lParam); } /********************************************************************* * 프로그램 시작점 *********************************************************************/ INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT) { //윈도우 클래스 등록 WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, "D3D Tutorial", NULL }; RegisterClassEx(&wc); //윈도우 생성 HWND hWnd = CreateWindow("D3D Tutorial", "D3D Tutorial 07 : IndexBuffer", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, GetDesktopWindow(), NULL, wc.hInstance, NULL); //Direct3D 초기화 if(SUCCEEDED(InitD3D(hWnd))) { //정점 버퍼 초기화 if(SUCCEEDED(InitVB())) { //인덱스 버퍼 초기화 if(SUCCEEDED(InitIB())) { //윈도우 출력 ShowWindow(hWnd, SW_SHOWDEFAULT); UpdateWindow(hWnd); //메시지 루프 MSG msg; ZeroMemory(&msg, sizeof(msg)); while(msg.message != WM_QUIT) { //메시지 큐에 메시지가 있으면 메시지 처리 if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { //처리할 메시지가 없으면 Render() 함수 호출 Render(); } } } } } //등록된 클래스 소거 UnregisterClass("D3D Tutorial", wc.hInstance); return 0; }






이 글을 공유하기

댓글

Designed by JB FACTORY