实例化数据管理

时间:2014-07-16 00:50:44

标签: c# xna buffer particles

我试图使用实例绘制几千个粒子。它起作用并且速度很快,但我有一个瓶颈会减慢整个程序的速度。

我的Particle课程类似于:

public class Particle
{
    public Vector2 Position;

    //More data not used for drawing
    //....
}

现在我的DrawLoop()我有这样的事情:

Vector2[] instanceData = new Vector2[numParticles];

public void Draw()
{
    for(int i = 0; i < numParticles; ++i)
        instanceData[i] = Particles[i].Position; //THAT'S the slow part

    instanceBuffer.SetData(instanceData);

    //Now draw VertexBuffer using instancing
    //...
}

我尝试过使用Parallel.For,但它并没有加快速度,因为我有8000个粒子。我还查看了MSDN中的particlesystem示例。但是他们的Particle结构只包含绘制粒子的数据,并且在着色器中计算位置。但是,我需要为几种算法提供额外的数据。

我无法想到课程设计,因此我不需要每帧都将粒子位置分配给数组。

1 个答案:

答案 0 :(得分:0)

由于此问题最终源于所使用的数据结构,因此,让我为您提供一个替代链接列表的常用替代方案,例如此方案。

链接列表通常不是一个存储粒子的好主意,原因有两个:一,你不能有效地随机访问它们,正如你在这里发现的那样;两个,链接列表很差locality of reference。鉴于粒子系统的性能要求,后一点可能是杀手锏。

标准列表具有更好的引用位置,但正如您所发现的,添加和删除项目可能会很慢,这是您在粒子引擎中常见的事情。

我们可以改进吗?

让我们从一个比列表更简单的东西开始,一个简单的数组。为了简单起见,让我们对引擎中的粒子数量进行硬化(我们稍后会对此进行补救)。

private const Int32 ParticleCount = 8000;
private readonly Particle[] particles = new Particle[ParticleCount];
private Int32 activeParticles = 0;

假设你有空间,你总是可以在恒定时间内将粒子添加到数组的末尾:

particles[activeParticles++] = newParticleData;

但是移除一个粒子是O(n),因为它之后的所有粒子都需要向下移动:

var indexOfRemovedParticle = 12;
particles.RemoveAt(indexOfRemovedParticle);
activeParticles--;

我们还可以在不变的时间内做些什么?好吧,我们可以移动粒子:

particles[n] = particles[m];

我们可以用它来改善我们的表现吗?

是的!将删除操作更改为移动操作,O(n)变为O(1):

var indexOfRemovedParticle = 12;
var temp = particles[indexOfRemovedParticle];
particles[indexOfRemovedParticles] = particles[activeParticles - 1];
particles[activeParticles - 1] = temp;
activeParticles--;

我们对数组进行分区:开头的所有粒子都是活动的,并且末尾的所有粒子都是无效的。因此,要移除粒子,我们所要做的就是将它与最后一个活动粒子交换,然后减少活动粒子的数量。

(请注意,你需要删除粒子数组中的索引。如果你必须去搜索它,你最终会恢复到O(n)时间;但是,因为粒子的通常工作流程是&# 34;循环遍历整个列表,更新每个粒子,如果它已经死了,将其从列表中删除,&#34;无论如何,你经常会获得死亡粒子的索引。#34; free&#34; )

现在,这一切都假定了固定数量的粒子,但是如果你需要更多的灵活性,你可以像List<T>类一样解决这个问题:每当你用完房间时,只需分配一个更大的数组,将所有内容复制到其中。

此数据结构提供快速插入和删除,快速随机访问以及良好的参考局部性。通过将Particle类放入结构中,可以进一步改进后者,以便将所有粒子数据连续存储在内存中。