[URP] 常见水体效果实现
说实话,我平时不太写shader,但看到udpe这个教程的时候,觉得挺有意思的。他分享了一套在Unity URP里实现水体效果的方法,包括低多边形水体、折射反射、水体交互这些。虽然是基础实现,没怎么扣优化,但够用了。
环境准备
他用的Unity 2022.3.62,URP项目。
- 先装ProBuilder工具,方便做网格。
- 打开ProBuilder窗口,创建一个50×50的平面。
- 新建Unlit Shader,右键创建材质,把材质丢给平面。
- 打开shader,URP通常用HLSL。
水波与顶点偏移
写一个水波方法,用正弦函数来偏移顶点。如果编辑器里看着卡,可以开那个选项。
然后在Properties里定义参数,在Pass里接收参数,直接返回设定颜色。
光照与低多边形效果
要算光照,就需要法线。
他想要类似纪念碑谷那样的低多边形水体效果——顶点着色器传递世界坐标,片元着色器通过求导加叉乘得到法线。这样每个三角形的三个顶点法线一致,颜色也统一。
然后加兰伯特光照和Unity环境光。
调调参数,每个面颜色就不一样了。
还可以混合两个波,看着不会太单调。
高光方面,先算光线与世界夹角的角平分线。如果水面法线和这个平分线比较接近,就显示高光。
水面浮沫
先建个方块放水里。
在方块接触水面的地方显示白色浮沫。
思路是:计算屏幕空间里水表面到水下物体的距离。如果距离近,就绘制浮沫。
- 添加配置参数。
- 在v2f里加入屏幕空间坐标。
- 在顶点着色器计算——先算水面的深度值,再算物体的深度值。
- 计算物体深度时,正交相机和透视相机要分开处理。
- 采样深度纹理,需要引入头文件,并在URP设置里开启Depth Texture。
- 最后算深度差和浮沫强度。
水体遮罩
用Cube做个船体(他演示时加速了)。
水会穿模到船体里,所以需要遮罩让水体不显示。
思路:让一个平面只写入深度,不写入颜色。在船体之后、水体之前渲染。这样船体正常显示,水体觉得被挡住了就不绘制。
- 创建平面和材质。
- 修改渲染队列。
- 开启深度写入,关闭颜色显示。
- 改一下水体的渲染队列。
不过这样做有一点小毛病——如果船没完全浸没,效果会有点怪。他也没再深入。
实战建议
这个教程虽然基础,但挺适合U3D特效入门的。作者说代码放Gitee上了,有兴趣可以去看看:https://gitee.com/udpe/urp-water-effect
总结
- 水波用正弦函数,简单够用。
- 低多边形光照靠求导加叉乘法线。
- 浮沫用深度差判断。
- 遮罩靠渲染队列和深度写入。
不过记住,这只是基础实现,真要商用还得抠优化。但起码能让你快速看到效果,找到感觉。