2009-09-23 286 views
10

我正在设计我自己的粒子系统引擎,这是为了学习的目的,我真的不想使用现有的引擎。粒子系统设计?

现在我产生了美丽的粒子,但我想布置引擎,使它更容易与他们合作。

我一直在思考一个类“粒子系统”,

该类将包含以下引用:

particlesList:组成该系统的粒子列表。

systemEmitter:系统发射器,用于将颗粒,所述辐射源类应该能够执行若干粒子排放的技术,如例如,来自线,点发光,从多边形随机发射。同样,这个班级应该做排放控制,就像向一个点发射,远离一个点,在一个方向和时间发射。

particleController:管理用于围绕点例如旋转,可变的粒径,可变粒子的颜色,所述系统周围的区域,以将颗粒以不同的方式,碰撞检测,如果变necesary反应(与其它物体或颗粒内)。

粒子渲染:负责本系统,可变混合型,颗粒纹理,粒子类型,如三角形,圆形,自定义...

这四个项目中,将组成粒子系统类。某些FX可能需要多个粒子系统,例如Fire FX,可以使用一个系统进行火灾,一个系统用于烟雾,一个系统用于火花。

这是我在我的脑海,但我真的很想知道,如果这种设计方式是好的,或者如果你看到我失去了一些东西还是可以/应该做不同的事情。我没有想过一些简单的方法来“拯救”FX,比如说什么是告诉我的引擎的最佳方式,“画火”,“画爆炸”,“绘画喷泉”等等,也许存储FX信息在XML文件将是一个不错的主意,等等。

意见是真正欢迎,正如我前面所说,我真的要构建这个,而不是使用其他引擎,学习的原因。

回答

5

这个设置应该没问题。我希望你在考虑的是什么数据会构成一个粒子类的粒子。您只需拥有最基本的基本功能,因此您只需在运行系统时尽可能少地读取/写入内存。

至于使数据驱动应该是非常简单的。我会建议一个XML和二进制格式选项进行加载。所以你可以在开发过程中轻松地调整东西(而不是使用工具)。一旦你有一个工具或完成调整,我会将XML转换为二进制快速加载。

您可能还需要一个处理这些粒子系统的创建和更新的经理类。这也可以让你有一个地方来处理与你的所有系统有关的其他功能。这方面的一些例子是限制可以出于性能原因而管理的粒子系统或粒子的数量,或者限制所有系统应该考虑的碰撞平面的数量。

你提到这是用于教育目的,在这方面,这些东西是非常挑剔的(但重要的是,如果你在一个粒子很重的游戏中使用它)。

我假设这是使用像DirectX或OpenGL API来渲染。在这方面,我会让粒子效应为您的顶点信息共享相同的内存池。这有助于渲染速度很多。我还会跟踪受颗粒系统影响的区域的边界以用于截锥体剔除(AABB或Circle)。

更新粒子系统的很大一部分是属性如何从一个值转移到另一个值。您可以更加动态地插值数值效果更好。简单地进行线性插值就足够了,但是最好有一个用于内插值的动态图形。例如,在一秒钟内不是从0到255的蓝色,而是在0.2秒内变为0到128,然后在0.8秒内变为128-255。添加这将大大增加你的效果看起来的选项。

除此之外,我认为你对你想做什么有一个很好的想法。你提到渲染不同类型的粒子告诉我你正在以正确的方式思考这个问题。我已经看到人们制作的粒子引擎只是专注于渲染四边形。选择发射3D几何图形确实让事情看起来很棒。你也可以考虑(如果你还没有)让你的系统有能力把模型信息和动态分裂成单独的粒子发射出去。实际上,爆炸模型看起来好得多,然后显示一些爆炸粒子并淡化物体或将其切换到损坏状态。

+0

感谢您的回应!是的,我正在考虑使用OpenGL进行渲染。此外,非线性插值的想法非常好,应该能够创建一些相当不错的视觉效果。 – Goles 2009-09-23 21:50:47

1

只是简单的2D精灵粒子优化的一些想法。

一个好主意是发送顶点数组/ VBO中的所有粒子,并使用顶点着色器随着时间的推移更新它们的位置。这很好,如果你有一个简单的运动,可以用x(t)y(t)(即它们只取决于时间)的数学公式很容易地描述。

另一个好主意是使用点精灵代替三角形和四边形。这应该将管道上的所需带宽减少到四分之一。


在我的空间SIM我已经实现了最微不足道的方法:发送为使用glBegin()/glEnd()纹理四边形颗粒。它们作为单独的对象被倾入当前的“部门”,并且完全独立于倾销之后。这是最原始,愚蠢和愚蠢的事情,并且导致性能的大幅下降,尤其是因为我所做的是通过STL向量的迭代器遍历对象并按顺序发送每一个对象。

你需要考虑你想要多少粒子,以及你希望他们做什么。 *你想让他们对环境做出反应并相互碰撞吗?然后你需要在CPU上处理更新并重复发送数据。 *他们只是以最愚蠢的方式飞来飞去吗?然后,您可以将所有粒子发送为VBO和TBO,并在着色器中更新它们。

玩得开心!


更新,从提问者涉及到的注释#1 :-)

我会做的是使用KISS principle。这意味着:一个名为ParticleEmitter的类包含一个顶点数组,一个速度数组以及一个带有简单碰撞体(如平面,球体,三角形)实例的STL。此外,有一个“全球”* STL vector与colliders。然后根据碰撞体更新速度。

类似的可以用影响因子(重力,风等)完成:ParticleEmitter中的另一个STL矢量与影响器和另一个影响器的“全局”STL vector

影响者和对撞者将是实现affectParticle(particle_t*)的类。其中struct particle_t { float x,y,z; float vx,vy,vz; }。我会保持它POD结构,并运行更新ParticleEmitter::update()

但是,如果你在iPhone上运行它,它可能是过度复杂吗?也许你可以逃避你已经实现的东西?我不知道我的设计可能会如何影响基准测试结果,但如果您保持粒子,对撞机和影响因子倒数,这对我来说听起来似乎足够合理,因为它听起来可能会大约与n*c+n*a一起缩放。

这些只是我的临时想法,以及我如何亲自实施它。您的设计或其他人的设计可能会更好:-)

*“Global”在引号内,因为使用任何您正在使用的空间分区可能是有意义的。

+0

你好伊万,谢谢你的答案,现在我正在iPhone上开发这个系统,自从我达到我的里程碑,渲染3.000 16x16像素GL_POINT_SPRITES,使用VBOs和达到45-55 fps之间,我取得了很好的进展。我认为这很不错。 但是现在我想开始研究粒子如何与其他物体相互作用和碰撞,并在某些方面进行了思考,但我真的很想听到关于它的一些想法。 再次感谢。 – Goles 2009-09-30 04:31:09

1

我在C++中为自己的引擎实现了相同的优秀设计。我没有使用引用和模板策略(策略 - 读取Alexandresku的“Modern C++ Desing”)。静态多态性提供了更好的性能。

0

我想根据我的经验做一些评论。

  1. 传统上,大多数粒子使用AOS(结构阵列)来存储粒子属性。但这可能不是最好的决定。使用SOA(数组结构)表示将为您添加每个粒子系统的属性提供很大的灵活性。而且,使用SOA进行SIMD可以提高性能。例如,使用SSE指令一起做4个粒子。
  2. 粒子发射位置只是一个粒子属性的初始化。当你发射粒子时,你可能需要初始化其他属性,例如生命周期,速度等。你可以将所有这些特征抽象为初始化。对于职位,你可能有一个磁盘初始化器,盒子初始化器等。
  3. 一些现代粒子系统采用事件的概念。粒子系统可能会产生事件(例如雨与地面碰撞),其他粒子系统可能会监听并执行某些操作(例如发射飞溅)。

顺便说一句,我认为最好的方法是通过研究现有的应用程序/中间件的设计,并且还通过实验。