最近看官方视频,看到肖月大佬提到用Ribbon的方法制作植物生长。一直也对这比较感兴趣,所以花时间试着做了一下。还有很多地方需要完善,希望大家多多提提意见。
【资料图】
目前首选的考虑当然是Houdini,这就需要Houdini To Niagara来完成信息传导。相关的插件地址:
https://github.com/sideeffects/HoudiniNiagara
https://github.com/sideeffects/SideFXLabs
一个是UE引擎的,一个Houdini的。网上有很多教程讲了如何安装插件,我就不赘述了。插件默认可以传递很多属性(点是关键),包括位置,ID,旋转,大小,Type等。
首先当然是在Houdini中制作我们所需的植物。我只需要植物的最终形态,只需要当前帧的数据,植物的生长效果在引擎内完成。
在最开始,对于Ribbon部分。我设想传递点的位置,大小来确定Ribbon。
首先Circle,Scatter节点在圆内创建几个点 ,作为最开始的根部。而后用AttributeRandomize分别对N,pscale进行随机化(确定曲线的朝向以及长度)。对于主干用Line和Resample做出一根很多点的线。
通过Length设置点的数量,更改TreatPolygon使线更加平滑。并且勾选curveu属性,此属性根据曲线长度进行0~1的赋值。
AttributeVOP节点,通过curveu进行曲线采样,然后采样的值与Noise相乘来改变点的位置,将Noise的Frequency、Roughness、Amplitude节点用鼠标中键提升为参数,这样就可以对曲线进行弯曲操作了。曲线的左端保持为0,让连接处的点不发生偏转。最后用CopyToPoint节点将散布的点的属性传递给曲线。
至于AttributeWrangle定义的属性有什么用,这在后面将会提到,现在我们专注构建基础形状。出与美术的考虑使用Twist对曲线进行扭曲。
这样主干部分就完成了。
随后用OrientAlongCurve使法线沿着曲线方向对齐,再对N和pcale进行随机化处理,Scatter产生点以进行下一层级的生成。其他的就和上面的一样,Copy&Paste改下参数名称就行了。
接下来,我想要在枝条末端生长花。为此,GroupRange节点就是选择枝条的最后一个点,并作为END的组。这个不能放在CopyToPoint的节点后面,不然你只会得到一朵花。别问我怎么知道,都是泪。
那么一个关键的问题来了,怎么确定花的朝向了。这个就要用到四元数了,我们首先OrientAlongCurve让法线沿着曲线的方向。而后用AttributeWrangle写上我们的朝向。我们只关注前三行关于方向的。1.定义旋转矩阵m,该矩阵的作用是让花的模型的Y轴(0,1,0)(参考UE方向)对齐到@N法线方向。2.对模型进行旋转,旋转的轴向是@N,旋转的角度用参数ang来控制然后与ptnum相乘让每朵花的旋转值不同。3.最后把矩阵m参与矩阵运算赋予orient。
后面的就是Copy&Paste过程了,然后疯狂的调整参数来达到你想要的美术效果。最后的花我没有进行方向的调整,因为这朵花相对较小,在UE里我就用GPU粒子朝向摄像机来解决,已获得那微小的性能提升。
好,做完了!!!准备导出到UE.
最后我们把需要导出的点用Merge合在一起,用我们安装好的插件的Niagara节点,选择渲染当前帧。导出!
什么,你问我,多了几个属性和节点。那是后来的事了,因为我把这个导进UE里一看。
CrazyWork!!!
好了,不皮了。导进UE里,我们还面对几个问题。
我们该怎么区分每个层级,区分不同的花以及枝干。
UE里的Ribbon怎么一条线连到底呢,怎么判断Ribbon那是起点,那是终点。
怎么做植物生长的效果。
通过查阅官方示例以及其他大佬的视频文章之后,慢慢的解决了。
1. 在每次CopyToPoint节点之前,创建一个新的属性Type用来区分他们。
需要注意的是花我们记得把之前的END组给上。
2. UE官方提到Particle.RibbonID和RibbonLinkOrder决定Ribbon的链接方式,但我仍然不明白究竟如何链接的。于是自己创建一个测试的粒子系统,把上面提到的两个变量赋予随机值。结果如下:
从第一张图不难发现,RibbonID一样时,Ribbon才会连起来,从第二张第三张图我们发现Ribbon的链接顺序取决于LinkOrder的大小。
RibbonID我们可以在CopyToPoint节点之前用ptnum赋值。LinkOrder则用之前提到过的curveu、1、2来赋值。忽视掉那些被注释掉的黄色代码,本来打算用pscale来做Ribbon的Width的,但由于树枝间的接缝问题以及LinkOrder的出现我没有用这种方法。
3. 植物的生长是通过对ID的重新排序得到的,我们得出每个点到原点的距离,并以此来进行重新排序。
然后在UE里根据这个值做出生长的效果。
以上就是整个Houdini的工作了。接下来导进UE里。
在安装好HoudiniNiagara插件后,我们找到官方自带的发射器,以此为模版。
我们只需要起始状态就行了,不需要变化,可以把Update里的Sample删除。然后把我们自己得到的点的数据到进来。
检查一下点的属性是否是我们想要的。
枝条用Ribbon发射器,UV就用默认的。Width等下我们自己设定。
Niagara里我们只是定义了枝条的发光颜色,枝条和花的材质都用的Masked的材质模式,用半透明模式消耗大,可能还会出现半透明排序问题。枝条的基础颜色,粗糙度,法线都是在材质里完成的。考虑到文章篇幅原因,材质我就不展示了,都是一些基本的UV流动,扭曲,溶解等。
Ribbon形状设定为Tube。
随后我们初始化LifeTime,Position,RibbonWidth。
发射器默认自带了一些Houdini的属性,将Houdini.Position赋予到Particle.Position里。
至于我们自定义的属性,需要像上面那样手动写进去。
接下来还剩一个问题,RibbonWidth的属性如何定义了,我们可以用Type确定那一层级,用Linkorder进行曲线采样来确定Width。
首先进行判断那一层级,根据结果来设定Width。
将我们所写的赋值给RibbonWidth,HType用Houdini.Type复制,TypeNum则是确定我们需要对那一层级进行编辑,0为主干,1为Branch_1~~~以此类推。至于Width我们用A*B赋值。
A用LinkOrder进行曲线采样,确定枝干的形状。ScaleCurve设置枝干的大小。
B是一个Noise,与A相乘赋予每个枝条更加随机的变化。
Noise是采样CurlNoise实现的,因为这样的噪音的随机是一种伪随机。
第一个是我们想要的Random,第二种是赋予随机值。
这个是参考官方的CurlNoiseForce写的。通过粒子的位置,Age实现对Noise的采样,采样出来的值归一化,用Lerp节点重新映射,这样我们便于方便的调整。
我想对Width做0.9~1.1的随机变化。
其他的就是Copy&Paste过程了,我们只需要改变TypeNum确定改变那根枝条就行了。后面的枝条在曲线开始初给了一个相对较小的值,这样枝条的连接处更加好看。
至于生长我们需要新定义一个Particle属性,TimeShiftByID。这个虽然看起来比上面简单,但其实花了我比较长时间想出来的。Age属性是一个每秒增加1的动态属性。再引入一个新的浮点数,定义生长的速度。最后和ID进行运算。(Age-ID*GrowSpeed)/GrowSpeed。(GrowSpeed不能为0),假如GrowSpeed为1,那么ID为0的粒子在0~1S内的TimeShiftByID为0~1;ID为1的粒子在1~2S内的TimeShiftByID为0~1;ID为2的粒子在2~3S内的TimeShiftByID为0~1。假如GrowSpeed为2,那么ID为0的粒子在0~2S内的TimeShiftByID为0~1;ID为1的粒子在2~4S内的TimeShiftByID为0~1;ID为2的粒子在4~6S内的TimeShiftByID为0~1以此类推。这样将TimeShiftByID进行采样就能实现很多效果。
最后我们给到GrowSpeed一个很小的值来确定生长时间,其实这里还可以根据ID调整GrowSpeed来让开始时生长的更快,结束时生长的慢一些。但是由于太快了,难以察觉我就没加。而后我们根据TimeShiftByID给EmissiveColor进行设值,这样就实现了植物生长的效果以及发光的效果。
我也通过DynamicMaterialParameters给材质中的溶解(Dissolve)参数赋值,其实这个和Alpha的功能有些重合,不过影响不大,在实现花的生长要靠溶解来更好的实现。
终于到最后的阶段了,首先花的模型是通过Blender做的。
首先建一个平面,保证模型的UV是正方形方便贴图制作。然后对平面用表面细分和阵列修改器进行编辑和复制。期间手动用衰减对点进行编辑,使其更加随机化,最后平滑着色就OK了。
花的贴图在SD里面做的,红色通道储存着Albedo的信息,绿色通道储存着EmissiveColor的信息,蓝色通道储存着溶解贴图的信息。
通过IF判断Type来确定花的生长位置和数量。
初始化花的基础信息,花的大小设置一个随机值就行了。
注意这里的横坐标的值很大,不是1,我给到的是3500,否则太快看不到发光生长。通过溶解来实现花的生长。到此为止,就没有什么新的东西了,后面的第二种花和前面的制作思路差不多。
其实做这个初衷是想用GPU粒子实现的,但我把Ribbon切换到GPU时发生错误,我看了下NiagaraDebugger发现,RibbonID和RibbonLinkOrder现在好像不能传递给GPU Ribbon,那样的话可以实现更大数量的植物模拟了。由于东西比较多,难免会出现错误,欢迎大家指出。
Copyright 2015-2022 南极创新网版权所有 备案号:粤ICP备2022077823号-13 联系邮箱: 317 493 128@qq.com