跳转至

Fluid Ninja

Fluid Ninja 是一个令人惊叹的交互流体模拟插件,使用它可以以极低的性能损耗制作出令人叹为观止的效果:

image-20231114145533712

image-20231114145942912

作者Youtube上很多视频教程:

获取

对于学生用户,可以到 Fluid Ninja 的Discord社区中下载学生免费版:

image-20231114152013980

对于商业用户,请在虚幻商城中购买FluidNinja插件:

示例

Content/FluidNinjaLive/Tutorial/Levels/中有大量的示例关卡,这些关卡中都有详细的描述文本:

image-20231114161611114

最好的学习方式就是依次对这些关卡进行复刻,理解它的参数配置:

image-20231117162611951

关键蓝图

NinjaLiveComponent

NinjaLiveComponent是FluidNinja的核心,使用它必须搭载一个静态网格体(一般是面片,称它为 跟踪网格(Trace Mesh) ),流体模拟的最终结果将作为跟踪网格的材质进行输出:

image-20231114162146791

上图中的红色面片也就是跟踪网格

NinjaLive

NinjaLive是Fluid Ninja提供的一个默认Actor,它对 NinjaLiveComponent 的参数进行了一层包裹,包含了一个能满足绝大多数情况的使用需求的跟踪面片,简化了NinjaLiveComponent的设置,并添加了一些额外的功能,比如:

  • 通过ActivationVolume 对 NinjaFluid 进行剔除休眠,进入到ActivationVolume才会激活NinjaLiveComponent
  • 通过InteractionVolume更细粒度地设置交互区域。

image-20231114164608493

NinjaLive_Utilities

NinjaLive_Utilities(蓝图Actor)提供了一些便捷的调试功能,比如:

  • 自动控制距离该蓝图最近的玩家
  • 显示鼠标
  • 调整抗锯齿,景深,运动模糊的质量
  • 解除编辑器120FPS的限制
  • ...

可以将该蓝图拖入场景中,并进行配置:

image-20231114165051217

NinjaLive_PresetManager

NinjaLive_PresetManager(蓝图Actor)用于调整NinjaLive的参数预设。

image-20231114165515082

将它拖入场景,启动PIE,可以看到如下面板:

image-20231114165552571

NinjaLive_MemoryPoolManager

NinjaLive_MemoryPoolManager(蓝图Actor)用于配置FluidNinja的内存策略。

image-20231114165855058

模拟过程

在FluidNinja的资产目录下,有一个名为 Help 蓝图:

image-20231114160604396

它里面详细描述了 Fluid Ninja 模拟的流程图:

image-20231114161417804

NinjaFluid的核心在于:

  • 构建 Density(密度) 贴图和 Velocity(速度) 贴图
  • 叠加 噪声(Noise) 来增加流体的随机度
  • 调整 画刷(Brush) 来控制流体的形体
  • 结合 输出材质(Output Mateial)
  • 将最终结果输出到 跟踪网格(Trace Mesh) 的材质表面
  • 得到我们想要的结果:

12332312

  • Density 为单通道纹理,值域为[0,1],用于表示当前位置流体的密度。
  • Velocity 为双通道纹理,值域为[0,1],用于表示当前位置流体的矢量速度,由于被标准化为[0,1],速度0实际上对应的RG值为(0.5,0.5),上图中:
  • Velocity纹理的R通道对应水平速度,当值<0.5时流体向左,>0.5时流体向右
  • Velocity纹理的R通道对应竖直速度,当值<0.5时流体向上,>0.5时流体向下
  • FluidNinja允许输入三通道材质,其中RG通道代表Velocity,B通道代表Density

使用流程

制作过程中,我们本质上是对 NinjaLiveComponent 进行操作,它的 配置项分类(Categories) 有:

image-20231114195314683

  • Live Activation :只有一个Disable Component选项,可以通过蓝图去动态设置来进行剔除。
  • Live Interaction :交互相关的所有配置,比如筛选交互目标,跟踪网格的朝向、锁定,世界坐标偏移等。
  • Live Brush Setting :画刷的参数配置。
  • Live Generic :通用配置,主要是调整效果的预设、输入和输出。
  • Live Performance :性能配置,可配置效果的迭代次数,FPS范围限制,LOD等。
  • Live Compatibility :兼容性配置,可配置碰撞通道,覆盖输入等。
  • Live Debug :调试配置,提供了一些勾选项用于打印提示信息。
  • Live Raymarching :配置Raymarching。
  • Live Memory Management :配置内存管理。

构建输入

这里的输入主要指的是 密度(Density)速度(Velocity) ,相关的输入配置参数主要位于 NiagaraComponentLive Generic分类下,Fluid Ninja的输入来源可以是以下几种:

  • 静态纹理
  • 动态材质
  • 场景摄像机捕获
  • 渲染目标(RenderTarget)
  • 流媒体视频
  • 鼠标输入
  • 场景交互:静态网格体、动态网格体、骨骼网格体、可破坏物...

以上输入并不是独立的,它们可以共存,FluidNinja会将多个输入混合到一起,详见Help.uasset中的流程图。

在地图Content/FluidNinjaLive/Tutorial/Levels/NinjaLive_Level03_SimulationInputs_LIVE17.umap中,有完整的NinjaFluid输入示例,下面对这些输入的关键步骤进行记录:

静态纹理(Texture)

静态纹理的输入设置位于NinjaPreset数据表中:

image-20231114201238339

通常情况下,我们不会直接修改数据表的内容,而是在 测试关卡 中,借助 NinjaLive_PresetManager 提供的编辑器面板来导出预设表格:

image-20231114202724330

动态材质(Mateiral)

材质的输入配置位于 NinjaComponentLive Generic 分类下:

image-20231114202905246

  • 可以在 Input Materials 参数中添加可用的输入材质。可以多添加,以便可以在 NinjaLive_PresetManager 中能够切换预览。
  • 调节 Input Material Selected 索引选择当前使用的输入材质。
  • 勾选 RGB-Input Material 会让材质的RG通道作为Velocity纹理,B通道作为Density纹理,否则 默认只会使用材质的R通道作为Density纹理
  • 勾选 Input Material Clamp ,将会裁剪UV坐标位于[0,1]之外的图像。

对于Ninja Fluid的输入材质,需要选择材质域后期处理,并关闭投影光线检测阴影

image-20231115095919654

场景摄像机捕获(Scene Capture 2D)

FluidNinja可以使用摄像机来捕获场景,并将相机画面内的图像作为流体模拟的输入,具体的配置位于 NinjaComponentLive Generic 分类下:

image-20231115100308055

  • 可以在 Input Scene Capture Camera 选择当前场景已存在的Actor

示例:

  • 创建一个 Ninja LiveCube场景捕获2D(Scene Capture 2D) ,并将相机对准要捕获的Cube

image-20231115101605904

  • Ninja LiveNinja Component 中,配置场景捕获2D,并选择较为直观的材质输出:

image-20231115101956749

image-20231115102115854

  • 执行PIE,能看到如下效果:

    image-20231115102315733

  • 可以在场景捕获2D去调整捕获的配置(相机的参数,对象的筛选...),借助 NinjaLive_PresetManager 来调整它的参数效果:

    image-20231115103426806

渲染目标(RenderTarget)

材质的输入配置位于 NinjaComponentLive Generic 分类下:

image-20231115103750131

  • 勾选 Use Render Target as Input ,将会使用下方的 Input Render Target 作为流体模拟的输入
  • Input Render Target 用于指定读取的 Render Target

在Fluid Ninja中,该方案可以用于制作 形态可控的3D流体

Level3中有如下示例:

123123176812

  • 左侧是一个Niagara粒子系统,中间是投影的RT,右侧是利用RT+输出材质最终展现出的效果

示例:

  • 在内容浏览器新建【Niagara粒子系统】,选择【从现有系统拷贝】

image-20231115104955903

  • 取消勾选仅库,在标准分类中找到 NS_ParticleCaptureBasic

image-20231115105156054

  • 创建完成之后打开粒子系统,可以发现它包含两个默认发射器:

  • NE_ParticleCaptureBasic :用于将Empty发射器的粒子,通过网格坐标映射到RenderTarget上,可在AttributeReader中选择捕获哪个发射器。

  • Empty :用于模拟的粒子发射器

image-20231115105833878

  • 下面给了它一个发射速度(60),并增加了一个四散的随机初速度,可以看到如下效果:

image-20231115110654951

  • NE_ParticleCaptureBasic 会利用捕获的粒子数据,根据所有粒子的坐标 “投影” 到一张RenderTarget上,我们可以在用户参数上设置这个投影过程的策略:

image-20231115111735046

  • 用户参数中,默认使用RT_PrevivewParticleCapture作为RT输出,它可能被其他粒子系统共用,直接用它会与其他逻辑(教程关卡)冲突,所以我们需要自己创建一张RT:

image-20231115112113233

  • 并在NiagaraSystem的默认参数中指定它,尝试调整用户参数来理解RT的映射规则:

image-20231115112418360

  • 将配置好的NiagaraSystem拖拽放入场景中,并场景中浮空放置一个 NinjaLiveActor ,在 NinjaLive的细节面板中设置TraceMeshSize为(5,5,1),在NinjaLiveComponent的细节并开启追踪网格面向相机(Camera Facing Trace Mesh),开启RT输入,并指定刚刚创建的RT,选择输出材质为 MI_DensityBuffer_Red

image-20231115111345866

image-20231115112955341

  • 启动PIE,我们能看到如下效果:

image-20231115113119585

  • 实际上,我们并不需要对NiagaraSystem进行渲染,我们只需要它的模拟数据, NS_ParticleCaptureBasic 默认开启只是为了方便调试,所以我们可以关闭粒子发射器的渲染器:

image-20231115113520770

  • 此外,由于RT的渲染也是依赖相机位置,所以为了获得更准确的平面图像,需要将 NiagaraSystemNinjaLive 的位置重叠,选择一个合适的输出材质效果,就能看到:

123176812

视频输入

使用视频文件作为NinjaFluid的输入,需要指定以下三个参数:

image-20231115181025276

  • Input Media Player :视频播放器
  • Media Texture :视频绘制所使用的纹理
  • Input Media Source :视频播放源

关于UE如何播放视频,可参阅文章 https://zhuanlan.zhihu.com/p/135963353

示例:

  • 添加一个NinjaLiveActor,指定视频作为Density输入,再设置一个向上的Velocity贴图T_Crumple,结合输出材质MI_Candle1,能得到这样的效果:

123812

用户输入

NinjaLiveActor默认开启了鼠标输入,它的效果如下:

1236572

可以在此处进行关闭:

image-20231115182237273

碰撞交互

Fluid Ninja可以通过物理碰撞来作为输入,来完成一些可交互的流体效果,一个简单的示例如下:

  • 添加一个NinjaLiveActor

  • 设置Trace Mesh SizeInteraction Volume Size(5,5,1)

  • 设置NinjaLiveComponent\Live Bursh Settings,否则会因为碰撞画笔太小导致看不到结果

    • 勾选Brush Scaled By Interacting Obj Size
    • 设置Primitive Obj Brush Scale 为 20
  • 添加一个小白人,能看到如下效果:

image-20231117163147270

该效果是通过UE的物理碰撞机制实现的,其完整的参数均位于 NinjaLiveComponent\Live Interaction 中:

image-20231117162047588

  • Continuous Interaction with Owner Actor :与持有该组件的Actor持续交互
  • Continuous Interaction incluisve Obj Type :过滤交互的碰撞对象类型
  • Continuous Interaction Component Name :过滤交互的组件名
  • Continuous Interaction Bone Names Exact :过滤交互的骨骼名
  • Single Target Mode :单一目标模式,开启之后FluidNinja认为碰撞产生的图像都是由一个目标生成的,这可以使碰撞路径变得平滑,没有断层(插值)
  • Single Target Type
  • Single Target Mode Skeletal Mesh Index
  • Single Target Move Set Sim Speed
  • Speed Influence Factor :速度影响因子
  • Clamp Max Velocity :截断最大速度
  • Camera Facing Tace Mesh :TraceMesh始终面向相机
  • Camera Facing Lock Y-Axis :锁定摄像机的Y轴
  • Use Legacy Camera Facing
  • Trance Mesh Translucent Sort Prio
  • Use Custom Trace Source :使用自定义追踪资源,开启之后相当于使用下面的位置作为摄像机位置来进行碰撞检测
  • Custom Trace Source Position :自动追踪资源的位置
  • Trace Mesh Moving in World Space :TraceMesh位于世界空间
  • Movement Not Quantized to Steps OnAxis
  • Movements is Locked on This axis :锁定某个轴的移动
  • Force Trace Mesh to Custom Vertical Pos
  • Force Trace Mesh Vertical Position :锁定TraceMesh的位置
  • Enable Paint Buffer Offset in World Spacing :开启绘制缓存区的世界空间机制
  • Simple Painter Mode :单纯的绘制模式,没有碰撞输入

对于 NinjaLiveActor ,对上述参数做了进一步封装,有如下参数可以调整:

image-20231117162207129

  • Overlap Based Interaction :开启碰撞交互

  • Interaction Volume Size :交互体积大小

  • 以下参数用于 筛选 哪些物体可以于交互体积发生“作用”。

  • Track Actor Primitive Components With Tag :追踪带有该标签的组件

  • Track Actor Skeletal Mesh Components With Tag :追踪带有该标签的骨骼网格体组件

  • Overlap Filter Inclusive Obj Tab :需要包含的对象碰撞类型

  • Overlap Filter Inclusive Bone Name Exact :需要包含的骨骼名称,如果为空,则会处理全部骨骼

  • Overlap Filter Inclusive Bone Name Partial :需要包含的骨骼名称字段,例如填入Foot,则所有名称包含Foot的骨骼都将被包含

  • Exclude Specific Actors from Overlap :需要排除的Actor类型

  • Auto Exclude Large Overlapping Objects :自动排除大型的覆盖对象

调节画刷

画刷用于控制FluidNinja输入贴图作用区域的缩放因子,其参数配置如下:

image-20231117161748514

一些关键参数:

  • Brush Scaled Inversely by Trace Mesh Size :画刷会随跟踪网格的大小进行缩放
  • Brush Scaled by Interacting Obj Size :画刷会随交互对象的大小进行缩放
  • Use Obj Bounds Instead of Size :使用交互对象的边界作为画刷尺寸
  • Global Brush Scale :全局画刷缩放系数

如果碰撞交互的效果几乎不可见,很有可能是画刷太小导致的

预设配置

预设表包含了流体模拟相关的参数:

image-20231117165456545

NinjaLive_PresetManager 阅读参数的提示信息,通过调整来理解它跟效果的关联关系,配完参数后另存为新表。

输出材质

FluidNinjaLive内容目录下定义了其使用的核心材质:

image-20231117161325291

我们可以直接使用Instance_*文件夹下的材质实例

image-20231117161142891

亦或是新建材质实例,设置父项为FluidNinja提供的基础材质(材质文件名称以M_NinjaOutput_开头):

image-20231117161054031

  • M_NinjaOutput_Basic :基础材质
  • M_NinjaOutput_Advanced :高级材质
  • M_NinjaOutput_TranslucentReflective :透明反射材质
  • M_NinjaOutput_WorldSpaceGeneric :世界空间材质
  • ...

以M_NinjaOutput_Basic为例,它提供了很多可供调整的参数预设:

image-20231117161508777

在FluidNinja的Tutorial和Usercase关卡中,有很多可供参考的材质示例,具体的参数意义,可通过复刻进行学习。

总结

FluidNinja的思路很巧妙,使用起来有些繁琐,但关键的步骤很清晰:

  • 构造模拟过程所需的Density(密度)贴图和Velocity(速度)贴图,使用恰当的画刷和预设并结合对应的材质来呈现出最终想要的效果。

优缺点

  • FluidNinja通过二维面片来伪装出三维视觉的效果,它的性能损耗远低于常规的粒子流体模拟,但想要伪装出足够真实的三维效果,就要有足够真实的二维输入,否则的话,在某些视角上可以轻易识破FluidNinja的追踪网格面片。
  • FluidNinja提供了很多的方式构建流体的输入:贴图,材质,RT,Niagara,相机...,可以满足绝大部分的开发需求,但细节很多,使用起来并不容易,想要随心所欲的制作出想要的效果还需要深入的学习。
  • FluidNinja并不能完全代替粒子,它更适用于 可交互的 流体模拟,比如烟雾,火焰,水体...

评论