45.인덱스와 인덱스 버퍼(Index Buffer)
기본적으로 정점 버퍼의 생성과 거의 유사하다. 정점 대신 인덱스(index)를 담는다는 점만 다르다.
인덱스 버퍼를 생성하고 파이프라인에 묶기까지 다음과 같은 과정을 거친다.
- 생성할 버퍼를 서술하는 D3D11_BUFFER_DESC 구조체를 채운다.
- 버퍼의 초기화에 사용할 자료를 서술하는 D3D11_SUBRESOURCE_DATA 구조체를 채운다.
- ID3D11Device::CreateBuffer를 호출해서 버퍼를 생성한다.
- 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 : 정점들을 가져오기 전, 사용할 인덱스에 더해지는 정수 값