Quagmire 粒子引擎






4.71/5 (17投票s)
2005年2月23日
6分钟阅读

110443

4094
一个面向对象的OpenGL粒子引擎,用于简单地创建高级粒子效果。
全局概览
OpenGL是一个强大的图形库,可以用来渲染一些惊人的效果。尽管这个库功能强大,但创建粒子效果可能会非常麻烦。随附的粒子引擎旨在极大地简化此类效果的创建。此处提供的代码远非完美,但它仅仅是这项工作的开始。欢迎提出任何建议、想法或对此代码的修改。
粒子效果
粒子效果的概念非常简单。粒子效果可以用来模拟火焰、烟花、喷泉、雪、雨、爆炸以及许多其他事物。这些效果是通过创建一定数量的粒子来产生的。根据对性能和逼真度的需求,粒子的数量可以从50个到数千个不等。每个粒子都有自己的位置、大小、速度、颜色、寿命和图像。粒子引擎控制粒子并使其根据粒子本身的规则进行反应。
随着粒子逐渐消失,粒子引擎会收到粒子“死亡”的警报。一旦所有粒子死亡,效果就会停止,或者如果引擎收到粒子死亡的警报,它可以重新初始化并再次显示。您可能希望查看此粒子引擎的火焰演示。它使用 glut[^] 来简化演示的Windows编程方面,并且实际的粒子引擎不依赖于它。
粒子概述
粒子封装在 QdParticle
中,并由 QdParticleEngine
使用。粒子引擎用于操纵粒子及其变量。粒子拥有的变量控制它们的行为,并且在粒子初始化后,不应手动更改它们。以下是 QdParticleEngine
的成员函数列表,用于操作存储在粒子中的数据。
表 1.1 QdParticleEngine
的成员函数。
函数 | Effect |
setCurrentColor(nParticle,fRed,fGreen,fBlue,fAlpha) |
在绘制粒子之前设置要更改的颜色。粒子的颜色将通过此颜色和位图的颜色确定。 |
setFadeColor(nParticle,fRed,fGreen,fBlue,fAlpha) |
每次更新粒子时,当前颜色变为其先前值加上给定颜色的值。 |
setDirection(nParticle,fX,fY,fZ) |
每次更新粒子时,其坐标变为其先前值加上给定值的值。 |
setGravity(nParticle,fX,fY,fZ) |
重力类似于方向,不同之处在于随着粒子年龄的增长,其效果也会增强。如果方向设置为正Y值,而重力设置为小的负Y值,粒子将上升,减速,然后下落。 |
setLR(nParticle,fX,fY,fZ) |
设置右下角的初始位置。 |
setUL(nParticle,fX,fY,fZ) |
设置左上角的初始位置。 |
setAge(nParticle,fAge) |
设置计算重力影响的年龄。当粒子初始化时,应将其设置为0。 |
setGravityFactor(nParticle, fGravityFactor) |
重力因子可以使重力作用更强或更弱。 |
setLife(nParticle,fLife) |
设置粒子的“生命力”。当生命值为0时,粒子“死亡”。 |
setFadeLife(nParticle,fFadeLife) |
设置每次更新粒子时应添加到生命中的值。应为负值。 |
粒子在堆上使用 init(nParticles)
函数创建在一个粒子数组中。参数是数组中存在的粒子数量。当引擎被解构时,它会删除堆上的这些粒子。init函数只能调用一次。引擎控制的粒子数量越多,效果以最大速度运行时就会越慢。
创建您自己的引擎
创建一个类来封装效果,继承自 QdParticleEngine
。添加您的引擎将使用的任何变量,并使用其构造函数根据需要初始化这些变量。虚拟函数 resetParticles()
和 particleDead
应用于设置各个粒子的变量。
resetParticles()
函数最初被调用,并且可以被多次调用以将粒子带回到它们最初的位置。因为随机数生成被用于为其中的变量赋值,所以默认的随机数生成器需要进行播种。
srand(time(NULL));
现在需要用粒子在时间流逝中如何反应的信息来填充粒子变量。在所包含的演示中,每个粒子将经历的初始化将与每个粒子在逐渐消失并用数据重新初始化时相同。我可以复制粘贴大量代码,但这除了是不良实践外,对我来说还要做更多的工作。解决方案是为每个粒子调用 particleDead()
函数。
int nCount=0; while(nCount != m_nParticles) { particleDead(nCount); nCount++; }
变量 m_nParticles
由函数 init(nParticles)
设置,无需手动更改。这个函数可以很容易地以一种与 particleDead(nParticle)
函数完全无关的方式初始化粒子,尽管火引擎与它在逻辑上联系更紧密。
当粒子的 m_fLife
变量小于 0 时,particleDead()
函数被调用。这个变量通过使用 setLife()
和 setLifeFade()
变量初始化而随时间稳定变化。此外,当粒子重新初始化时,将帧和年龄设置为 0 很重要。setFrame()
和 setAge
函数应相应使用。如果这些函数未被调用,重力变量将产生异常效果。
在火引擎中,使用了一个非默认构造函数来设置粒子的初始颜色。粒子引擎内的构造函数和变量可以用于此类事情,或用于其他适合的原因。
粒子位图路径
默认情况下,用于每个粒子的位图名为 *particle.bmp*,但路径可以更改。在粒子引擎调用 init()
函数之前,调用函数 setImgPath()
。如果提供给引擎的路径不正确,如果图像不是有效的位图,或者由于其他原因引擎无法使用位图,则在初始化时可执行文件可能会显示一条不太有用的错误消息。
错误信息:位图无效
可以重叠的粒子
为了使大多数粒子效果起作用,并允许粒子相互重叠而不会擦除之前创建的图片,引擎需要使粒子的一部分透明。粒子位图上用黑色表示粒子的透明部分。为了使粒子上的黑色透明,应在显示粒子之前添加以下代码。
glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE);
设置粒子的限制
当粒子离开视图窗口时,可以通过设置粒子的限制来重新初始化它们。函数 setLimit(fLimitL, fLimitR, fLimitT, fLimitB)
设置这样的边界。它可以在引擎生命周期的任何时候调用。禁用边界可以很容易地完成。
setLimit(0);
随附的纹理引擎,粒子引擎的内部工作需要它,也是我创建的,可以随粒子引擎自由地分发到您选择使用的任何项目中。纹理引擎与此示例一起工作,但在各种其他情况下可能无法工作。请确保包含 *texture.cpp* 和 *texture.h*,否则编译时会发生错误。
欢迎提出任何问题或意见,如果您在此基础上创建了自己的任何引擎,我很乐意看到。