首页 百科知识 MAYA粒子特效教程:表达式创造逼真龙卷风

MAYA粒子特效教程:表达式创造逼真龙卷风

时间:2024-10-05 百科知识 版权反馈
【摘要】:第六节用表达式“写”出一个龙卷风来为了加强对表达式和粒子通用属性的理解,在这一节我们使用表达式“写出”一个龙卷风来。首先,要做龙卷风就要知道龙卷风是什么样子的,并且用语言表达出来,然后再把语言转换成表达式。接下来确定对什么属性进行控制:Position,我们当然是位置,我们控制每一个粒子的位置来制造一个龙卷风的形态。在改变半径前,我们先对表达式作一个修改,因为它太长了。

MAYA粒子特效教程:表达式创造逼真龙卷风

第六节 用表达式“写”出一个龙卷风

为了加强对表达式和粒子通用属性的理解,在这一节我们使用表达式“写出”一个龙卷风来。

首先,要做龙卷风就要知道龙卷风是什么样子的,并且用语言表达出来,然后再把语言转换成表达式。我们说:龙卷风是从地面向上升起的圆形粒子群,并且上大下小,下面风口快速移动,上部被带动移动而产生扭曲。

接下来确定对什么属性进行控制:Position,我们当然是位置,我们控制每一个粒子的位置来制造一个龙卷风的形态。

最后就是动手制作了:新建一个场景,创建一个粒子发射器(使用默认属性)。

默认情况下,粒子是四散开来的,粒子的位置受到粒子发射器的发射速度影响而变化:

要精确控制粒子的位置,就需要使用表达式接管位置的属性控制权:为粒子的Position属性制作RunTimeExpression。

回到第一步,“龙卷风是从地面向上升起的圆形粒子群”那么,首先要解决的就是让粒子绕着圈的上升;再分解一下就是:先在原地转圈再上升。那么怎么让粒子在原地转圈呢?还记得前面讲到的Sin(),Cos()么?两个在时间轴上互补的函数,是制作圆形运动的首选:

注意:使用RunTimeExpression

在这里还是解释一下这个表达式的含义:

particleShape1.position=<<sin(time),0,cos(time)>>;

是一个简单的赋值,将一个矢量值<sin(time),0,cos(time)>赋值给每一个粒子的位置信息,在X轴和Y轴是分别以sin(time)和cos(time)为位置,在Y轴上是0。时间不断增加所以粒子在平面上逆时针旋转。

结果和我们想象的不太一样,因为粒子挤作一堆了,原因是我们给每个粒子的位置信息值都是一样的:sin(time)和cos(time)为位置,所以要想粒子围成一个圈,需要为每个粒子赋于不同的值(基于现有圆形运动);也就是需要一个每个粒子都有的,但每个粒子都不一样的值来和time进行运算,这样每个粒子的位置就不一样了,而且还是一个圆形运动:

于是我们想到:particleId,不是么?每个粒子都有一个Id,而且每个都不一样,更好的是这个值是不断增加的,于是矢量值可以写成:

效果:

粒子变成了一个圆圈,并且在逆时针旋转,可是半径只有1,太小了;那么增加这个半径怎么写呢?

在改变半径前,我们先对表达式作一个修改,因为它太长了。我们把这个表达式改成这样:

是不是结构很清晰?第一行声明一个变量$speed,并将重复使用的time+ particleShape1. particleId赋值给它,那么在第二行里面,就不用再重复使用了,只需要使用$speed就可以了,这种方法有很多好处:其中一个是能够使结构清晰,并且在需要修改的时候非常方便,因为你只需要修改一次就可以了,而不用重复修改了。

由于粒子的位置在X轴和Y轴上都是−1到+1之间,所以要增大半径,就只需要乘于一个数就可以了,所以表达式可以改成:

很明显粒子圆圈的半径增加了,在这里使用了*半径而不是+半径,是因为:sin函数的值有正有负,使用‘+’数值不论正负,只会增加不会减少,结果变成了位移了;而使用‘*’则数值负的更小,正的更大,所以结果就是半径变大了。

接下来,增加点细节,因为这个太有规律了,龙卷风应该是有点随机感的扩散,而不会是一个圆圈的线,所以只要在半径$r上面动一下脑筋,给个随机就可以了不是么?可是问题也来了,如果直接加上个rand()函数,那么每运行一帧就$r会变化一次,结果粒子就会不停的抖动(读者可以试验一下,体会一下)。所以我们需要一个每个粒子都有,很接近的,但有都不相同的这样的一个数值,来和$r相加,来产生圆圈的随机感。

所以我们需要一个PerParticle的值,这个值还应该是Rand(x)的。看来现成的是没有了,所以我们就自己创造吧:

单击General按钮,为粒子创建一个PerParticle的属性,ok以后就会出现在PerParticleAttribute属性里面:

接下来就是为这个Rand属性真正的赋上一个Rand(2)的值了,使用CreateExpression,于是我们就有了一个PerParticle的值,这个值还是Rand(2)的:

在属性后面鼠标右键单击,在弹出菜单选择CreateExpression

创建如下表达式:(www.xing528.com)

于是,我们的粒子位置信息的表达式就成为:

在半径的后面加上每个粒子的不同的随机值,那么这个圆线就会变成有宽度的面了:

在平面上,基本的形态已经形成了,接下来就是让这个平面旋转的粒子群,向上升起来:这比较简单,只要在position的Y轴数值增加就可以了。所以这个表达式被改写成:

在这里将Y轴上的增加,使用了一个小技巧:先将粒子的位置信息position赋值给一个矢量的变量$pos然后使用$pos.y将Y轴的分量拿出来进行计算,使用$pos.y+0.3来使得$pos.y在每一帧都增加0.3个单位,并且将这个值赋给变量$up,然后将这个$up变量赋值给position的Y轴分量。于是粒子群旋转上升了(如下图):

当然了,不要忘了把粒子的生命周期该修改一下,否则粒子不停的上升,没完没了:

好了,最简单的部分完成了,接下来要实现的是让这个旋转上升的粒子群变得上大下小,这才是龙卷风的样子,而且上大下小还要有漏斗的形态(至于扭曲那就放在下一步)。

要实现上大下小,当然还是控制粒子的position值来实现,也就是我们又要修改position的x和y分量的值了。现在是通过sin($speed)和cos($speed)产生旋转并且使用*$r来产生每个粒子随机的偏移量,然后随着时间的增加使用+0.3来使粒子上升。那么,要在上升的过程中产生漏斗形状那就需要一个数值,这个数值必须要随着粒子的生命周期的改变而改变(粒子产生时候最小,粒子死亡时候最大,而且每个粒子都有同样的这个值)。然后将这个值和半径相乘,那么不就产生了粒子产生到时候(最下面)半径小、粒子死亡的时候(最上面)大的形状了么?

那么这个值有没有?很可惜没有,没有怎么办?那就自己造一个PerParticle的值,就好像particleShape1.Rand一样。不同的是,我们要为这个值赋一个动态变化的值(粒子产生时候最小,粒子死亡时候最大的值),怎样赋值?还记得ramp么?是不是正好满足我们的要求呢?我们先为粒子增加一个名字叫life_position的PerParticle属性:

为粒子增加PerParticle粒子属性life_position:

为该属性添加Ramp值:

该属性值随着粒子的年龄增加,从下至上返回ramp里面的RGB的值

编辑ramp,我们希望粒子出生的时候返回最小的值,在粒子死亡的时候返回最大的值,这样我们将这个值与粒子的旋转半径相乘,得出的结果就是:粒子在产生的时候粒子旋转半径最小,上升的过程中逐渐变大,并且可以通过调整Ramp的颜色控制,最后消失的时候达到最大半径。

当然了,在此之前,必须将颜色代表的最大值和最小值定义下来。

在life_position属性后面单击鼠标右键,选择编辑数值映射(EditArrayMapper)

进入编辑最小值和最大值的面板:

对改表达式进行修改:

在这里命名了一个$life_position的浮点数变量,并且将particleShape1.life_position赋值给他。然后在position表达式里面用它和半径$r相乘就产生了一个随着粒子年龄的增加而变幻的粒子旋转半径(如右图)。

你可以调整一下ramp的颜色结构,会有不同的效果,在这里强调一个理论知识:颜色值是矢量值<<R,G,B>>将它赋值给了浮点数结果将会是:img126

最后是让龙卷风扭曲起来,也就是让粒子在旋转的时候再加上位移(基于每个粒子的位移),于是我们的最终表达式就是:

这里将偏移量定义为一个浮点数$move它的值是一个随机数noise()和rand()都是返回一个随机数的函数,然后在粒子运动的X轴和Y轴上加上这个偏移量,就产生了扭曲。

为了产生扭曲我们使用的是基于每个粒子的偏移量,也就是利用了particleId这个每个粒子都不同而且又是唯一的属性值,来产生每个粒子都不同的位移量,其中又乘以了0.01等等,读者可以调整这些数值看看有什么变化。

最终我们得道的龙卷风如图所示。

这个实例,只是单纯的为粒子的Position进行赋值操作,就可以产生如此效果,所以使用表达式能够随心所欲的控制粒子的运动。

结合粒子的其他属性和粒子的不同渲染类型,我们能够制作出任何一种你所能想象到的特效。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈