ue4玻璃材质_如何在UE4中简单的模拟Alyx半条命液体的效果

b88f55a83d58d1f7e9de2cef66269caf.png

虽然有很多大佬已经实现了其中的效果,但是大佬们的文章太过于深奥,萌新只能简单的尝试下模拟效果了。
首先整个内容大体可以分为两个部分,材质液面模拟,裁切和运动简单模拟。我们先实现下材质液面的模拟。1.液面模拟

液面模拟我用的是印度大佬的方法,整个物体需要三层的模型,第一层模型用来模拟外面的玻璃容器,第二层模型用来模拟液面,第三层模型则是用来当裁切的MASK。
我们新建一个pawn或者actor,然后放入三层模型。我这边用的是一个酒瓶,glass_label_beer和glass_label_mask使用的是同一个酒瓶模型,cylinder用的则是一个和酒瓶差不多体积的柱子,因为柱子的面比较平液面是靠把顶面压平实现的,所以我选择了柱子,然而为什么是skeletal mesh呢,如果只是静态的话用staticmesh就可以,想要动起来的话我这边采取的方法需要skeletalmesh。

8e616680f196bcc1e27b43bca74d5bc7.png
pawn中的模型

模型准备好后接下来就是材质的部分了,玻璃的材质很普通,大家可以做的更好一些

02da3374e2358e0259d0e3adf34d7983.png
外层玻璃材质节点

接下来就是液面的材质,液面需要将模型上半部分压扁,所以我先用世界位置减去物体位置得出一个基于自身的黑白mask,然后通过减去的height值来定义这个mask的上下移动,接着我们对其输出结果和1进行MAX运算以限制其最小值为1然后乘以负一将上半部分的位移反向,但是由于有max的关系,结果就会出现上半部分会被压成一个平面,(需连接到worlddisplacement或者worldpositionoffset)当然会有多余的部分,我们接下来就开始如何将其进行裁剪。

1d80d923f9c5a854fec4f2d29a6d9b9f.gif
通过height定义液面高度

ad72b6a12bef165835d8390018a752b7.gif
将液面压平

7b00fc6b7899c86859ca18269e303087.png
液面节点图,需连到世界位移或者世界置换

2.裁切

裁切的话我们是用custom depth进行裁切,需要准备一个瓶子模型然后给个简单的黑色材质就行了,将其添加到pawn中的glass_label_mask上,取消勾选Render in Depth Pass和Render in main pass,这样他就不会渲染了,然后勾选Render CustomDepthPass,就可以在液面材质中调用到这个自定义深度做成一个瓶子的mask对超出mask的液面进行不显示。

056afffe71d80de519a3cff4307df7c9.png
BP中设置其属性

然后我们需要在液面材质中加入裁切判断,将场景深度减去自定义深度,就是刚才的瓶子mask,然后让超出的部分为0,未超过的设置为1,将结果连接到opacity通道上,并将材质的设置为translucent模式,勾选details面板的allow custom depth writes(允许自定义深度写入),这样我们就可以得到一个完整的裁切过的半透液面。最好将最外层玻璃瓶放大为1.2倍,用于裁切的mask放大为1.1倍用于提升裁切效果。

aec290a1ed691acb5e07d21bf043ca67.png
勾选允许自定义深度写入

ba633de3061b537f08b2313bd34d8869.png
自定义深度mask判断

7cd9306d17868052265d63fbcaed432c.gif
裁切后的液面

接下来我们需要在液面表面加一层泡沫,原理很简单,在第一步的时候我们得到了基于自身坐标的黑白蒙版,我们只需要将height值再减去一个数,作为mask进行颜色区分就可以了

648fd5289616be7608268ef2a5224b06.png
Fill2值控制泡沫的厚度

0211d7d88ad5f32e1ee5ede175f74f50.gif
Fill2值的变化

有了泡沫以后我们需要在液体表面模拟一下基本的运动,基本方法是在表面用sine函数进行顶点偏移。将第一步worldposition减去objectposition的R轴提取出来(G轴也可以),然后加上时间偏移经过sine之后叠加到被压平的液面上乘以0,0,1取Z轴就可以得到基本的效果,然后可以自己控制sine的频率和强度,可以得到下面的运动效果。法线的话可以不加,如果想要静态的话这边已经可以基本满足你的需求了。

9b37351af323c98df74de6203b511873.gif
液面的运动模拟

a9f9a4bd08a9795680aabf71cc8bbc07.png
液体表面运动节点

2.液面运动模拟
液面的运动模拟的话我采用的是spring bone的方法,我看到有些大佬是基于顶点算的效果,但是由于本人技术有限,只能做些简化的模拟了。
首先我们需要一个带绑定蒙皮的skeletalmesh,由于本人只会简单的绑定,绑的不是很好,权重都是自动的,当时的思路是由上面四个bone控制液面的运动,后来发现其实效果一般,相信各位大佬有更好的解决方法。由于需要液面运动,所以我给了比较多的点。

53d56a1c7470c56d1242cb8f4b0c0d65.png
blender中rig好的模型

59bed4393c23108e5865bfcfb8a7244b.png
模型线框

这步完成以后导入UE4并给上材质,然后这时候我们需要以圆柱的骨架创建一个动画蓝图,在动画蓝图里给每个bone加入spring controller,然后设置其对应的参数。最底层的骨骼我是用来模拟整体运动的,我让其只在Z轴运动并调整了SpringStiffness(刚度,越大弹性越好)和SpringDamping(阻尼,越大,回弹越慢)。然后给各个骨骼都调整参数(比较耗费时间,但是参数调的好可以模拟出大多数的流动质感)。

6cf295d9307fd9b2e8819acea4d73fab.png
最底层bone参数设置

ca00826fbe88f0a9322eb67c12238cc2.png
动画蓝图的springcontroller

初始的动画我们直接双击圆柱的skeletalmesh,点击CreateAsset下的CreateAnimation然后创建个静态的动画就行了(或者你可以从建模软件中导出)。

4e2a98c59b6476a36a59ed2803c19d46.png
初始静态动画创建

最后我们将保存好的动画蓝图放在我们创建的pawn中的cylinder上就行了

bfd3fc994be53f58302c7b48a85a4dc6.png
给圆柱pawn中的圆柱骨架赋予动画蓝图

现在我们可以点击play然后肆意的移动她,你会发现在旋转的过程中其实体积偏差有些大,这时候就需要把上面提到的height值用参数集代替然后用actor的rotation来关联调整height并且传回到液面的材质里。

68538e588057e6b320b05c55e305a493.png
每帧设置height的值并且用HEIGHT来调整整体高度

然后我们基本就已经得到了我们所需要的结果,下面是我基本做好的液面,虽然运动轨迹不是很好,但是基本实现了我们所需要的效果,想要完善则需要更好的rig和更合适的参数设定了。我们也可以把参数和UI绑定一下,用UI控制更加直观一些。

010c57a49fa524e45b5dccd0a36aa6b4.gif
上下摇晃

02cabd78f167fa89e640a4710a1edc50.gif
旋转摇晃

408153fde5e8499ffd4914e81dfa348a.gif
液面高度控制

总结:
这个效果前前后后也做了不少的时间,其中还存在着很多的问题,比如透明穿插,比如表面怎么模拟的更真实,运动如何更好,甚至泡沫如何形成消散等(本人也在努力学习raymarch,争取能在后面完善)。希望大佬们能多多指出我文章中的错误和不足,斧正。
最后感谢下孙同学提供的啤酒瓶 @孙大胖 。


附上原视频链接:https://www.youtube.com/watch?v=VIz80hrCNd4
给我思路的一篇文章:https://80.lv/articles/simulating-liquids-in-a-bottle-with-a-shader/