写在前面
前两天学习并整理的大气散射基础知识:【Unity大气渲染】关于单次大气散射的理论知识,收获了很多,但不得不承认的是,这其实已经是最早的、90年代的非常古老的方法了,后来也出现了一些优化性的计算思路和方法。因此,我打算先不急着跟各种教程在Unity中实现大气散射,而是再花时间来看看最近的游戏是如何去实现大气渲染的:06.游戏中地形大气和云的渲染(下) | GAMES104-现代游戏引擎:从入门到实践
接下来就跟着GAMES104讲地形大气和云渲染的部分学习并做简单的记录,设计到之前没提到的Mie散射也只选择直接截图PPT的方式记录啦!毕竟对于做作品来说,之后实现出来才是重要的~
当然,May佬的百人计划在今年8月份也有一期关于大气散射的讲解,这里也放上课程的链接以及对应的超长内容整理的知乎文章链接:
【百人计划】图形 4.6 雾之 大气散射_哔哩哔哩_bilibili
游戏魔法编程:unity实现完整大气散射 - 知乎
话不多说,开始今天的学习!
1 理论知识的查漏补缺
1.1 天空组成
天空(球、离我们很远)与云(非常visible的、离我们很近)是两个最重要的元素。其实还有个东西Fog,但雾效并不只是大气,更多的是可控性的效果,所以这里把雾和天空/云分开来考虑。
3A的标准在手游实现将会非常坑爹hhh,另外我想实现的是风格化天空盒,会参考更多以精简计算。
1.2 Mie散射
太阳、大气中的气体分子与气溶胶分子,于是Rayleigh散射和Mie散射就被提出来了~Rayleigh散射波长越短散射的越厉害,而Mie散射对所有波长光一视同仁。
g=0的时候,跟Rayleigh散射差不多;但g>0的时候,下图右边所示就会会更加向前。
生活中的Mie散射
Mie散射就是一些日出日落halo。
1.3 多次散射
真实世界的散射绝对不止一次散射,一定还有多次散射!听上去很麻烦,但实际上目前的3A游戏多需要考虑多次散射。如下图右侧考虑多次散射的才是符合真实大气的样子:
1.4 Ray Marching
单次散射其实就是RayMarching(沿着视线不断向下积分,算是一种暴力解法吧),实际上计算所有的大气效果都是用Ray Marching这个思路。
2 新的东西
2.1 T项的LUT
大气中的光学现象其实就只有两个部分:Transmittance&Scattering,这俩分别对应着我上一篇文章中的衰减系数T项和散射系数S项,这里介绍了一种很机智的算法计算Transmiitance——Precomputed Atmosphere Scattering,预计算。
(插播一点,这里也可以看看游戏魔法编程:unity实现完整大气散射 - 知乎后面部分对LUT的介绍)
这里最重要的思想是参数化——对于海拔高度为h的点,用视线与天顶角度去计算T项,从这一点一路走到大气层边界,记录边界处的Transmittance值。
那我怎么去用这个LUT表?——去查!怎么查?如下左图,假设我们想知道Xm位置的山脉的Transmittance的值,查1(从人眼位置Xv出发到边界的值);查2(山脉Xm到边界的值),查1/查2就是当前Xv位置看Xm位置的Transmiitance的值了。
2.2 单次散射的LUT
选择海拔为h的点,向大气层边界去看(打出一条射线),这个时候看向的方向到天顶的角度1,这个时候太阳到天顶的角度2,看向的方向和太阳之间的角度3,这三个角度其实就得到了一个立体角!那么,这三个角度组成的立体角其实就能表达当前海拔高度所有视线方向沿途的Transmittance值,再从不同海拔通过RayMarching的方法一下获取一堆数据,这样一来就足以在一个3D Texture中将单次散射所有的光(4D数据)全部存下来了。
2.3 多次散射的LUT
我们用前两次的两个结果再做几次积分(其实3-4次已经够用了),就能得到多次散射的结果。
2.4 问题
预计算很费计算,手游上不太星。
刚开始是蓝天白云->下雨的效果的过渡,这个过渡需要很流畅;同时我们的美术会需要调整一些参数,这中间由于有预计算,会很麻烦。
2.5 更前沿的方法
这里是课程最后提到的UE采用的方法,是在论文A Scalable and Production Ready Sky and Atmosphere Rendering Technique的基础上实现的,具体可以看看这篇文章:UE4新版大气实时渲染-论文导读 - 知乎 (zhihu.com)
仅作简单的记录:
对于一个分子,可以假设四面八方光是均匀的,那就算两次,知道一个差值,就知道后来所有的值的百分比了!
既然世界需要动态,那省事儿创造更流畅的画面才是关键,那假设人不变(干掉h),假设太阳不变(干掉太阳的那个角度),