墙和鸡蛋 发表于 2020-12-24 09:15

在Unity中完善一下Unreal模拟伪液体血瓶的效果

之前群里的诸位程序大佬们看到一个血瓶效果,链接点这里:
知乎链接:
https://zhuanlan.zhihu.com/p/67576382?utm_source=wechat_session&utm_medium=social&utm_oi=69639983857664&from=groupmessage
标题:Unreal-TrickTech_血瓶_伪液体
然后就吐槽我,让我也写点儿类似这种效果的文章啊,云云...
我在学习啊,我在补渲染基础啊,我才看到图片压缩算法啊,才刚知道BC1(DXT1)压缩比为啥是6:1啊,擦......
算了,今儿上班有点儿空,就大体实现了一下之前自己的一个思路。
原文中,是以一个物体顶点位置的高度作为mask,进行顶点剔除,然后双面渲染,将内表面的法线调整为float3(0,0,1),再加上边缘顶点的扰动,来实现的伪液体的效果。几年前我在项目中,制作边缘过度的水效果的时候,也是大同小异的这么一种思路,当然问题就是水面其实是凹进去的,无法进行必要的交互,否则就会穿帮。
所以,看完这篇文章后,我就大体想到了另外的一个思路。不是用mask将顶点剔除,而是保留顶点,将高度超过限制的顶点摊平到液体表面,之后再调整法线和加入液体的顶点运动模拟来实现伪液体效果。好处自然是不用双面渲染而且深度测试也完全OK,不管算光照,反射还是阴影都不会有问题。
思路有了,剩下的就是着手开干了:
1:Max中创建标准球体模型,记下球体半径,模型记得坐标系归零。
2:导入Unity,附上材质,创建空无光照Shader,拖给材质,开始进行Shader的编写。
3:为了观察法线效果,我这里用了一张血色check图,然后设置为CubeMap模式,先给球写一个反射效果。
到这里都没有什么问题,当然也还没进入正题,下面就开始写顶点变换部分的算法了。
4:很简单的,先给一个控制血量百分比的参数:
_HpAmount("HP%",range(0.001,100)) = 100
然后VS里面,写入(注意,这里都是在Local空间下计算的顶点位置,所以要写到剪裁空间变换之前。还有,所有的if,都可以用step来进行优化):
if (v.vertex.z >= 0.006 * _HpAmount)
{                  
    v.vertex.z = 0.006 * _HpAmount;
    v.normal = float3(0, 0, 1);
}
这样就实现了最基本的顶点高度坍缩了。
当然,目前的效果看,有几个很大的问题:
a,液面面积不能进行必要的改变。高于50%血量还凑合,但如果低于50%的话,血球效果就完全不对了。
b,因为顶点数量较少,在VS里面写顶点级别的形变,毫无疑问,上下两层顶点之间,是不会有很好的过度的,这就会导致血量下降时,球体边缘的变化不是沿着球面弧形变化的,而是直上直下的顶点塌陷,很丑。
所以,我们要想办法解决这两个问题。
是时候,运用我们的几何知识了——

根据调整的血量百分比,我们完全可以计算出,该血量高度下的圆形液面的半径,从而也就完全能得出在该血量下,球体的外轮廓正确的顶点位置坐标。之后,只要将塌陷的顶点的水平坐标根据正确的坐标位置进行修正即可。
所以也就出现了本做法的一个重要的限定条件,这玩意儿的形状必须是简单的规则几何体。
好了,下面我们开始讲几何:


设目前的血量为H,H>=50%,球体半径为r,我们要求的,就是球面上一点P的坐标值。如上图:
因为我们的坐标系已经初始化为球底部中心为(0,0,0),所以:
点P到球中心轴的距离长度为r * sinα。
而cosα = 球面上半部分的血量 / 半径r。
血量H-50%,即为球面上半部分的血量。
这样,我们也就得出了H高度下,理想的球弧面上,顶点P距离中心轴的距离了(下面简称理想距离)。
而我们塌陷的点距离中心轴的实际距离为(下面简称实际距离):
√(v.vertex.x + v.vertex.y)
所以,我们还需要根据两个距离的比值,对顶点的x、y值进行缩放。这样就可以保证顶点完美的附着在球体表面了。
H>=50%的时候,顶点的x、y值都是需要进行扩大的。但这里又不能每个顶点都进行扩大,因为液面上还要保证一定的网格密度,好留着后面进行液面模拟和法线修正呢。所以这边可以设定一个实际距离的长度阈值,用来保证只对外围的顶点进行x、y值的修正。
当H<50%的时候,同样的,需要将实际距离的长度大于理想距离的点进行x、y值的修正即可。
计算代码如下:
经过这样的修正之后,液面就可以在保证一定的网格密度的前提下,根据血量高度,沿球体弧面进行平滑的面积缩放了。
之后,至于传入随机数,进行液面波浪的模拟啊,PS通道中利用偏导数求解法线啊,什么光照计算啊,阴影模拟啊,什么什么的,就都可以顺利的往下慢慢进行了。
页: [1]
查看完整版本: 在Unity中完善一下Unreal模拟伪液体血瓶的效果