前言
现在很多游戏为了场景的表现都会加入大气散射等等的效果,甚至有些NPR的游戏都会引入大气散射,大气散射和常规渲染不一样的地方在于常规渲染都是发生在面片表面的,而大气散射隶属于体渲染的范畴
[^]: 图源 荒野大镖客2的大气散射效果
前一阵子出于某些原因看了alan那篇很知名的大气散射的文章翻译,自己又找了点文章看了看,有所收获
大气散射理论相关
首先由于光这种东西非常特殊,具有波粒二象性,可以认为是粒子也可以认为是电磁波。在大气中(真空中不会发生散射),电磁波由于和大气分子或者气溶胶发生相互作用【这里和大气分子由于本身非常微观,对于尺度小于光的波长1/10的粒子,如大气分子等,会发生瑞利散射所以这种情况下一般用瑞利散射模型去表示,气溶胶相对大气分子来说比较大,尺度与波长相当会发生米氏散射,也就是说米氏散射和瑞利散射是共存的而不是对于一种模型不同的描述】
而正是因为大气和光会发生这种交互,导致大气的渲染非常困难,实时渲染中我们通常使用单次渲染模型去描述大气散射【单次渲染模型:不考虑其他方向的光的散射造成的影响,只考虑对应的光的方向的散射,也就是冯乐乐那篇文章说的:“光线从太阳发出过、只经过一次散射被改变方向后射入我们的眼睛。”,因为一个点当前的光可能是多个方向散射过来的光的和】
[^]: 太阳光经过真空,射入大气层开始衰减(这里散射到别的方向的光在单次散射模型由于对最后结果没贡献不考虑在内)沿着原来的光路继续到P由于散射改变方向进入人眼
第一部分:出射散射
我们先把视角锁定在CP之间,先研究CP之间发生了什么,我们需要求出P点由于光照衰减最终到达的光照。
我们用一个衰减系数T来表示:
T表示的是在该路径上光的衰减比例,也就是透射率,引用冯乐乐的文章“该公式也可以被认为是零级散射(zero scattering),即不考虑任何散射事件、直接考虑经过衰减后光强。“
这段CP线段在alan的文章中被称为是出射散射部分。
聚焦CP出射散射部分
假设光线I0与大气中的粒子发生碰撞之后能量为I1,衰减比例为β,那么I1=(1-β)*I0
如果这段距离x内的介质是均匀的,剩余的能量I=I0(-β *x) 【可以参考 alan的推导】
但是由于不同高度下大气并非均匀,密度随着高度稳步增加,所以这本身是一个积分的过程。则有下面的推导
第二部分:入射散射
那么AP部分就是入射散射部分了(因为是进入人眼的部分)。
这里的S(λ,θ,h)为散射方程【这里冯乐乐文章称他为散射系数,β为海平面散射系数。但是也有许多文章称S为散射方程,β是散射系数】
散射方程S和散射系数β
散射方程S可以拆解成β(λ,h)P(θ)【相位函数P有些文章记作γ,这里全都用P代替】,而β(λ,h)代表的海拔h波长λ的波长的光线的散射系数,可以继续拆解为β(λ)ρ(h)以及相位函数P的乘积。
相位函数P代表对应角度的光的散射所占比例,ρ(h)代表海拔h于海平面的大气密度比,β(λ)代表波长λ的波长在海平面处的光线的散射系数。
在实时渲染里,我们会使用exp去近似密度比简化计算:
聚焦PA入射散射部分到最终结果
P仅仅只是路径上的一个点,我们要求出最终结果需要对其进行积分
这里我们将前面CP部分求出来的P点的能量Ip代入方程获得最终渲染方程
小结
本文到这里差不多告一段落了,这里不会提及相关的相位函数或者散射系数的公式【这并不是非常重要,有现成的公式可以抄】,主体还是对相关A点的能量如何得到做简单的一次概述,最近算是开始做实现了,等到实现效果了会再发一个实现篇。