unity水面涟漪反射效果
Unity3D技术手机游戏引擎手游引擎CGGraph渲染
显示全部 9
46720 104
实名

通过了实名认证的内容创造者

发布于 2018-11-19 14:28:29

您需要 登录 才可以下载或查看,没有账号?注册

x
WaveProvider是一个组件和着色器库,可以使用Unity轻松表达波形,利用该组件可以实现受物理影响的水面动态涟漪效果,该组件的使用方法在开源库原文中作者已经有了详细的介绍,本文重点解析该效果的实现过程和性能测试。

效果展示:
8.gif
7.gif












实现原理

1.添加用于绘制倒影图像的反射相机




考虑到主摄像机的位置可能会动态地改变,所以反射摄像机也需要使用脚本控制使其动态移动到合适位置(与主相机相对水面对称)以绘制正确的反射图像。

2.根据投影面编写一个水面投影反射的着色器
投影时,需要统一投影侧的空间并确定投影面(项目中的这个投影面就是水面)。使用反射相机的变换矩阵变换,并渲染每个对象。当使用主摄像机在水面上绘制对象时,使用反射相机的变换矩阵来转换对象顶点。

下面的代码段是水面投影反射着色器的一部分:
1    struct v2f
2    {
3        float2 uv : TEXCOORD0;
4        float4 vertex : SV_POSITION;
5        float4 ref : TEXCOORD1;
6    };
7
8    sampler2D _MainTex;
9    float4 _MainTex_ST;
10    sampler2D _RefTex;  //反射绘制的纹理
11    float4x4 _RefVP;    //反向VP矩阵输入
12    float4x4 _RefW;     //反射对象的局部变换矩阵
13
14    v2f vert (appdata v)
15    {
16        v2f o;
17        o.vertex = UnityObjectToClipPos(v.vertex);
18        o.ref = mul(_RefVP, mul(_RefW, v.vertex));
19        o.uv = TRANSFORM_TEX(v.uv, _MainTex);
20        return o;
21    }
22
23    fixed4 frag (v2f i) : SV_Target
24    {
25        return tex2D(_RefTex, i.ref.xy / i.ref.w * 0.5 + 0.5);
26    }
其中_ RefTex是反射绘制的纹理,_ RefVP是反向VP矩阵输入,_RefW是反射对象的局部变换矩阵。顶点着色器使用_RefW将顶点转换为世界坐标,再通过_RefVP将世界坐标转换为反射相机的投影空间,片元着色器将其转换为普通坐标转换+纹理坐标,并用于主摄像机渲染。
然后,我们得到了如下效果:

这样,即使相机移动或反射物体移动,旋转或缩放,也可以在没有违和感的情况下显示正确的投影图像。

3.在投影着色器的基础上编写一个根据法线扭曲的着色器
接下来,我们添加扭曲投影的代码,这里通过引用法线贴图的方式实现。

1float2 offset = bump * _BumpAmt * _RefTex_TexelSize.xy;
2i.ref.xy = offset * i.ref.z + i.ref.xy
其中_BumpAmt是可调节的影响系数,_BumpAmt越大,则涟漪越强烈,但同时会影响到水面的反射效果,因此建议将参数控制在300以下,并按自己的需求进行调整。


_BumpAmt参数对效果的影响示意图

4.根据脚的运动输入波动方程


利用波动方程,使波浪的高度可以作为纹理。(此处不对波动方程进行详细介绍)

左边区域是波纹输入纹理的调试界面,接下来,将存储在此纹理中的波的高度(被视为高度图)解析为法线并扭曲反射纹理,实际上,当从高度图计算法线贴图时,也可以直接求解偏导数,从而输出正常值作为着色器的凹凸。感兴趣的朋友可以参考该作者的另一篇相关文章:
http://esprog.hatenablog.com/entry/2016/10/24/183733

同时根据角色脚的运动输入更改波动方程
作者在人物的脚点上附上了Collider组件和一个改造了InkPainter的CollisionPainter的脚本,可以理解为在人物的脚点上各加了一个笔刷,具体实现可以参考InkPainter插件里的Brush类。
ps:InkPainter插件链接附在文末,喜欢Splatoon的,或者想实现类似Splatoon效果的朋友,该插件可以提供不错的参考价值。


性能测试


使用UWA GOT Online对这个效果进行了性能测试。为了更真实地反映这个项目的渲染开销,我们使用了非多线程渲染的版本。

同时准备了4个版本的场景作比较:
版本A:即原版,3个角色加水面涟漪反射效果;
版本B:3个角色,去除涟漪反射效果,同时将地板Shader更换成简单的Diffuse;
版本C:9个角色加水面涟漪反射效果;
版本D:9个角色,去除涟漪反射效果,同时将地板Shader更换成简单的Diffuse。

测试4个版本的场景后,通过UWA GOT Online解析数据,最终得到对比数据如下:



我们观察到,有无涟漪反射的效果,对场景的帧率有一定的影响,但随着角色数量的上升,场景帧率发生了明显的下降,通过逻辑代码的分析我们发现开销主要集中在渲染模块上,接下来我们具体看一下Camera.Render的耗时均值对比:



下面我们以版本A为例具体看一下渲染耗时曲线:

可以观察到渲染耗时在8ms左右波动,其中不透明渲染在5ms左右,半透明渲染在1ms左右。然后再来对比一下四个版本的不透明和半透明渲染的平均耗时:



这里我们可以看到,开启效果后,不透明渲染和半透明渲染开销均有上升,且影响较大,开启效果会额外增加40%左右的渲染开销。

考虑到项目中的角色材质比较复杂,会对测试结果造成一定影响,对红米Note3这类低性能机型而言,能跑到这个数据,该效果的性能还是可以接受的,但建议开发者在使用时控制反射场景的复杂度,同时可以考虑优化水波反射的Shader以达到很好的优化效果。






评分

参与人数 2元素币 +20 活跃度 +10 展开 理由
七濑丸 + 10 【点赞】这很有大网气质!
元素界王神... + 20

查看全部评分

还没有设置签名!您可以在此展示你的链接,或者个人主页!
使用道具 <
34100171  发表于 2018-11-19 14:40:04  
2#
谢谢楼主分享。
回复 收起回复
使用道具
赵国勇  发表于 2018-11-19 15:44:51  
3#
666666666
回复 收起回复
使用道具
wuming  发表于 2018-11-20 09:34:35  
4#
回复 收起回复
使用道具
free5days  发表于 2018-11-20 09:39:09  
5#
满满正能量·
回复 收起回复
使用道具
vitamins  发表于 2018-11-20 09:40:46  
6#
谢谢楼主分享。
回复 收起回复
使用道具
vitamins  发表于 2018-11-20 09:41:08  
7#
谢谢楼主分享。
回复 收起回复
使用道具
vitamins  发表于 2018-11-20 09:42:35  
8#
谢谢楼主分享。
回复 收起回复
使用道具
vitamins  发表于 2018-11-20 09:43:00  
9#
谢谢楼主分享。
回复 收起回复
使用道具
1991072687  发表于 2018-11-20 10:11:03  
10#
谢谢大佬分享
回复 收起回复
使用道具
1991072687  发表于 2018-11-20 10:11:11  
11#
谢谢大佬分享
回复 收起回复
使用道具
Swyan  发表于 2018-11-20 10:11:56  
12#

解释得很详细 楼主给你赞个
回复 收起回复
使用道具
张前进  发表于 2018-11-20 10:15:03  
13#
这个真的非常好,借鉴意义蛮大.
回复 收起回复
使用道具
夕明  发表于 2018-11-20 10:15:43  
14#
7
回复 收起回复
使用道具
飞~  发表于 2018-11-20 10:16:21  
15#
赞一个~666
回复 收起回复
使用道具
qq_Violet_aNs  发表于 2018-11-20 10:19:56  
16#
666666666
回复 收起回复
使用道具
@LD  发表于 2018-11-20 10:27:22  
17#
路过围观,感谢分享~
回复 收起回复
使用道具
房森  发表于 2018-11-20 19:24:32  
18#
实打实大所大所
回复 收起回复
使用道具
房森  发表于 2018-11-20 19:24:36  
19#
实打实大师
回复 收起回复
使用道具
G长远36  发表于 2018-11-21 06:34:25  
20#

谢谢分享,收藏学习
回复 收起回复
使用道具
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表