Mecanim 发表于 2022-5-28 16:21

【Unity URP特效】使用VFX Graph制作冰冻肥皂泡——冰晶 ...

最后一篇文章我们来实现泡泡上的冰晶,前两篇文章请看:
今天来实现完整的效果↓





背光



给冰晶添加彩虹色效果



为了压缩图片加速播放了

本工程使用Unity 2021.2.13f1,URP12.1.4,需要在package manager里手动安装Visual Effect Graph。
工程地址:https://github.com/MidoriMeng/Frozen-Bubble
因为有工程,所以之后的讲解都会挑重点讲
<hr/>这是参考视频:
https://www.bilibili.com/video/BV1mT4y1K7TS/?spm_id_from=333.788.recommend_more_video.0
(最早看的视频删掉了,只剩下一堆零散的抖音视频,无语)










通过对视频的观察,我们首先可以看到冰晶是飘动的,因为吹泡泡的时候会产生一个动力让冰晶根据惯性在泡泡表面有运动。其次冰晶是会生长的,如果用缩放去实现,那么已经长好的部分会被跟着一起放大,所以我们要让他真正的生长。


我们的目标是去制作上图红圈中的单个冰晶,制作它的生长动画,然后用VFX graph让它在泡泡表面生成。
1.面片建模




“Cylinder”



形变才能贴合在球面上

vfx graph中内置了一些几何体供我们选择,其中就有octagon(八边形)的选项,但是我们仍然要自己建一个模型,因为需要在中间添加一些顶点,为形变做准备。
2.贴图

四角冰晶贴图使用substance designer制作,最终输出法线图以及一张包含各种信息的mask贴图:



全览

先来制作一根冰针:



这里注意头和尾是要有高度差的,这样才好区分生长的先后

接下来我使用了一位大神制作的一系列曲线自定义节点:
https://www.artstation.com/artwork/lV3BKG
有了它我可以很方便的控制形状,更加人性化,如果用传统的节点去拖,不知道要拖多少个。





大神制作的示例作品



生成冰晶。这里可以更明显的感觉到先长冰晶的地方高,后长冰晶的地方低。这个是为了之后的动画做准备的。这是一个高度信息,不是颜色信息


之前制作的生长mask在这里体现了它的效果,我们使用histogram scan节点控制它的亮度(position),从而实现冰晶的从内向外的生长。这也是substance designer的一个重要技巧,用直方图操作去控制纹理的生长和衰减。



这部分才是颜色或者说透明度信息的制作


输出到两张图上,mask的三个通道分别表示生长,光滑度,以及透明度
3.冰晶shader graph




全览



控制顶点铺在一个半径为“Bubble Radius”的球上


上图的custom function是重现了在designer中我们刚使用的节点,在designer中这个节点可以右键open reference打开查看它的实现,直接照抄过来就可以。默认的情况下过渡的效果不好,把mask图的压缩选成high quality就可以了。


我们要开启双面渲染,此时背面的法线会出现问题(格外地亮),所以我们需要判断一下当前渲染的面是正面还是背面,如果是背面就翻转一下。其实不翻转也可以,因为冰晶本身也是有BTDF的透光效果。



调整Growth参数和Bubble Radius参数

4.动态冰晶vfx graph




全览



初始化,根据泡泡的半径确定一些数值

4.1随机位置



上图展示了冰晶位置的计算。(先不用关注红框以外的地方)我们使用的是球坐标系,随机生成半径以及两个角度(θ和φ),最终使用最右边的spherical to rectangular节点转化为笛卡尔坐标系。


为什么要使用球坐标系呢?因为冰晶要围绕着球旋转,使用球坐标系的话旋转就只是两个角度的变化。


现在我们看之前忽略的红框之外的一大堆东西,他们关乎三件事:

[*]如上图所示,我们随机地生成两个角度θ和φ,在二维平面看起来是均匀分布的,但是在球面上会出现两端更密集的问题。使用这位大佬的方法后生成下图所示的正确分布(http://corysimon.github.io/articles/uniformdistn-on-sphere/)
[*]因为unity的φ和一般球坐标系的φ范围是不一样的,所以要重新映射一下。
[*]为坐标添加动画。使用时间去插值起点和终点,并且用曲线控制运动的节奏。


4.2 随机旋转



此时我们生成的冰晶都是一个角度,接下来我们添加旋转。比如上图所示,默认情况下,每片冰晶的坐标系都像左边一样和世界空间是一个坐标系,此时去旋转冰晶就会戳进泡泡里。我们想将它的坐标系转化成右边的样子,以法线N作为y轴。这样给y轴一个随机值就能实现随机旋转,还可以添加动画。
现在我们手头只有一个法线方向(通过将冰晶的位置归一化得到),怎么得到另外两个坐标轴呢?这里我们用到施密特正交化(gram-schmidt process)。
现有一组基(即xyz轴,这里的n表示可以对任意维空间操作):


想用它算出一组新的正交基(正交即每个基相互垂直):


要使用以下算法:


可以看到它是迭代计算每个基的。对应一下,β1就是v1就是法线N;β2的使用了新向量v2,我们可以随便用xyz轴哪一个都可以,细致的同学可以根据当前向量去判断更适合使用哪个轴,避免两个向量基本重合的情况(我没做,挠头)。



完整计算过程。我选用的是y轴(0,1,0)计算



piece bending是不知道为啥用泡泡半径的时候面片不能很好地贴合球面,懒得纠结了直接加个参数【


这里给出我的参数设置,注意开启reflection probe。
5.讨论

我们用三篇文章实现了两个效果,一个是肥皂泡,一个是动态冰晶,他们组合成了最终的冰冻泡泡效果。目前的版本还有一些局限:

[*]冰晶其实也是有彩虹色的,通过对视频的仔细观察可以发现
[*]冰晶会相互重叠,实际情况是已经有冰晶的位置就不会再被覆盖了
[*]目前泡泡的编辑比较繁琐,分为两个材质,每次调参数都要调两遍

对于第一个问题,可以复用之前的彩虹色函数,把冰晶也转化成高光工作流。





高光令我瞎眼


上图是给彩虹色添加的参数。thickness remap将冰晶透明度由0~1映射到这个参数的范围,和phase shift一起调整效果。specular intensity是给彩虹色乘以一个系数,防止过亮。

第二个问题,我的想法是添加一个render pass,将冰晶的透明度渲染到另一个render texture,用于在正常渲染的时候判断当前屏幕空间位置是否已经有冰晶。但是目前shader graph和vfx graph都不支持。我没有想到方便一些的办法。

第三个问题可以写一个render feature控制,让特殊材质渲染两次,并且修改他们的culling。这里给出两个参考链接:
https://docs.unity3d.com/ScriptReference/Rendering.CullMode.html
https://forum.unity.com/threads/expose-shader-culling-option-in-material-editor.200236/

更高端的彩虹色模型可以参考这篇论文,提出了新的高光BRDF:
https://belcour.github.io/blog/research/publication/2017/05/01/brdf-thin-film.html


unity hdrp中内置了该模型:


碎碎念一下,整个制作过程最花时间的一个是计算位置用到的数学,一个是着色。数学解决了就完了,着色其实到现在我都觉得不太好,没有很好地还原参考视频,而且调整比较麻烦,要同时调整diffuse, specular和alpha,放在雪地比较好的效果放在东非大草原里又太亮了,这里调好了放回雪地又不满意,其实这就不符合PBR的原则了。
挑选diffuse和specular的时候,查了水、冰的设置,数值很低,效果都不好。想来是因为冰晶材质有一些偏冰霜,所以albedo要提高,外加有BTDF和BSSRDF,都会让它更亮(尝试找补)。
如果有大佬能提意见建议改进着色,万分感谢!

再放一遍工程链接:
https://github.com/MidoriMeng/Frozen-Bubble
比起学习某个知识点写文章,做这个完整效果真的花了挺长时间(然后还不完善呜呜呜),求支持一下orz

*本文于5月20日(好惨啊没过节)首发于“Unity官方开发者社区”公众号,更多unity知识欢迎关注:
今日豆知识-URP VFX graph冰冻泡泡效果 附工程
页: [1]
查看完整版本: 【Unity URP特效】使用VFX Graph制作冰冻肥皂泡——冰晶 ...