雾效在游戏的作用:
在大型的3D项目中都会考虑使用雾效调节画面色调、增强游戏纵深感,雾效又可细分为高度雾、体积雾、线性距离雾。
下面是怪物猎人世界的场景雾效
雾效原理:
单次散射(single scattering):
首先我们需要了解单词散射的大气渲染模型,即光线从太阳发出过,经过一次散射被改变方向并衰减过后射入人眼。
光经过大气中的粒子,散射衰减,而大气中又很多不同种类的大气粒子,一般在大气渲染模型中把它们分为两大类:一种是小分子,例如氮气和氧气分子,另一种是大粒子,例如各种尘埃粒子。
小分子:指的是大小远小于光线波长的粒子,小分子对光的散射在前后方向上分布比较均匀,通常会使用瑞丽散射(Rayleigh Scattering)来表示渲染模型,由于这些分子大小比波长还要小很多,因此光的波长也会影响瑞利散射的程度。
大粒子:指大小远大于光线波长的粒子。大粒子在发生散射的时候会把更多的光散射到前向,通常会使用米氏散射(Mie Scattering)来表示渲染模型,由于这些分子大小比波长大很多,波长几乎可以忽略,因为我们认为米氏散射跟光线波长无关。
下面以Rayleigh散射为例,解释S(λ,θ,h)的含义。这里直接给出公式,在Rayleigh散射模型中,散射到θ方向上的比例为:
其中,λ是光的波长,n是粒子折射率,N是海平面处的大气密度,ρ(h)是高度h处的相对大气密度(即相对于海平面的密度,可以理解成h处真正的大气密度与海平面处大气密度的比值,因此它在海平面处值为1,随着h增加不断减小),我们一般会使用指数函数对它的真实曲线进行数学拟合(是一种近似拟合,不要和后面提到的指数函数弄混):
其中,H是大气的整体厚度。
可以看出Rayleigh散射大致和波长的4次幂的成反比,波长越小(越靠近紫光)的光被散射得越厉害。所以白天的时候天空为蓝色,因为蓝光在大气里不断被散射,黄昏的时候天空会变红,因为相比于白天,阳光此时要穿越更厚得多的大气层,在到达人眼之前,大多数蓝光都被散射到其他方向,所以剩下来的就是红光了。
以上内容参考冯乐乐的雾效专题:https://zhuanlan.zhihu.com/p/36498679
以下内容根据上面内容推导:
由于我参与的是手游项目,这么复杂的雾效模型在手游上肯定是行不通的,我们需要对其拟合并用一些通俗易懂的语言解释。
上面的公式中有很多游戏中无法判定的数据,比如光的波长λ,粒子折射率n,海平面处的大气密度N,我们把这些数据合并成常量A来表示,称之为雾浓度。
因此可以拟合为:
这个公式可以理解为,雾效从海平面向天空衰减,并乘以自定义的雾效浓度数据。
同理,水平方向上的雾效也可以用这个公式来处理,只不过h和H替换成摄像机与物体之间的距离d和D,最后我们得到这个公式。
Unity中的实现公式可以参考下面两篇文章,具体细节由于项目还未上线,暂时无法提供。
参考:http://iquilezles.org/www/articles/fog/fog.htm
参考:https://www.alanzucconi.com/2017/10/10/atmospheric-scattering-1/