前向渲染中的雾
到目前为止,我们一直把光线看作是在真空进行传输的。当你的场景是设置在太空里的时候,这可能是准确的,但是在其他情况下,光线必须穿过大气层或是液体。在这种情况下,光线可以被吸收、散射和反射到空间的任何地方,而不仅仅是撞击固体表面。
准确地渲染大气干扰需要昂贵的体积方法,这是我们通常负担不起的。取而代之的是,我们将满足一个近似方法,它只依赖于一些恒定的雾参数。它被称为雾,因为这种效果通常被用于雾状大气。由清晰的大气层造成的视觉扭曲通常是如此的微妙,以至于在较短的距离内都可以忽略它们。
标准雾
Unity的光源窗口包含了一段场景中雾的设置。在默认情况下它是禁用的。当被激活的时候,你会得到默认的灰色雾。但是,这只适用于使用前向渲染路径渲染的对象。当延迟模式处于激活状态的时候,在雾的设置区域就会提到这一点。
![](https://i-blog.csdnimg.cn/blog_migrate/c4012d73a9872ee6c79495fac8aaacb7.jpeg)
默认的雾处于激活状态。
稍后我们将讨论延迟渲染模式中的雾。现在,让我们把注意力集中在前向渲染的雾上。为此,我们需要使用前向渲染模式。你可以更改全局渲染模式,或者强制主摄像机使用所需的渲染模式。因此,设置摄像机的渲染路径为前向渲染模式。现在让我们禁用高动态光照渲染渲染。
![](https://i-blog.csdnimg.cn/blog_migrate/e698d58e7112a6f58e0fc61e88e88e19.jpeg)
使用前向渲染模式的摄像机。
创建一个小的测试场景,就像在平面或立方体上的几个球体一样。使用Unity的默认白色材质。
![](https://i-blog.csdnimg.cn/blog_migrate/62a418e111d4cdc15b9176807cbe9aa5.jpeg)
不明显的雾。
环境光照设置为默认强度1,你会得到一些非常明亮的物体,而且没有明显的雾。
线性雾
为了让雾更加的明显,把它的颜色设置成黑色。这代表了一种吸收光线而不会散射的大气,就像浓黑的烟雾那样。
将雾的模式设置为线性。这和现实的情况不相符,但是很容易配置。你可以设定雾开始有影响的距离,以及它进行完全遮挡的距离。在中间雾的强度线性增加。这是用视图中的距离来测量的。在雾开始影响的距离之前,能见度是正常的。过了这段距离,雾将逐渐模糊物体。最后,除了雾的颜色外,什么也看不见。
![](https://i-blog.csdnimg.cn/blog_migrate/8a0a41c0d42e9334ae1a3f277c8c9658.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/3cd7fd87aad0c7660d3150a101965ae9.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/147adb3589d7660f8c303888db988f49.jpeg)
线性雾。
线性雾的因子是通过函数来计算的,其中c是雾的坐标,S和E是雾开始和结束的位置。然后将这个因子限制在0-1的范围内,并用于在雾和物体的渲染颜色之间进行插值。
![](http://upload-images.jianshu.io/upload_images/7240015-5d76aa1f8ad21768.png)
为什么雾不会影响到天空盒?
雾的效果调整了前向渲染物体的碎片颜色。因此,它只影响那些物体,而不会影响天空盒。
指数雾
Unity支持的第二种雾模式是指数雾,这是一种更接近于雾的近似。它使用函数,其中e是欧拉数,d是雾的密度因子。这个方程永远不会得到零,不像线性版本。将密度增加到0.1,使雾看起来更靠近镜头。
![](https://i-blog.csdnimg.cn/blog_migrate/8ff4f7fc717ff85ae6acda313507d385.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d41991780175e0e64ef4aa1944c95822.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/816d5bc23b0adf3191869077bb0faaa5.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/d3cbaa9ddc7e15db33c6925116299b9d.jpeg)
指数雾。
指数平方雾
最后一种模式是指数平方雾。这就像指数雾,但是使用了函数,这样就能在近距离产生较少的雾,但是它强度增长的速度会更快。
![](https://i-blog.csdnimg.cn/blog_migrate/47834acb5bbf19688bc66efb688c13bd.png)
![](https://i-blog.csdnimg.cn/blog_migrate/43d599aa36dedb43316264618902ed0d.jpeg)
![](http://upload-images.jianshu.io/upload_images/7240015-09d8a3be510750d5.jpg)
![](https://i-blog.csdnimg.cn/blog_migrate/ce64ce67994c245a53be12add59bd67d.jpeg)
指数平方雾。
添加雾
现在我们知道了雾是什么样的,让我们把对它的支持添加到我们自己的前向渲染过程中。为了便于比较,将一半的物体设置为使用我们自己的材质,而剩下一半的物体则使用默认的材质。
![](https://i-blog.csdnimg.cn/blog_migrate/a67eff2b8c393e1ed3c5cc74e577a6e9.jpeg)
我们的材质在左边,右边是标准材质。
雾模式由着色器关键字控制,因此我们必须添加一个多编译指令来支持它们。 有一个预定义的multi_compile_fog指令,我们可以用于此目的。 它为FOG_LINEAR,FOG_EXP和FOG_EXP2关键字带来了额外的着色器变体。 将这个指令添加到两个前向渲染通道里面。
#pragma multi_compile_fog
接下来,让我们在“MyLighting”中添加一个函数,以将雾应用到我们的片段颜色。 它将当前颜色和内插器作为参数,并应返回应用了雾的最后的颜色。
float4 ApplyFog (float4 color, Interpolators i) {
returncolor;
}
雾的效果是基于视距,等于相机位置和片段的世界位置之间的矢量的长度。 我们可以访问这两个位置,所以我们可以计算这个距离。
float4 ApplyFog (float4 color, Interpolators i) {
floatviewDistance = length(_WorldSpaceCameraPos - i.worldPos);
returncolor;
}
然后我们使用这个信息作为雾密度函数的雾坐标,它由UNITY_CALC_FOG_FACTOR_RAW宏计算。 这个宏创建了unityFogFactor变量,我们可以使用这个变量在雾和片段颜色之间进行插值。雾的颜色存储在unity_FogColor中,它在ShaderVariables中定义。
float4 ApplyFog (float4 color, Interpolators i) { </