GPU가 정점 배열에 접근할 수 있으려면, 배열의 정점들을 버퍼(buffer)라고 부르는 특별한 자원에 담아 두어야 한다. 마치 자원 말고 자원 뷰를 묶는 것처럼? Direct3D 코드에서 버퍼는 ID3D11Buffer 인터페이스로 대표된다. 정점들을 담는 버퍼를 '정점 버퍼'라고 부른다. Direct3D의 버퍼들은 자료를 담을 뿐만 아니라, CPU나 GPU가 자료에 어떻게 접근할 수 있고 버퍼가 파이프라인의 어디에 묶이는지에 대한 정보도 가진다. 정점 버퍼는 다음 과정을 통해 생성하고 묶는다.
다음은 D3D11_BUFFER_DESC 구조체이다.
struct D3D11_BUFFER_DESC {
UINT ByteWidth;
D3D11_USAGE Usage;
UINT BindFlags;
UINT CPUAccessFlags;
UINT MiscFlags;
UINT StructureByteStride;
다음으로 D3D11_SUBRESOURCE_DATA 구조체의 정의는 다음과 같다.
struct D3D11_SUBRESOURCE_DATA {
const void *pSysMem;
UINT SysMemPitch;
UINT SysMemSlicePitch;
}
이제 이 정보를 토대로 정점 버퍼를 생성할 수 있다. ID3D11Device::CreateBuffer를 사용한다.
md3dDevice->CreateBuffer(&desc, &subData, &vertexBuffer);
assert(SUCCEEDED(hr));
제1 매개변수는 D3D11_BUFFER_DESC 구조체 객체이다. 제2 매개변수는 D3D11_SUBRESOURCE_DATA 구조체 객체이다. 제3 매개변수는 생성한 정점 버퍼를 반환 받을 포인터 변수이다.
이렇게 생성된 버퍼의 정점들을 실제로 파이프라인으로 공급하려면, 버퍼를 장치의 한 입력 슬롯에 묶어야 한다. 이 메서드를 쓴다.
void ID3D11DeviceContext::IASetVertexBuffers(
UINT StartSlot;
UINT NumBuffers,
ID3D11Buffer *const *ppVertexBuffers,
const UINT *pStrides
const UINT *pOffsets);
입력 슬롯에 붙인 정점 버퍼는 다시 변경하지 않는 한 계속 그 입력 슬롯에 붙어있다. 마치 기본도형 위상구조(primitive topology), 입력 배치(input layout)처럼 말이다.
이렇게 하면 정점 버퍼를 GPU에게 완전히 제공한 것이다. 하지만 이렇게 했다고 저절로 그리기 작업이 진행되는 것은 아니다. 그리기 연산을 실제로 시작하려면, ID3D11DeviceContext::Draw 메서드를 호출해야 한다.
void ID3D11DeviceContext::Draw(UINT VertexCount, UINT StartVertexLocation);
제1 매개변수는 정점 갯수, 제2 매개변수는 그 정점의 시작 위치를 말한다.
다음은 예시 코드이다.
Vertex vertices[] =
{
{ XMFLOAT3(-1.0f, -1.0f, -1.0f), (const float*)&Colors::White },
{ XMFLOAT3(-1.0f, +1.0f, -1.0f), (const float*)&Colors::Black },
{ XMFLOAT3(+1.0f, +1.0f, -1.0f), (const float*)&Colors::Red },
{ XMFLOAT3(+1.0f, -1.0f, -1.0f), (const float*)&Colors::Green },
{ XMFLOAT3(-1.0f, -1.0f, +1.0f), (const float*)&Colors::Blue },
{ XMFLOAT3(-1.0f, +1.0f, +1.0f), (const float*)&Colors::Yellow },
{ XMFLOAT3(+1.0f, +1.0f, +1.0f), (const float*)&Colors::Cyan },
{ XMFLOAT3(+1.0f, -1.0f, +1.0f), (const float*)&Colors::Magenta }
};
D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(Vertex) * 8;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
vbd.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = vertices;
ID3DllBuffer* mVB
HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mvB));
UINT stride = sizeof(Vertex);
UINT offset = 0;
md3dImmediateContext->IASetVertexBuffers(0, 1, &mvB, &stride, &offset);
void ID3D11DeviceContext::Draw(UINT VertexCount, UINT StartVertexLocation)