开发经验 | 在Unity中实现水体动态效果
本文将由开发者Olivers Pavicevics分享如何在Unity中处理水效果的各种制作难题。
前提介绍
Olivers Pavicevics是一名意大利的大学教授以及Unity的开发者,他开发了Unity插件资源:VR Panorama 360 Pro和CScape。
在本文中我们分享的是他正在开发的插件项目NordLake的一些经验感受。NordLake是针对VR进行优化的Unity水体系统,本文中视频中的内容,均是Unity中的效果,而非照片效果。
从2016年9月Olivers在Unity官方论坛进行公布后,受到很多开发者的期待,但是由于其个人精力有限,对效果精益求精,目前NordLake依旧是一个开发中的项目,并没有正式发布在Asset Store资源商店。
Olivers提供了一个旧版的NordLake资源包,提供免费测试使用,并且接受反馈,以对NordLake进行最后的修改。一些使用过的人员对此给予高度赞扬,表示:惊叹于NordLake展示的效果与美丽,让人就像站在一个平静的湖边。
如果你希望了解NordLake更多信息,以及下载该测试包,请访问:
https://forum.unity.com/threads/nordlake-optimised-water-system.390012/
常见项目问题
在处理此类项目时,我将从实际难题开始着手。下面我将列出曾经遇到有关水系统相关问题:
几乎所有水系统都使用半透明着色器。但使用半透明着色器可能会带来和图像效果有关的严重问题,这意味着我们无法渲染阴影和基于深度的图像效果,例如:SSR(次表面散射),AO(环境遮蔽)或DOF(景深)。
较逼真的系统会使用一个或二个额外摄像机,并需要多次渲染场景,此处指没有水体,反射平面和折射视图的正常场景。对于VR而言,由于必须对场景渲染4~6次,这意味着会对性能产生很大影响,因为我们必须渲染立体视图。
现有的多数水系统都用于模拟大海的水体,但对于平静的水体却几乎没有效果逼真的解决方案。
多数水系统在处理模糊和浑浊水体时存在问题。
在第一阶段中,我的重点不在动态水体,我主要考虑如何制作好着色器,使它既能在VR上高效工作,又适用于移动端系统。
参考效果
水的参考效果来源于现实生活。我花了大量时间观察芬兰的一个湖泊,了解一天中不同时间段和不同天气下水面的效果。在湖边花的时间给我带来了创作灵感,让我开始制作NordLake项目,实现其它水系统所缺乏的效果。
逼真感
我认为实现逼真感的关键并不在于完美的物理模拟效果,至少目前没有足够的CPU和GPU性能来实时计算所有可用的流体动态效果。
所以我尝试的是通过艺术角度处理问题,而不是依照复杂的物理计算公式。这种方法主要源于对现实世界的观察,并描绘现实世界的画面。区别在于:使用的不是油彩和画板,而是着色器。
处理这类表面的一个主要难题是,水表面可以从不同距离观察,这意味着它们应该在短距离和长距离都有一定可信度。
下图中,我们近距离观看到的是清澈的水波,远距离则是没有反射效果的表面。
水的另一个问题在于,它不是完全清澈的。我们总会看到有东西漂浮在水中,例如植物,昆虫和鱼,它们让水产生波纹,这也是需要在水上实现的一个特点。
但是我无法使用简单的平铺纹理,所以我使用了水的深度信息,来实现水面的多个特性,该效果通过使用纹理数组来完成。纹理数组很强大,它能将大量纹理打包到一个纹理中,该纹理可以被着色器用作单个纹理。
波浪
在尝试实现交互式水体的不同方法后,我发现这些方法对最终用户来说效果有限且难以使用。当必须绘制大型表面时,流体贴图却难以制作,而且在工具中绘制流体贴图要求掌握熟练的功底和艺术技巧,过程非常繁琐。
于是我使用了最简单的方法:水的动态效果由简单的粒子生成。它能在不影响渲染性能的同时,轻松控制艺术效果。
我使用了要渲染到渲染纹理的粒子,以及特别着色器,从该深度纹理创建法线贴图。这样得到的波浪虽然不完全符合物理,但是看起来很真实。这种方法非常灵活,因为它允许使用粒子作为波浪的来源,并使用图像遮罩来遮挡部分不需要粒子的区域。
我没有使用粒子来渲染微小的起伏效果,起伏效果是通过水面着色器的代码实现的,它们基于深度纹理的输入来产生效果。这种方法大幅提升了性能,因为带有波浪信息的深度纹理会很小,而且着色器只需要渲染大型波浪。这些场景中的波浪只在合适距离进行渲染,通常在其周围50米的距离内。该距离足够用于FPS类型视图。
最后,为了实现波浪或波纹,用户只需要将粒子系统加入场景中想要出现波浪的位置即可。它可以在静态对象下,也可以附加到移动对象上,例如下图的鲨鱼。由于使用了Unity粒子,那些波浪还能由碰撞体反弹。
挑战
Unity中的工作流程很直观:
你可以将Nordlake水平面添加到包含地形,即Unity地形或网格的场景。
单击按钮生成材质,湖泊的所有必要贴图会在几秒内生成,你可以按喜好设置材质参数,包括水颜色,菲涅尔因子和流速。
对于逼真渲染效果来说,最重要的是使用后期处理效果。由于NordLake适用于屏幕空间反射效果,所以启用SSR很重要。但这不是必要条件,因为NordLake也可以使用反射探针。
还有一个必备效果是泛光,因为对所有反射表面来说,当我们观察反射亮光的水面时,泛光效果有助于模拟眼睛看到的实际效果。
较强的波浪会需要其它方法来实现,但该方法没有现在所使用方法的优化程度。强劲的波浪要使用顶点替换功能,这意味着我们必须使用曲面细分着色器。
但需要注意曲面细分着色器不是所有平台都可用,这并不表示实现方法很难,只是要处理一些其它方面的问题。例如较强波浪带有不同的属性,因为它们会产生泡沫和内部折射。
建议
液体大概由50%的着色和50%的动态效果组成。不要低估这二个因素,如果着色达到60%,那么动态效果会变为40%。
简单来说,我会将所有液体作为粒子系统处理。在制作粒子系统前,必须考虑的一个问题是:我是让系统完全符合物理,还是让它看起来合理就行?
在我看来,人类无法区分准确符合物理的粒子流体和大致符合物理的运动效果。作为人类,我们善于感知自然的运动,因为我们每天都会看到这类运动,但我们通常看到的是宏观运动以及宏观的动态效果。
另一个“关注点”在于光线对该运动的表现行为。从这个角度看,对于微观运动,我们应该研究反射和光照的具体情况。手机摄像头是进行动态分析的好工具,它能捕捉60FPS以上帧率的画面。我喜欢使用视频捕捉,并将捕捉结果重叠在粒子系统上,以便得到符合现实世界的时间点和光照。
我做了一个测试,首先捕捉水表面的屏幕截图,只要其中一帧即可。然后观察那一帧画面,试着了解它是否可以使用。只有在我发现该画面符合照片效果时,才会开始处理水的运动效果。这可以与水结合,就像粒子一样,但问题在于,你必须找到合适的平衡,使视觉效果不会看起来太别扭。
小结
在Unity中实现水体动态效果的经验分享就介绍到这里,更多Unity开发经验分享尽在Unity官方中文论坛(UnityChina.cn)。
推荐阅读
官方活动
2019年5月10日-12日上海,Unite大会强势回归。 暖冬特惠票正式开售,购票即获指定Asset Store资源商店精品21款资源的5折优惠券。[了解详情...]
购票链接:
http://UniteShanghai2019.bagevent.com
Unity全球学生开发挑战赛火热进行中(最后半个月)
Unity面向全球的学生推出-Unity全球学生开发挑战赛,寻找全世界最具创意,展现自我的学生开发者团队。[了解详情...]
活动地址:
https://connect.unity.com/challenges/gsc2018
活动 | Unity for Humanity 2019挑战赛
参加Unity for Humanity挑战赛,向我们展示你的作品将如何改变世界。[了解详情...]
活动地址:
https://connect.unity.com/challenges/unityforhumanity
点击“阅读原文”访问Unity官方中文论坛