不过最初的效果原先仅仅是自己自学shader与练习时实现的,没有考虑过多优化措施,总的来说做的比较水(当时才工作半年多 ~_~|||)
考虑到该效果貌似关注的人挺多的,最近刚好也在项目中使用了该效果的移动版本,因此整理出了Demo分享一下制作经验(Demo Git地址在最下面):
实现过程:
1.使用顶点颜色代替深度图
在原版的效果中,我使用了投影深度图的方式,来计算海水底部到海面的深度差,通过这种方式判断海水的潜水处和深水处,这是一种很常见的实现水体效果的方法,然而这意味着:首先我们需要额外渲染场景的深度图,这个操作对于PC平台而言消耗不大,事实上unity中PC平台默认就是开启深度图渲染的,而对于移动平台,深度图的渲染是关闭的,我们当然可以手动在代码中设置开启,但这意味着额外的drawcall消耗。
因此我考虑使用顶点色的方式来表达海水的深水和潜水处,如下图:
但使用这种方式需要高度依赖海水mesh的顶点数量和顶点分别,以及顶点色的控制,因此存在以下两个问题:
1.绘制顶点色的成本
2.如何控制顶点数量和分布
对于第一个问题,我的实现方式是,在unity中通过编辑器预先从海水mesh顶部往下渲染深度图,并映射到mesh的顶点色,同时增加工具允许美术直接在unity中直观的绘制顶点色,如下:
该纹理在编辑器中渲染并映射到mesh:
提供直接绘制顶点色的工具用于调整效果:
比较棘手的是第二个问题,考虑到如果直接交由美术制作mesh,一方面增加制作成本,另一方面比较不容易把控顶点的分布于数量,因为显然这种基于顶点色的效果依赖顶点数量,但顶点数量过多会增加mesh占用的内存以及渲染性能,而直接由程序生成mesh的话如果顶点过少又无法达到效果,如下:
过少的顶点无法体现出海水波浪效果:
2.Mesh细分的思路
为了解决上述为题,我实现了两种对Mesh根据海陆交界处细分的方法,实际上这两种方法都大量借鉴了比较流行的地形lod技术中的方法(只不过我生成的是静态mesh),其中第一种方法借鉴了GeoMipmapping技术,第二种方法则依靠四叉树来实现: