1. 从“一滩水”开始:为什么流体模拟是CG创作的质变点
几年前,我接手一个需要制作咖啡倒入杯中、液面晃动并泛起泡沫的镜头。当时的第一反应是找现成的视频素材或者用贴图动画“硬扛”,结果不是角度不对就是质感塑料,完全无法融入三维场景。就在几乎要放弃这个镜头时,我决定硬着头皮研究一下Blender的流体模拟。从第一次点击“域(Domain)”物体,到看着一堆粒子在框里乱窜,再到最终渲染出那杯带着真实涡流和表面张力的咖啡,整个过程虽然踩坑无数,但那种“创造物理”的成就感是无与伦比的。流体模拟,就是把CG创作从“雕刻静态形状”提升到“模拟动态规律”的质变点。它不再是美术层面的工作,而是介乎于艺术与科学之间的实验。
对于很多刚接触Blender的创作者来说,“模拟”这个词听起来就有点门槛,让人联想到复杂的物理公式和漫长的计算等待。但我想说,Blender的流体系统(特别是自2.8版本以来集成的MantaFlow引擎)已经足够友好,它把复杂的Navier-Stokes方程封装成了几个直观的参数面板。你不需要是物理学家,也能通过调节“粘度”、“表面张力”来让蜂蜜流淌得更粘稠,或者让水珠更圆润。本篇内容,就是带你绕开我当年走过的弯路,从零开始,理解Blender流体模拟的核心逻辑、掌握关键参数的“手感”,并最终渲染出可信的流体效果。无论你是想制作倾泻的瀑布、杯中晃动的红酒,还是科幻场景中的能量流,这套基础都能成为你的起点。
2. 流体模拟的核心拼图:域、流与障碍物
在Blender里启动一次流体模拟,就像在桌子上规划一个物理实验。你需要明确三样东西:实验发生的空间(域)、被研究的物质(流),以及影响实验的物体(障碍物)。这是最核心的三个角色,理解它们的关系,就理解了整个模拟的骨架。
2.1 域(Domain):流体的舞台与边界
域,就是那个划定模拟范围的透明框子。你可以把它想象成一个装满无形“计算力”的鱼缸,流体所有的行为都只在这个鱼缸内部被解算。
创建一个域非常简单:在场景中新增一个立方体(Shift+A -> Mesh -> Cube),然后在物体属性面板中找到“物理属性”(Physics Properties)标签,点击“流体”(Fluid),并选择类型为“域”(Domain)。这时,立方体会变成一个半透明的框,它的尺寸直接决定了你的“鱼缸”有多大。
这里有几个至关重要的细节决定了模拟的成败:
分辨率:精度与耗时的博弈在域的流体设置里,“分辨率”是最关键的参数,没有之一。它决定了这个“鱼缸”被划分成多少个小格子来进行计算。分辨率64,意味着长、宽、高每个方向都被分成64格,总共是64x64x64=262,144个计算单元。分辨率128,则变成超过200万个单元。
注意:分辨率的提升对计算量的增加是指数级的。从64到128,格子数变为8倍,所需内存和计算时间可能增加10倍以上。我的经验是,对于学习和小样测试,分辨率64完全足够看清基本行为。对于最终渲染,通常需要100-150的分辨率才能获得平滑的表面,但这意味着你需要为一次数秒的模拟准备好喝杯咖啡甚至吃顿饭的等待时间。
时间尺度:控制流体的“性格”时间尺度(Time Scale)参数常常被忽略,但它能极大地改变流体的“性格”。默认值是1.0,代表模拟时间与现实时间1:1。如果你觉得流体下落得太慢,像在月球上,可以把值调到1.5或2.0,它会计算得更“快”。反之,调到0.5,流体会像在粘稠的介质中一样缓慢运动。这个参数非常适合快速调整流体的整体速度感,而不用去改动重力等全局物理参数。
边界类型:流体能逃出去吗?域的六个面都可以单独设置边界类型。默认是“域”(Domain),意味着流体碰到边界会被挡住。你也可以设置为“流出”(Outflow),这样流体碰到这个面就会消失,非常适合制作水龙头出水口的效果。或者设置为“流入”(Inflow),让流体从这个面持续生成。在制作瀑布时,我会将顶面设为“流入”,正面和侧面设为“域”,底面设为“流出”,这样水流就会源源不断地生成、落下并消失在底部。
2.2 流(Flow):流体的诞生与形态
流物体定义了流体的来源和初始属性。任何一个网格物体都可以被指定为“流”。同样在物理属性中,选择“流体”类型为“流”(Flow)。
流类型:你是泉眼还是冰块?这里有三个核心选项,对应三种完全不同的流体行为逻辑:
- 流入(Inflow):这是最常用的“源头”。被指定为流入的物体会持续不断地向外喷射流体粒子。你可以用它来做水龙头、喷泉、倒出的酒瓶口。关键参数是“流量”(Flow Rate),值越大,单位时间内喷出的流体越多。
- 流出(Outflow):与域的流出边界类似,但这是物体级别的。任何接触到这个物体的流体都会被“吸走”消失。可以把它想象成一个下水道口或排水孔。
- 液体(Liquid):这是将物体本身作为一块“已经存在”的流体。点击烘焙后,物体会被转化为流体粒子。这是制作“一滩水”、“一个水球”或者“融化的冰淇淋”的常用方法。它没有持续生成的能力,其形状就是流体的初始形状。
初始速度:给流体一个“推力”在流体的“初始速度”(Initial Velocity)选项里,你可以给新生成的流体一个初始的运动方向。例如,做一个侧向喷出的水柱,除了调整流入物体的喷口方向,还可以在这里设置一个朝向侧面的速度矢量(比如X: 5.0, Y: 0, Z: 0)。这个功能在制作爆炸、溅射等效果时非常有用。
2.3 障碍物(Obstacle):与流体互动的万物
障碍物是场景中与流体发生碰撞的物体。任何复杂的流体交互,本质都是流体与各种障碍物的碰撞。指定一个物体为障碍物后,流体在模拟时会“知道”它的存在并绕开或沿着它流动。
表面厚度:解决“渗漏”的利器这是新手最容易踩坑的地方。在障碍物的流体设置底部,有一个“表面厚度”(Surface Thickness)参数,默认是0.0。在低分辨率模拟下,流体粒子可能会因为计算精度不足,从障碍物网格的缝隙中“渗”过去。适当增加这个值(比如0.02m),相当于在障碍物表面包裹了一层无形的碰撞体,能有效防止渗漏,让流体更服帖地沿着表面流动。
影响因子:是海绵还是钢板?“影响因子”(Effect Factor)控制障碍物对流体影响的强度。默认1.0是完全的固体碰撞。如果你把它调到0.5,流体会更容易“推开”这个障碍物,或者表现出更滑的摩擦。调到0,则该物体对流体完全无效(虽然很少这么用)。这个参数可以用来模拟一些非刚体的、能被流体推动的物体,比如漂浮的软木塞。
3. 参数调校:从“像水”到“是蜂蜜”的艺术
当基础拼图搭建好后,决定流体最终视觉特性的,是一系列物理参数。Blender把这些参数藏得比较深,在域的“流体世界”(Fluid World)设置里。调整它们,就像在厨房调配不同质感的液体。
3.1 粘度(Viscosity):流体的“粘稠度”
粘度是流体内部摩擦力的度量。水的粘度很低(大约1 mPa·s),所以它流动顺畅。蜂蜜的粘度很高,所以它流动缓慢,甚至能拉丝。
在Blender中,粘度参数有两个模式:“真实值”(Real)和“自定义”(Custom)。对于初学者,我强烈建议使用“自定义”模式,因为它提供了更直观的滑块。“线性”(Linear)值从0(像空气)到1(像沥青)。制作水,可以设置在0.1到0.3之间。制作蜂蜜或糖浆,则需要0.8以上。我制作熔岩效果时,甚至会用到0.95,并配合极低的“表面张力”,让它看起来浓稠而柔软。
高粘度流体模拟时有个技巧:由于流动慢,你可以适当降低模拟的“结束帧”(End Frame),因为不需要太多帧数就能看到其缓慢移动的过程,这样可以节省大量烘焙时间。
3.2 表面张力(Surface Tension):让水珠“站”起来
表面张力是液体表面收缩的趋势,它使得小体积的液体(比如水滴)趋向于形成球形。这个参数对表现流体的“质感”至关重要。
Blender的表面张力值也是“自定义”模式更易用。值越高,流体越倾向于团聚成球状。做一颗从叶片上滴落的水珠,需要较高的表面张力(0.5以上)。而模拟一大片水域(如海洋),表面张力几乎可以忽略(0.05左右),因为在大尺度上,重力主导了形态。
一个常见的误区是,认为高表面张力会让所有流体都变成完美球体。实际上,它是在与流体的惯性(速度)和粘度竞争。一个高速喷射的水流,即使表面张力设得很高,也会因为惯性而被拉成柱状,只有在末端速度减慢时才会碎裂成球状水珠。这个动态过程正是模拟迷人的地方。
3.3 浮力与重力:流体的“重量感”
重力是默认存在的全局力,你可以在场景属性(Scene Properties)的“重力”(Gravity)中修改。标准的-9.8 m/s²是地球重力。如果你想做太空中的流体,可以设为0。
浮力(Buoyancy)参数在流体世界设置里,它控制着密度差异导致的上升或下沉力。对于大多数液体模拟(水、油),保持默认值1.0即可。但如果你在模拟烟雾(在空气中),这个值就非常关键。热空气上升,就是因为浮力为正。你可以通过给流体的“初始温度”(Initial Temperature)设置一个高值,并配合浮力,来模拟烟雾上升的效果。
这里有一个结合使用的例子:模拟水中倒油。你需要创建两种流体。水作为背景流体(一种复杂用法,通常用高粘度障碍物模拟),油作为流动流体。将油的密度(在“高级”设置中可以找到相关参数,通常通过粘度等间接影响)设置得比水低,并确保浮力为正,油就会漂浮在水面上。这需要更精细的网格和粒子设置,但原理正是基于浮力。
4. 网格化与渲染:从粒子到视觉盛宴
烘焙完成后,你看到视图里的可能只是一大堆点(粒子显示模式)。如何把这些点变成可以渲染的、光滑的液体表面?这就是网格化(Meshing)的工作。
4.1 网格化参数:在平滑与性能间取舍
在域的流体设置中,切换到“网格”(Mesh)面板。点击“烘焙网格”(Bake Mesh),Blender会根据你烘焙好的粒子数据,生成一个连续的液体表面网格。
粒子半径与细节尺寸网格化的核心逻辑是:围绕每一个流体粒子,生成一个“水滴”形状(默认为球体),然后将所有重叠的“水滴”融合成一个光滑的表面。因此,“粒子半径”(Particle Radius)决定了这个基础水滴有多大。它通常与你在烘焙时设置的粒子尺寸相关联。
更重要的参数是“细节尺寸”(Detail Size),它决定了网格生成的精度。这个值会除以域的“分辨率”来得到最终用于生成网格的体素大小。例如,分辨率128,细节尺寸1.0,则用于网格化的体素大小就是域尺寸的1/128。如果细节尺寸设为0.5,体素大小就变成域尺寸的1/256,网格会更精细,但计算更慢,文件更大。
提示:永远不要先烘焙高精度网格。我的工作流是:先用极低的网格细节(比如细节尺寸4.0)快速烘焙一次,在视图里检查流体的运动轨迹和基本形态是否正确。确认无误后,再逐步提高细节尺寸(2.0, 1.0, 0.5)进行局部帧的测试烘焙,观察细节提升程度与时间成本的增加是否值得。最后才针对需要渲染的帧范围,烘焙最终精度的网格。
平滑与压缩:优化网格质量“平滑”(Smoothing)参数可以柔化网格的锯齿,让表面看起来更自然,通常1-2的值就足够。“压缩”(Compression)则尝试简化网格,在视觉变化不大的情况下减少面数,对提升后续渲染速度有帮助。
4.2 材质与着色:赋予流体灵魂
一个完美的流体网格,如果没有好的材质,看起来依然像塑料。流体的材质核心在于折射、透射和凹凸。
基础设置:玻璃BSDF对于清澈的水,最直接的方法是使用“玻璃BSDF”着色器。将其连接到材质输出节点的“表面”。调整“粗糙度”(Roughness)为0, “IOR”(折射率)为1.33(水的折射率)。这样你就能得到基本的折射效果。
但真实的水不是完美的玻璃。它会有微妙的颜色变化(浅水偏绿,深水偏蓝),内部有杂质导致的浑浊感,以及表面因微小波纹产生的凹凸。
进阶:原理化体积与层权重
- 颜色与吸收:在玻璃BSDF前面,可以添加一个“原理化体积”(Principled Volume)节点,用“颜色”来控制光线在流体内部传播时的吸收。给一个淡淡的蓝绿色,并增加“密度”,可以模拟游泳池或深海的水体感。
- 表面凹凸:绝对光滑的水面看起来很假。我们需要添加细微的波纹。使用“噪波纹理”(Noise Texture)节点,缩放(Scale)调到很大(如500),连接到“凹凸”(Bump)节点,再将凹凸连接到玻璃BSDF的“法向”输入。这样就能产生非常细微的、动态的水面起伏,对高光反射的影响巨大。
- 泡沫与飞沫:流体会在碰撞、跌落时产生泡沫。在流体模拟烘焙时,可以启用“泡沫”(Foam)选项,它会生成额外的泡沫粒子数据。渲染时,你需要为泡沫创建单独的材质(通常是白色、高粗糙度、略带次表面散射的材质),并使用“属性”(Attribute)节点读取名为“foam”的属性,来混合水体材质和泡沫材质。
4.3 照明与渲染设置:最后的点睛之笔
流体,尤其是透明流体,极度依赖照明和环境来展现其质感。
环境光与HDRI关掉默认的世界背景,使用一张高质量的HDRI(高动态范围环境贴图)是必须的。HDRI提供了丰富、真实的环境反射和折射光源。Blender内置的HDRI选择很少,建议去Poly Haven这类网站下载免费的、高质量的HDRI,特别是那些带有天空、云彩和建筑环境的,它们能在水体表面反射出丰富的细节。
焦散(Caustics)这是让水体渲染效果产生质变的一步。焦散是光线通过透明物体折射后,在周围表面上形成的明亮光斑(比如游泳池底的光纹)。在Cycles渲染器中,你需要:
- 在渲染属性(Render Properties)的“光程”(Light Paths)中,大幅提高“折射”(Transmission)和“光泽”(Glossy)的反弹次数(如12以上)。
- 确保你的水体材质使用了玻璃BSDF等折射节点。
- 在场景中布置一个足够亮的、面积稍大的面光(Area Light)作为主光源,因为焦散需要足够强的直射光才能形成。
- 在接收焦散的物体(如池底)的材质上,确保其有足够的漫反射来显示光斑。
开启焦散计算会急剧增加渲染时间,但它带来的真实感是无可替代的。对于测试,可以只渲染一小块区域看看效果。
采样与降噪流体渲染因为涉及大量的折射、反射和透明计算,噪点会很多。提高“渲染”(Render)采样率是根本方法(最终渲染建议512-1024起步)。同时,务必开启“降噪”(Denoising)。在渲染属性的“降噪”部分,选择“OpenImageDenoise”选项,它能在几乎不损失细节的情况下去除大量噪点,大幅节省达到洁净画面所需的采样数。
5. 实战避坑指南:那些我踩过的“深水区”
理论说再多,不如踩一次坑记得牢。下面是我在无数小时模拟、烘焙和渲染中总结出的几个关键陷阱和解决方案。
5.1 模拟速度慢如蜗牛?检查这三点
- 分辨率是头号杀手:这是最核心的原因。永远从低分辨率(32或64)开始测试动画和形态。在最终烘焙前,使用“简化”(Simplify)面板中的“视图端口”(Viewport)细分设置,在视图中用低精度预览,确认无误后再用高分辨率烘焙。
- 时间步长与自适应域:在域的“自适应域”(Adaptive Domain)选项中,开启“使用自适应域”(Use Adaptive Domain)。这个功能会让模拟只计算流体实际占据区域的网格,而不是整个域框,对于流体只占一小部分空间的场景(如水杯),可以节省大量计算。同时,调整“时间步长”(Time Step)方法为“自适应”(Adaptive),让模拟根据流体的速度自动调整计算步长,能在保证稳定的前提下加快速度。
- 结束帧与缓存管理:不要动不动就模拟500帧。先用低分辨率模拟全部帧数,找到你真正需要流体出现的帧范围(比如第30帧到第150帧)。然后在烘焙设置中,将“开始帧”(Start Frame)和“结束帧”(End Frame)精确设定到这个范围,只烘焙需要的部分。烘焙完成后,及时清理旧的、无用的缓存文件,它们可能占用数十GB的磁盘空间。
5.2 流体“穿模”或行为怪异?
- 障碍物表面厚度:如前所述,这是解决流体从障碍物缝隙渗漏的首要检查项。给所有障碍物增加一个很小的表面厚度(0.01-0.05)。
- 碰撞网格精度:障碍物本身的网格太粗糙(面数太少),模拟引擎可能无法准确识别其表面。确保与流体发生精细交互的障碍物(如杯壁、复杂地形)有足够的面数。一个技巧是:为碰撞单独使用一个细分修改器(Subdivision Surface Modifier),并在流体模拟的“碰撞”(Collision)设置中,将“碰撞质量”(Collision Quality)设置为“更高”(Higher),这样Blender会使用细分后的网格进行碰撞计算,而渲染时仍用原网格。
- 初始速度与引力方向冲突:如果你给流体设置了很大的初始水平速度,但重力又很强,流体可能会在初始几帧表现出剧烈的抖动或非预期旋转。检查初始速度矢量是否合理,或者尝试在流体开始运动后几帧才让重力完全生效(这需要用到关键帧动画,较复杂)。
5.3 渲染结果一片黑或透明感全无?
- 检查法向:生成的流体网格法向可能向内。在编辑模式下全选所有面,按Alt+N,选择“翻转”或“重计算外侧”,确保法线朝外。
- 照明不足:透明材质需要大量的光才能被“看见”。确保你的HDRI足够亮,或者额外添加面光源从侧面和顶部照射流体。尝试关闭所有材质,用一个自发光材质赋予流体,看它是否能在渲染中显示,以排除网格本身的问题。
- 折射率与背景:流体的玻璃质感需要通过折射背后的物体来体现。确保你的流体背后有东西(比如一个棋盘格平面、房间的墙壁或其他物体)。一个常见的测试方法是:在流体后面放一个带有鲜明图案的背景板,如果渲染能看到图案的扭曲,说明折射在工作。
流体模拟是一个需要耐心反复调试的过程。每一次失败烘焙的几分钟甚至几小时,都在加深你对这些参数之间微妙关系的理解。最好的学习方式,就是定一个小目标(比如“让水从杯口溢出并沿着杯壁流下”),然后从最简单的设置开始,逐个参数调整,观察变化,并做好记录。当你第一次看到自己调出的液体,带着真实的粘滞感和表面光泽在屏幕上流动时,那种感觉,绝对值得之前所有的等待。