DirectX11 使用Instancing技术提高重复模型的绘制效率

本文介绍了如何使用DirectX11的Instancing技术提高重复模型的绘制效率,避免大量draw call造成的性能损耗。通过指定输入布局、设置顶点结构和使用DrawIndexedInstanced方法,实现了一次draw call绘制多个带有不同属性的相同模型,显著提升了渲染效率。
摘要由CSDN通过智能技术生成

在游戏场景中,经常需要我们绘制大量相同的模型,比如英雄联盟中,战场上的小兵可以达到非常多的数量。

这里写图片描述

(图为英雄联盟游戏截图)

如果我们用以前的方法绘制,一个模型draw call一次,那么就会造成巨大的性能损耗。因为每次数据从内存传入显存都需要不少时间;而且每次draw call需要CPU和GPU进行周期同步,会导致CPU或GPU在等待;每次传入顶点数据后,都需要走一遍渲染管线,上下文也要进行切换等等。如果我们有一种方法,对于模型相同的游戏对象,只需要传一次模型的顶点数据,每个实例也可以包含不同的位置信息、颜色信息等,那么就可以极大增加渲染效率。DirectX10开始有Instancing技术的硬件支持,帮助我们完成解决这个问题。(这个问题在之前要通过程序员自己batch合并模型顶点来一次draw call来完成,而现在是通过硬件支持,更加方便)

一、指定输入布局

顶点元素描述如下:

typedef struct D3D11_INPUT_ELEMENT_DESC {
    LPCSTR SemanticName;
    UINT SemanticIndex;
    DXGI_FORMAT Format;
    UINT InputSlot;
    UINT AlignedByteOffset;
    D3D11_INPUT_CLASSIFICATION InputSlotClass;
    UINT InstanceDataStepRate;
} D3D11_INPUT_ELEMENT_DESC;

有几个新增的字段需要介绍一下,

  • InputSlotClass:为了区分顶点数据和实例数据,在输入布局元素中的InputSlotClass字段应当用D3D11_INPUT_PER_VERTEX_DATAD3D11_INPUT_PER_INSTANCE_DATA进行区分。
  • InstanceDataStepRate:指定每个实例数据有多少个实例要绘制。比如说我们有3种不同的实例颜色,但是有6个模型,我们可以设置2,那么前2个、中间2个、后面2个都分别占有不同的三种颜色。如果每个实例都有一个实例数据,那么就设为1。顶点数据只需要设为0。

我们的Demo中,实例数据包含了世界矩阵和每个实例的颜色,下面是一段代码示例:

const D3D11_INPUT_ELEMENT_DESC InputLayoutDesc::InstancedBasic32[
在 OSG 中使用 GPU Instancing 技术添加模型需要以下步骤: 1. 创建 InstancedGeometry 节点,用于存储实例化模型的数据。 ```cpp osg::ref_ptr<osg::InstancedGeometry> ig = new osg::InstancedGeometry(); ``` 2. 创建 Geometry 节点,用于存储模型的几何信息。 ```cpp osg::ref_ptr<osg::Geometry> geom = new osg::Geometry(); ``` 3. 设置 Geometry 节点的顶点数据、法线数据、纹理坐标等信息。 4. 创建 StateSet 节点,用于设置渲染状态。 ```cpp osg::ref_ptr<osg::StateSet> stateset = geom->getOrCreateStateSet(); ``` 5. 创建 UniformBufferObject 节点,用于存储每个实例化模型的位置、旋转、缩放等属性信息。 ```cpp osg::ref_ptr<osg::UniformBufferObject> ubo = new osg::UniformBufferObject(); ``` 6. 将 UniformBufferObject 节点添加到 InstancedGeometry 节点中。 ```cpp ig->setInstanceData(ubo); ``` 7. 将 InstancedGeometry 节点添加到场景图中。 ```cpp root->addChild(ig); ``` 8. 在渲染循环中,更新 UniformBufferObject 节点中每个实例化模型的属性信息。 ```cpp ubo->setMatrix(osg::Matrix::translate(x, y, z)); ``` 9. 使用 GraphicsContext::drawInstanced 方法进行渲染。 ```cpp view->getCamera()->getGraphicsContext()->drawInstanced(geom.get(), 0, numInstances); ``` 以上是使用 OSG 实现 GPU Instancing 技术添加模型的基本步骤,具体实现还需要根据场景的需求进行调整。添加模型时需要根据实际情况设置每个实例化模型的位置、旋转、缩放等属性信息,这些信息可以通过 UniformBufferObject 节点来管理。使用 GPU Instancing 技术可以大大减少绘制调用次数,提高渲染效率,适用于需要大量渲染相同模型的场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值