11

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

现在我生成了漂亮的粒子,但我想对引擎进行布局以使其更容易使用它们。

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

该类将包含以下引用:

particleList:组成系统的粒子列表。

systemEmitter:粒子的系统发射器,Emitter 类应该能够执行多种粒子发射技术,例如从线、点发射、从多边形随机发射。这个类也应该做发射控制,比如向一个点发射,远离一个点,在一个方向和时间发射。

粒子控制器:管理例如围绕一个点的旋转、可变粒子大小、可变粒子颜色、粒子以不同方式反应的系统周围区域、碰撞检测(与其他对象或在必要时在粒子内)。

粒子渲染器:负责绘制这个系统,可变混合类型,粒子纹理,粒子类型如三角形,圆形,自定义......

这四项,就组成了粒子系统类。一些 FX 可能需要多个粒子系统,例如 Fire FX,可以使用一个系统用于火,一个系统用于烟雾,一个系统用于火花。

这就是我的想法,但我真的很想知道这种设计方法是否良好,或者您是否看到我遗漏了某些东西或可以/应该做一些不同的事情。我还没有想过一些简单的方法来“保存”FX,例如什么是告诉我的引擎的最佳方式,“draw Fire”、“draw explode”、“draw喷泉”等,也许存储 FX 信息在 xml 文件中将是一个好主意,等等。

非常欢迎提出意见,正如我之前所说,出于学习的原因,我真的想构建这个,而不是使用另一个引擎。

4

4 回答 4

5

这个设置应该没问题。我希望您考虑的是哪些数据将构成粒子类中的粒子。您只想拥有最基本的必需品,因此在运行系统时只需要读/写尽可能少的内存。

就使其成为数据驱动而言,这应该是非常简单的。我建议使用 xml 和二进制格式选项进行加载。因此您可以在开发时轻松调整内容(并且没有工具)。一旦你有了工具或完成调整,我会将 xml 转换为二进制文件以便快速加载。

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

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

我假设这是使用 DirectX 或 OpenGL 之类的 API 进行渲染。在这方面,我会让粒子效果都为您的顶点信息共享相同的内存池。这对渲染速度有很大帮助。我还将跟踪受粒子系统影响的区域范围,以用于截头体剔除(AABB 或圆形)。

更新粒子系统的很大一部分是属性如何从一个值变为另一个值。您可以使值的插值越动态,您的效果看起来就越好。简单地线性插值就足够了,但最好有一个用于插值的动态图。例如,与其在 0.2 秒内从 0 到 255 蓝,不如在 0.2 秒内从 0 到 128,然后在 0.8 秒内从 128 到 255,这可能很酷。添加这将大大增加您的效果外观的选项。

除此之外,我认为您对自己想做的事情有一个很好的想法。你提到渲染不同类型的粒子告诉我你正在以正确的方式思考这个问题。我见过人们制作粒子引擎只专注于渲染广告牌四边形。可以选择发射 3d 几何体真的让事情看起来很棒。您可能还想考虑(如果您还没有)让您的系统能够获取模型信息并将其动态拆分为要发射的单独粒子。实际上,爆炸模型看起来比显示一些爆炸粒子并淡出对象或将其切换到损坏状态要好得多。

于 2009-09-23T16:16:06.527 回答
1

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

一个好主意是发送顶点数组/VBO 中的所有粒子,并使用顶点着色器随时间更新它们的位置。如果您有一个可以使用数学公式轻松描述的简单运动,那就太好了x(t)y(t)也就是说,它们仅取决于时间)。

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


在我的太空模拟中,我实现了最简单的方法:使用glBegin()/将粒子作为纹理四边形发送glEnd()。它们作为单独的对象被倾倒到当前的“扇区”中,并且完全独立于倾倒的时间。这是最原始、最愚蠢和最愚蠢的事情,并且会大大降低性能,特别是因为我所做的是通过 STL 向量的迭代器遍历对象并按顺序发送每个对象。

你需要考虑你想要多少粒子,以及你想让它们做什么。*你想让他们对周围环境做出反应并发生碰撞吗?然后,您需要在 CPU 上处理更新并一遍又一遍地发送数据。* 他们只是以最愚蠢的方式飞来飞去吗?然后,您可能能够以 VBO 和 TBO 形式发送所有粒子,并在着色器中更新它们。

玩得开心!


更新以与提问者的评论 #1 相关:-)

我要做的是使用KISS 原则。这意味着:一个名为的类,ParticleEmitter包含一个顶点数组、一个速度数组和一个 STL vector,其中包含平面、球体、三角形等简单对撞机的实例。vector此外,还有一个带有碰撞器的“全局”* STL 。然后根据对撞机更新速度。

可以对影响器(重力、风等)进行类似的操作:另一个带有影响器的 STL 向量ParticleEmitter和另一个带有影响器的“全局”STL vector

Affectors 和 colliders 将是实现affectParticle(particle_t*). 哪里struct particle_t { float x,y,z; float vx,vy,vz; }。我会将其保留为 POD 结构,并在ParticleEmitter::update().

但是,如果您在 iPhone 上运行它,会不会过于复杂?也许你可以摆脱你已经实施的?我不知道我的设计会如何影响基准测试结果,但如果你让粒子、对撞机和影响器倒计时,这对我来说听起来足够合理,因为它听起来可能会以大约n*c+n*a.

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

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

于 2009-09-29T20:43:15.020 回答
1

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

于 2010-03-14T20:28:03.347 回答
0

我想根据我的经验发表几点意见。

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

顺便说一句,我认为最好的方法是研究现有应用程序/中间件的设计,以及进行实验。

于 2012-11-14T09:51:12.053 回答