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

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

by 민돌이2 2022. 2. 8.

기본적으로 정점 버퍼의 생성과 거의 유사하다. 정점 대신 인덱스(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

댓글