应用场景:
这种方式无法减少被渲染的顶点的数量,但是可以降低带宽的压力,尤其是在绘制大量重复场景的时候具有得天独厚的优势。
原理:
在顶点buffer进入渲染管道的时候,并不是直接送给VS进行渲染,而是进入一个IA阶段。正是因为这个原因,才多了一次对顶点进行二次加工的机会。以下是从IA进入的数据:
IASetIndexBuffer :索引缓冲区绑定到汇编器的输入阶段。
IASetInputLayout :输入布局对象绑定到汇编器的输入阶段。
IASetPrimitiveTopology :绑定信息的基本类型和数据顺序来描述的输入数据输入汇编阶段。
IASetVertexBuffers :顶点缓冲区数组绑定到汇编器的输入阶段。
这里面IB是顶点的索引没啥好说的,PT的定义体元描述顶点绘制的形状的跟这个也没关系。VB是存储顶点的buffer,这里是s说明可以同时传递n个VB和1个IB。关键的是IL对输入的数据格式的定义。
LPCSTR SemanticName; // 这个是定义HLSL中的语义,HLSL就是通过这个语义来识别它。
UINT SemanticIndex; // 这个是语义取重名的时候,用来区分的序号,例如矩阵要描述里面的每一个元素,总不能取不同的名字吧,所以用序号区分
DXGI_FORMAT Format; // 数据格式,它对应HLSL的数据类型
UINT InputSlot; // 输入插槽,设置为0即可
UINT AlignedByteOffset; // 对齐的偏移量,不知道该如何计算,还好只需要设置为:D3D11_APPEND_ALIGNED_ELEMENT就好了
D3D11_INPUT_CLASSIFICATION InputSlotClass; //
UINT InstanceDataStepRate; // 这个值必须为0 - -。
} D3D11_INPUT_ELEMENT_DESC;
typedef enum D3D11_INPUT_CLASSIFICATION { 对应倒数第2个
D3D11_INPUT_PER_VERTEX_DATA = 0, // 输入的是每个顶点的数据
D3D11_INPUT_PER_INSTANCE_DATA = 1 // 输入的是每个实例的数据
} D3D11_INPUT_CLASSIFICATION;
InputSlot和InputSlotClass要对应起来,暂时这么理解的,如果创建INSTANCE的话,InputSlotClass为D3D11_INPUT_PER_INSTANCE_DATA 所以InputSlot也要等于1,暂时这么理解,不一定对。
整个创建INSTANCE最主要的就是把这个地方对应好就行了。
下面给出大致的实现代码:
1.创建instanceBuff:从本质上来讲,它其实就是VB
// 设置索引缓冲描述. instanceBufferDesc.Usage = D3D11_USAGE_DEFAULT; instanceBufferDesc.ByteWidth = sizeof(float3) * mInstanceCount; instanceBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; // 这个比较重要 instanceBufferDesc.CPUAccessFlags = 0; instanceBufferDesc.MiscFlags = 0; instanceBufferDesc.StructureByteStride = 0; // 指向存临时索引缓冲. instanceData.pSysMem = mInstancePos; instanceData.SysMemPitch = 0; instanceData.SysMemSlicePitch = 0; // 创建索引缓冲. device->CreateBuffer(&instanceBufferDesc, &instanceData, &mInstanceBuff);
2.定义语义:
{"INSTANCEPOS",0,DXGI_FORMAT_R32G32B32_FLOAT,1,D3D11_APPEND_ALIGNED_ELEMENT,D3D11_INPUT_PER_INSTANCE_DATA,1}
这里第4个参数为1,说明它是从第二个插槽输入进去的,倒数第二个参数说明它是一个实例的数据,而不是顶点的数据。最后一个参数还不知道干什么用的,写成1是对的。
3.绘制:
immediateContext->IASetVertexBuffers(1, 1, &mInstanceBuff, &stride2, &offset); mContext->DrawIndexedInstanced(indexCount, instanceCount, 0, 0,0);
文档说的不详细,只能靠别人的文章描述,或者自己的经验进行总结。这个暂时这个样了,以后了解的更深刻的时候补充
总结:在学习API的时候,最重要的不是用会了什么,而是了解了作者的意图是什么。只有了解 了作者的意图,你才能把整套API的体系打通。而一套API是否难学,也是看读者是否能够很容易理解作者的意图。VB是一个数据流,而IL是它的格式描述,IA阶段也正是根据IL的描述对VB的数据进行加工的。