서적 정리/DirectX11을 이용한 3D 게임 프로그래밍 입문

45.인덱스와 인덱스 버퍼(Index Buffer)

민돌이2 2022. 2. 8. 16:24

기본적으로 정점 버퍼의 생성과 거의 유사하다. 정점 대신 인덱스(index)를 담는다는 점만 다르다.

인덱스 버퍼를 생성하고 파이프라인에 묶기까지 다음과 같은 과정을 거친다.

  1. 생성할 버퍼를 서술하는 D3D11_BUFFER_DESC 구조체를 채운다.
  2. 버퍼의 초기화에 사용할 자료를 서술하는 D3D11_SUBRESOURCE_DATA 구조체를 채운다.
  3. ID3D11Device::CreateBuffer를 호출해서 버퍼를 생성한다.
  4. ID3D11DeviceContext::IASetIndexBuffer을 호출하여 인덱스 버퍼를 파이프라인에 묶는다.(Input Assembler : IA)

1.생성할 버퍼를 서술하는 D3D11_BUFFER_DESC 구조체를 채운다.

D3D11_BUFFER_DESC 구조체는 d3d11.h에서 찾을 수 있다.

typedef struct D3D11_BUFFER_DESC
{
	UINT ByteWidth;
	D3D11_USAGE Usage;
	UINT BindFlags;
	UINT CPUAccessFlags;
	UINT MiscFlags;
	UINT StructureByteStride;
} D3D11_BUFFER_DESC;

1.ByteWidth : 생성할 버퍼의 크기(byte 단위)
2.Usage : 버퍼가 쓰이는 방식(*주 1)
3.BindFlags : 버퍼가 파이프라인에 바인딩되는 방법을 식별(*주 2)
4.CPUAccessFlags : CPU가 버퍼에 접근하는 방식을 식별. CPU가 버퍼를 사용하지 않는다면 0을 지정한다.
5.MiscFlags : 기타 플래그 식별
6.StructureByteStride : 구조적 버퍼에 저장된 원소 하나의 크기. 구조적 버퍼를 위해서만 필요하고, 그 외의 모든 버퍼에 대해서는 0을 지정한다.

 

2.버퍼의 초기화에 사용할 자료를 서술하는 D3D11_SUBRESOURCE_DATA 구조체를 채운다.
D3D11_SUBRESOURCE_DATA 구조체는 d3d11.h에서 찾을 수 있다.

typedef struct D3D11_SUBRESOURCE_DATA
{
	const void *pSysMem;
	UINT SysMemPitch;
	UINT SysMemSlicePitch;
} D3D11_SUBRESOURCE_DATA;​

1.pSysMem : 버퍼를 초기화할 자료를 담은 시스템 메모리 배열을 가리키는 포인터.
2.SysMemPitch : 텍스처의 한 줄 시작에서 다음 줄 까지의 거리(byte)이다. 2D, 3D 텍스처 데이터에서만 사용되고, 나머지에서는 사용하지 않는다.
3.SysMemSlicePitch : 한 깊이 레벨의 시작에서 다음 깊이 레벨까지의 거리(byte)이다. 3D 텍스처 데이터에만 사용된다.

 

3.ID3D11Device::CreateBuffer를 호출해서 버퍼를 생성한다.
CreateBuffer 함수는 d3d11.h에서 찾을 수 있다.

HRESULT CreateBuffer(
	const D3D11_BUFFER_DESC* pDesc,
	const D3D11_SUBRESOURCE_DATA* pInitialData, 
	ID3D11Buffer** ppBuffer
);

1.pDesc : 생성할 버퍼를 서술하는 구조체
2.pInitialData : 버퍼를 초기화하는 데 사용할 자료
3.ppBuffer : 생성된 버퍼 반환

 

4.인덱스 버퍼를 파이프라인에 묶는다.(Input Assembler : IA)
ID3D11DeviceContext::IASetIndexBuffer을 이용하여 묶을 수 있다.

void IASetIndexBuffer(ID3D11Buffer* pIndexBuffer, DXGI_FORMAT Format, UINT Offset);

1.pIndexBuffer : 인덱스 버퍼에 대한 포인터

2.Format : 인덱스 버퍼의 데이터 형식 지정 

3.Offset : 인덱스 버퍼의 시작부터 사용할 첫 번째 인덱스까지의 크기(byte)

 

위 과정을 코드로 써보자

UINT indices[24] = 
{
	0, 1, 2, //삼각형 0
	0, 2, 3, //삼각형 1
	0, 3, 4, //삼각형 2
	0, 4, 5, //삼각형 3
	0, 5, 6, //삼각형 4
	0, 6, 7, //삼각형 5
	0, 7, 8, //삼각형 6
	0, 8, 1, //삼각형 7
}

//인덱스 버퍼 구조체 설정
D3D11_BUFFER_DESC desc;
desc.Usage = D3D11_USAGE_IMMUTABLE;
desc.ByteWidth = sizeof(UINT) * 24;
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
desc.CPUAccessFlags = 0;
desc.MiscFlag = 0;
desc.StructureByteStride = 0;

//버퍼 초기화 설정
D3D11_SUBRESOURCE_DATA subResource = { 0 };
subResource.pSysMem = indices;

//인덱스 버퍼 생성
ID3D11Buffer* buffer = NULL;
HR(md3dDevice->CreateBuffer(&desc, &subResource, &buffer);

//생성한 인덱스 버퍼를 파이프라인에 바인드
UINT stride = sizeof(Vertex);
UINT offset = 0;
md3dImmediateContext->IASetIndexBuffer(buffer, DXGI_FORMAT_R32_UINT, 0);

 

인덱스 버퍼를 이용하여 기본도형을 그릴 때에는 ID3D11DevcieContext::DrawIndexed 메소드를 호출해야 한다.

void ID3D11DeviceContext::DrawIndexed(UINT IndexCount, UINT StartIndexLocation, INT BaseVertexLocation);

1.IndexCount : 그리기 호출에서 사용할 인덱스들의 개수

2.StartIndexLocation : 사용할 첫 인덱스의 위치

3.BaseVertexLocation : 정점들을 가져오기 전, 사용할 인덱스에 더해지는 정수 값

 

728x90