1.设置输入装配描述符
关键字:D3D11_INPUT_PER_INSTANCE_DATA
注意矩阵的更新方式,因为DXGI_FORMAT一次最多仅能够表达128位(16字节)数据,在对应矩阵的语义时,需要重复描述4次,区别在于语义索引为0-3.
const D3D11_INPUT_ELEMENT_DESC GameApp::VertexPosColor::inputLayout[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "World", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1},
{ "World", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 16, D3D11_INPUT_PER_INSTANCE_DATA, 1},
{ "World", 2, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 32, D3D11_INPUT_PER_INSTANCE_DATA, 1},
{ "World", 3, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 48, D3D11_INPUT_PER_INSTANCE_DATA, 1}
};
2.创建实例缓冲区
注意:需要能够动态更新
D3D11_BUFFER_DESC vbd;
ZeroMemory(&vbd, sizeof(vbd));
vbd.Usage = D3D11_USAGE_DYNAMIC;
vbd.ByteWidth = sizeof(InstancedData) * instances.size();
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
D3D11_SUBRESOURCE_DATA InitData;
ZeroMemory(&InitData, sizeof(InitData));
InitData.pSysMem = instances.data();
HR(m_pd3dDevice->CreateBuffer(&vbd, &InitData, m_pInstanceBuffer.GetAddressOf()));
3.输入装配阶段设置顶点缓冲和实例缓冲
// 输入装配阶段的顶点缓冲区设置
UINT strides[2] = { sizeof(VertexPosColor), sizeof(InstancedData)}; // 跨越字节数
UINT offsets[2] = { 0,0};
ID3D11Buffer* buffers[2] = { m_pVertexBuffer.Get(), m_pInstanceBuffer.Get() };// 起始偏移量
m_pd3dImmediateContext->IASetVertexBuffers(0, 2, buffers, strides, offsets);
4.绘制实例
m_pd3dImmediateContext->DrawIndexedInstanced(6, m_instancedNum, 0, 0, 0);
5.着色器设置
实例缓冲区的数据全都设置到顶点输入结构体中
struct VertexIn
{
float3 posL : POSITION;// 来自输入槽0
float4 color : COLOR;// 来自输入槽0
matrix world : World; // 来自输入槽1
};