实例(instancing)绘制

应用场景:

这种方式无法减少被渲染的顶点的数量,但是可以降低带宽的压力,尤其是在绘制大量重复场景的时候具有得天独厚的优势。

 

原理:

在顶点buffer进入渲染管道的时候,并不是直接送给VS进行渲染,而是进入一个IA阶段。正是因为这个原因,才多了一次对顶点进行二次加工的机会。以下是从IA进入的数据:

 

IASetIndexBuffer :索引缓冲区绑定到汇编器的输入阶段。

 

IASetInputLayout :输入布局对象绑定到汇编器的输入阶段。

 

IASetPrimitiveTopology :绑定信息的基本类型和数据顺序来描述的输入数据输入汇编阶段。

 

IASetVertexBuffers :顶点缓冲区数组绑定到汇编器的输入阶段。

 

这里面IB是顶点的索引没啥好说的,PT的定义体元描述顶点绘制的形状的跟这个也没关系。VB是存储顶点的buffer,这里是s说明可以同时传递n个VB和1个IB。关键的是IL对输入的数据格式的定义

 

写道

 

typedef struct D3D11_INPUT_ELEMENT_DESC {
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的数据进行加工的。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值