【Unity】FOV战争迷雾

版权声明:本文为博主原创文章,未经博主允许不得转载 https://blog.csdn.net/mobilebbki399/article/details/78444375
战争迷雾作为一种常用的游戏效果,被广泛的运用在RTS游戏和最近火热的moba类游戏中,在游戏中需要不断的进行探索和侦察来打开更多的视野区域,或者用来显示友方的位置,或者是躲避敌方等。

常见的战争迷雾主要有两种:
第一种是比较纯粹的将周围指定半径内的区域全部认为可见,即以整个圆形范围来表示可见的区域。由于玩过的RTS比较少,记不清哪些游戏使用的是这种方式了,这里随便找了张图片,大致是这样的效果:



这种方式的实现相对比较容易,网上也有相当多的unity实现这类战争迷雾的方案。但这种实现方式存在一个缺点,就是它的渲染是基于玩家视角(上帝视角)而不是角色视角的,即如果角色此时周围存在森林或一座小山或是高墙,对于正常情况,角色应该是看不到被障碍物遮挡的后方的物体的,但使用这种方式会将整个原形范围内的视野都渲染出来。

第二种方式应该是moba和大部分3DRTS游戏中比较常见的实现了,这种方式需要计算出角色实际可见的视野区域(Field of Vision),这样可以剔除掉角色本来应该看不见的区域,如下:


红色线段夹角内即为角色不可见的区域

因此我们首先要关心的就是如何生成可见区域:
1.生成表示地图信息的二维数组:
这一部分主要就是生成一个记录整个场景障碍物信息的二维数组(地图格子),具体可以是预计算生成数据(比如对于场景障碍物信息不会发生变化的情况),或者游戏运行时动态计算(比如RTS类游戏如果建造了建筑,或者砍掉了一片森林需要修改地图障碍数据)。
2.计算视野区域:
这一部分我的做法是从角色位置开始,在指定视野范围内先找出最近的障碍物点,然后从角色位置到障碍物点位置的方向,可以计算出所有不可见的格子(根据夹角),如下演示过程:


考虑到如果场景中存在许多角色需要计算视野,可能会在主线程占用过多CPU计算,因此这里使用了线程池,在子线程计算FOV

3.生成战争迷雾mask贴图:
一般的战争迷雾效果我们可以看到都不是实时更新的,因此我在每隔一定时间才会从FOV数据生成mask贴图,且只有当角色的地图格子位置发生变化才计算一次fov,但这样可能导致迷雾mask的更新出现间歇性,因此我需要缓存上一次更新的数据,每次更新完mask,通过插值的方式来做一个渐变效果。
这里我使用了mask贴图本身的颜色通道来作为上一帧缓存,如下,R通道将每一次更新得到的可见区域叠加,来作为已探索区域,G通道为当前更新的可见区域,B通道为上一次更新的可见区域:




R通道:叠加每次的可见区域,用于渲染已探索区域:


G通道:当前的可见区域:


B通道:缓存上一次更新的可见区域:


4.模糊处理:
这一步可以省略,但如果希望得到更模糊柔和的迷雾,可以做这步操作。

5.投影战争迷雾:
这是整个效果的最后一步,需要将生成的战争迷雾mask纹理投射到场景中,你可以用普通投影机或者直接将渲染完的战争迷雾纹理投射到场景物体的shader中(像shadowmap一样,前提是需要修改场景物体shader),这里使用的方式是屏幕空间投影,需要计算出从世界空间从上往下投影的投影矩阵。

最终效果:




Git地址请到我的博客原文查看: http://www.lsngo.net/2017/11/04/unity_fovfogofwar/

猜你喜欢

转载自blog.csdn.net/mobilebbki399/article/details/78444375
FOV