怪物猎人OL海水渲染效果的改进

发表于2015-07-21
评论4 3.3k浏览

      怪物猎人OL目前发布的版本用的是CRYENGINE自带的海水渲染,这个模块CRYTEK很多年没怎么改过了,DX9版本效果上基本和07年CRYSISI刚出来时差不多,DX11版本加了tessellation效果会好一些,但和目前效果做的最好的一些游戏还是有差距,原因嘛估计主要是CRYSISI后面几代基本上都是城市场景为主,CRYTEK也没有太重视这个模块。怪物猎人OL去年底加入了新的关卡水龙关,这个关卡的移动方式就是开着快艇在海面上跑,为了让这个关卡效果更好一些,决定改进下CRYENGINE的海水渲染方式。研究了好几个游戏的海水渲染,感觉目前效果做的最好的还是刺客信条4黑旗,看了下他们的实现方式觉得也不难,于是我在我们引擎里实现了一套类似的效果:

  介绍下AC4的渲染方法:

 1.海水的几何部分用2张预计算的128*128的FFT来模拟,一张用于比较小的波形(左图)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


一张用于比较大的波形(右图),它们tilling的范围一小一大

 

2法线是512*512的,这部分他们的技术文档里没有看到写,不过通过GPA分析发现每一帧用的是不一样的法线,而且没有发现哪个DP或者computer shader和这个有关,所以我估计就是直接录的序列帧

3海水的caustic也是录的序列帧,大小256*256

 

 

4海水颜色通过一张美术做的纹理来控制,不同的海水深度取不同的颜色

5 海水3S效果也是通过这张颜色纹理来做的,需要3S的部分就把水的深度变浅

 

6海面的mesh用的projectgrid的方法,利用当前相机位置算一个Projector的位置,然后由这个projector来投射mesh,大小是256*1024,一共分64个DP来画,一个DP画一个64*64的mesh

 

7.foam大致分两种,一种是静态的海浪,通过噪声纹理和地形拓扑结构和美术预先刷好的图来控制的,另一种是动态的海浪,根据FFT数据算出来的

 

8.船航行的拖尾效果直接是用particle做的,先在projector space画一个mask,然后渲染的时候再贴到海面上和foam texture做运算

      

 画Mask的DP

画MASK的粒子资源

 

我基本是按照AC4文档里介绍的方法来实现的,不过在一些参数上设置有些不同,首先我FFT录了3组128*128的数据,其中一组5秒,30FPS,用来表现比较小型的海浪;一组10秒,15FPS,用来表现中大型的海浪,还有一组只有1秒,用来表现细微的法线贴图。存储上一共用掉了16MB的内存(感觉这里完全还有压缩空间,目前只写到这步),帧与帧之前我是直接在CPU里插值的,分成3个线程和主线程异步做的,测试了下对游戏效率完全不会有影响,而且物理那边取海水高度图也比较方便,不需要回读。

小的海浪                  大的海浪                 法线

它们对应生成的法线图如下

       海面MESH的法线                BUMP用的法线

先利用5秒和10秒的FFT计算出projector space的法线图,然后再计算1秒的FFT的法线图,法线图的分辨率是512*512,画的时候是带着128*128的MESH一起画的,这样比直接计算法线图边缘清晰一些。

海面MESH的分辨率我用的比AC4小,最早用的512*512,后来改成了256*512,感觉质量下降比较小,而且开销更低。顺便说下我DEBUG过的几个用类似这种算法的不同游戏的分辨率设置,战地4是512*256,watch dog是1024*1024,不过watch dog有个优化,它也是分成8*8个MESH来画的,每个128*128,但是它会事先对每个MESH做一个frustum culling(似乎是通过occlusion query来做的),只有看得见的才画,我数了一下,在最常见的平视海面的情况基本可以做到只画一半的mesh,这个优化以后有空可以做下。

Foam的生成我也做得比较简单,根据每张FFT动态计算,法线图那张不需要算,然后由一个参数来控制它们直接的混合比例,海浪越大就越偏向大的那张。具体算法看FFT海水最早那张paper (Simulating Ocean Water)

Project grid实现上注意不要让projector离海面太近,这样既可以避免近处过采样浪费顶点,还可以提高远处的mesh密度减轻次采样的问题。

还有就是海水的realtime reflection我直接去掉了,改用SSR实现的版本,性能提高了1-3ms,因为我们游戏镜头转动很小,效果差不太多。

参数上暴露给美术的主要有下面几个

FFTSmllHeightScale   5秒的FFT的高度缩放

FFTSmllChoppyScale  5秒的FFT的陡峭度缩放

FFTSmallTillingScale  5秒的FFT的纹理缩放

FFTBigHeightScale    10秒的FFT的高度缩放

FFTBigChoppyScale   10秒的FFT的陡峭度缩放

FFTBigTillingScale    10秒的FFT的纹理缩放

FFTBumpTillingScale  法线图的缩放

FFTFoamIntensity     海浪颜色强度

FFTFoamBlend       2张FFT算出的海浪的混合比例

FFTSSSSIntensity     3S颜色缩放

 

我在660GTX的显卡下做了个测试,1080P海面完全填满屏幕时开销最大,所有加起来开销大概有2ms,之前的海水大概单独渲染需要1.5ms,而且现在去掉了实时反射,这部分能省下来1-3ms,总算下来性能还提升了,而且画质也提升了。不过缺点就是现在FFT是预计算了,占掉了16MB的内存,还有就是SSR效果比起实时反射还是差了一点,尤其是镜头垂直角度变化比较快的时候。

 下图是一个测试场景,模拟了不同的风浪情况下的海面

 

 

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引