gpt4 book ai didi

XNA-同时创建很多粒子

转载 作者:行者123 更新时间:2023-12-04 15:27:42 26 4
gpt4 key购买 nike

是时候提出另一个XNA问题了。但这一次纯粹是从技术设计的角度。

我的情况是:我已经基于GPU计算创建了一个粒子引擎,虽然还不完整,但是可以工作。我的GPU可以轻松处理10k粒子而不会费劲,如果再增加一堆,我也不会感到惊讶。

我的问题:每当我同时创建很多粒子时,我的帧速率就会讨厌我。为什么?即使我已将其最小化以仅包含几乎所有的内存操作,但仍占用了大量CPU资源。

仍然可以通过CPU调用来完成粒子的创建,例如:

  • 方法要创建粒子并进行调用。
  • Quad以顶点的形式创建并存储在缓冲区
  • Buffer插入到GPU中,我的CPU可以专注于其他事情

  • 当我大约有4个发射器每帧创建一个粒子时,我的FPS会降低(确保每秒只有4帧,但是15个发射器会使我的FPS下降到25)。

    创建粒子:
            //### As you can see, not a lot of action here. ###
    ParticleVertex []tmpVertices = ParticleQuad.Vertices(Position,Velocity,this.TimeAlive);
    particleVertices[i] = tmpVertices[0];
    particleVertices[i + 1] = tmpVertices[1];
    particleVertices[i + 2] = tmpVertices[2];
    particleVertices[i + 3] = tmpVertices[3];
    particleVertices[i + 4] = tmpVertices[4];
    particleVertices[i + 5] = tmpVertices[5];

    particleVertexBuffer.SetData(particleVertices);

    我的想法是,也许我不应该经常创建粒子,也许有一种方法可以让GPU创建所有东西,或者也许我只是不知道您如何做这些事情。 ;)

    编辑:如果我不是经常创建粒子,那么如何使它看起来仍然不错?

    所以我在这里发布,希望您知道如何设计一个好的粒子引擎,如果我走错了路。

    最佳答案

    没有办法让GPU创建所有内容(缺少使用需要SM4.0的Geometry Shaders)。

    如果我要创建一个粒子系统以最大程度地提高CPU效率,则可以在顶点和索引缓冲区中预先创建(仅出于示例目的选择一个数字),如下所示:100个粒子:

  • 制作一个包含四边形(每个粒子四个顶点,而不是六个顶点)的顶点缓冲区
  • 使用自定义顶点格式,该格式可以存储“时间偏移”值以及“初始速度”值(类似于XNA Particle 3D Sample)
  • 设置时间值,以使每个粒子的时间偏移量小于最后一个粒子的1/100(因此,通过缓冲区的偏移量范围为1.0到0.01)。
  • 随机设置初始速度。
  • 使用索引缓冲区,该缓冲区使用每个粒子的四个顶点为您提供两个三角形。

  • 而且很酷的事情是,您只需要执行一次即可-您可以对所有粒子系统重复使用相同的顶点缓冲区和索引缓冲区(前提是它们对于最大的粒子系统而言足够大)。

    然后,我将拥有一个顶点着色器,它将接受以下输入:
  • 每个顶点:
  • 时间偏移
  • 初始速度
  • 着色器参数:
  • 当前时间
  • 粒子生命周期(也是粒子时间回绕值,以及正在使用的缓冲区中的粒子分数)
  • 粒子系统的位置/旋转/比例(世界矩阵)
  • 您喜欢的任何其他有趣的输入,例如:粒度,重力,风等
  • 时间标度(获取实时信息,因此速度和其他物理计算很有意义)

  • 然后,该顶点着色器(再次类似于 XNA Particle 3D Sample)可以根据粒子的初始速度和该粒子在模拟中的时间来确定其顶点的位置。

    每个粒子的时间为(伪代码):
    time = (currentTime + timeOffset) % particleLifetime;

    换句话说,随着时间的流逝,颗粒将以恒定的速率释放(由于偏移)。而且,只要粒子在 time = particleLifetime处死亡(或者浮点模数为1.0?会令人困惑),时间就会循环回到 time = 0.0,以便粒子重新进入动画。

    然后,当需要绘制粒子时,我将设置缓冲区,着色器和着色器参数,并调用 DrawIndexedPrimitives 。现在,这是一个聪明的地方:我将设置 startIndexprimitiveCount,以便在动画中期不会出现任何粒子。当粒子系统第一次启动时,我将绘制1个粒子(2个基本体),等到该粒子即将死亡时,我将绘制所有100个粒子,其中第100个将开始。

    然后,片刻之后,第一个粒子的计时器将循环并使其成为第101个粒子。

    (如果我只想在系统中使用50个粒子,则将粒子生命周期设置为0.5,并且只绘制顶点/索引缓冲区中100个粒子中的前50个。)

    当需要关闭粒子系统时-只需做相反的操作-设置 startIndexprimitiveCount,以使粒子死后不再被绘制。

    现在,我必须承认我已经掩盖了所涉及的数学以及有关使用四边形作为粒子的一些细节-但要弄清楚它应该不难。 要理解的基本原理是将顶点/索引缓冲区视为粒子的圆形缓冲区。

    圆形缓冲区的一个缺点是,当您停止发射粒子时,除非当当前时间是粒子生命周期的倍数时停止,否则最终会出现一组事件粒子,这些粒子跨越缓冲区两端并留有间隙。中间-因此需要两次抽奖(慢一点)。为避免这种情况,您可以等到停止的时间到了-对于大多数系统来说,这应该没问题,但是对于某些系统来说可能很奇怪(例如:“慢速”粒子系统需要立即停止)。

    这种方法的另一个缺点是必须以恒定的速率释放粒子-尽管这对于粒子系统通常是非常典型的(显然,这是每个系统且速率是可调整的)。稍作调整,就可以实现爆炸效果(所有粒子立即释放)。

    话虽如此:如果可能的话,使用现有的粒子库可能是值得的。

    关于XNA-同时创建很多粒子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3136021/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com