在U3D中实现战争迷雾

原文地址: 在U3D中实现战争迷雾
一、 简介
RTS 类型的游戏经常用到战争迷雾。一开始整个地形被迷雾遮蔽,只有Viewer 的周围一定范围可见,随着Viewer 的移动,未探索的区域变成了可见。
二、 实现方法
本人之前也没有实现过战争迷雾,但是一提到战争迷雾,我的第一反应是用RenderTexture 来实现,几乎所有运算都是在屏幕空间中进行,绘制出迷雾Texture 后,再用Projecter 将迷雾Texture 投射到整个场景,有点类似GPGPU 的思想。方法的主要步骤如下:
1 、创建一个RenderTexture (称为FogOfWarRTT )用于绘制(刷出)迷雾。
2 、设置当前RenderBuffer FogOfWarRTT ,并且不清除该RenderBuffer ,这就使得刷上去的迷雾不会被清除掉。
3 、创建一个Projecter ,用于将FogOfWarRTT 投射到场景。
三、实现细节
   知道大致过程后,还有一些细节问题需要讨论,如下:
1、    创建好FogOfWarRTT 后,应该怎么刷上迷雾呢?换句话说,当Viewer 在场景中移动时,怎么样才能擦除FogOfWarRTT 上黑色的迷雾?我们只是知道Viewer 的世界坐标ViewerCenter ,而在FogOfWarRTT 上刷迷雾时,用的是屏幕空间的UV 坐标,也就是说,怎么将ViewerCenter 转化为屏幕空间的UV 坐标?如下:


其中m_projMatrix 是投影矩阵,m_viewMatrix 是视图矩阵。这两个矩阵是怎么来的,下面再讨论。
2、    创建Projecter 的视图矩阵ViewMatrix

创建视图矩阵的代码如下:



其中  look up right pos 都是世界坐标系下的。  
3、    创建正交投影矩阵 ProjMatrix


Projecter 投射 FogOfWarRTT 用的是正交投影矩阵。看到这里读者可能会有疑问, Projecter 不是已经有投影矩阵了吗,直接用它的就好了呀,干嘛还这么费劲再自己编写呢?  Projecter 的正交投影空间 是方形的,对于一些在 XZ 平面是比较狭长的场景, Projecter 的正交投影空间包裹得就不是很严密,这就会造成 FogOfWarRTT 大量的像素浪费,也就是说 FogOfWarRTT 有相当大的一部分像素是没有用的,下面这图描述了用 Projecter 的投影矩阵在 FogOfWarRTT 上刷迷雾的缺陷。  

创建正交投影矩阵的代码如下:

其中v3MaxInViewSpace v3MinInViewSpace 分别是场景区域在Projecter 的视图空间中的最大坐标点和最小坐标点。
四、 绘制迷雾。

有了Projecter ViewMatrix ProjMatrix 后,最后一步就是绘制迷雾,下面是绘制迷雾的PixelShader 的代码:

 half4 _ViewCenter; //x,y Viewer 的世界坐标转换成的屏幕空间UV 坐标,z 刷子的半径,w 刷子边缘柔和程度
  
half  _BufferAspect; // 场景矩形区域的横纵比
  
half  _FogDensity;  // 迷雾浓度
sampler2D _NoiseTex; //Perlin 噪音,对圆形的刷子进行抖动,使之变得不太规则。

图片:例子.jpg


你可能感兴趣的:(Unity,游戏开发)