看不懂论文代码怎么办_UE4新版大气实时渲染-论文导读

8944d113c50df8510acb4b6a76c17f39.png

简介

本文为Sébastien Hillaire在Eurographics Symposium on Rendering 2020发表的论文A Scalable and Production Ready Sky and Atmosphere Rendering Technique的导读。据论文介绍,文章中的方法已经在Fortnite和UE4中实装。

论文作者Sébastien Hillaire应该很多人都会熟悉,之前在Frostbite的部门工作,Frostbite的体积渲染的Siggraph course(Towards Unified and Physically-Based Volumetric Lighting in Frostbite)就是他做的。现在到了Epic,负责的渲染相关工作。

这篇论文的提供的思路非常棒,简单来说使用了一定程度的近似,最后达到的效果为:

  • 在保证效果跟path tracing的GT接近的情况下,比以前的预计算LUT,实时采样LUT(Bruneton08)的效率只稍微慢一点;
  • 有一定的LUT要素,但是LUT完全可以实时计算(大气参数可以实时修改,而且不是分帧更新之类的伪实时,是真的一帧搞定);
  • 在iPhone6s上可以在每帧1ms以内搞定(包括了LUT计算);
  • 做了一些近似假设,从而可以用数值方法计算所有高阶散射之和;而不是像之前的方法只计算一定的阶数就结束。在大气稀薄的情况下(高阶散射更加重要)效果提升非常明显。

总结一下,在效率、效果方面,可以说是把以前的方法拉起来全部A了。

5eddc7aa681e3d79e310f1212a638858.png
给老方法拍张遗照

当然因为采用了一定的近似,在结论部分作者也提供了一个明显偏差的情况,即大气设置非常厚重(比地球密55倍)时会出现偏差。

但是即便存在这个缺点,该方法依然是比之前的方法存在大量的优越性的。

作者官网以及paper链接:

https://sebh.github.io/publications/​sebh.github.io https://sebh.github.io/publications/egsr2020.pdf​sebh.github.io

我是第一次写这种论文导读类型的文章,欢迎指正。

前置知识

在阅读这篇论文前,读者应该对老方法有一定的认识,如果能读懂Bruneton08的论文,本篇论文就非常好理解了。另外Bruneton在17年做了一个新的开源实现,使用了C++做验证实现(相同的glsl代码通过宏定义的方式编译成C++代码),并且代码做了非常多的注释(甚至有图),看了代码就基本上不用看那篇论文了。代码被作者托管在http://github.io上,点开就可以直接看带图的注释,链接如下:

https://ebruneton.github.io/precomputed_atmospheric_scattering/​ebruneton.github.io

知乎上也有大佬对大气散射相关原理的解析,这里我推荐一篇 @Lele Feng 大佬的文章,最早的时候就是这篇文章让我明白了大气散射的原理:

https://zhuanlan.zhihu.com/p/36498679​zhuanlan.zhihu.com

此外,论文中前4章也一定程度上说明了大气散射的原理,可以作为补充。

下一章开始说明Hillaire20的内容。因为本文主要为讲解论文的创新点,因此对于大气散射的原理、计算方法等不会做过多说明。这里假设读者已经完全理解了Scattering、Absorption、Rayleigh、Mie、Henyey-Greenstein、Phase Function、Transmittance等名词的意思,并且清楚大气散射的计算方法。如果发现自己看不懂,建议先阅读上述内容。

另外,开始之前我对一些论文中的名词做出本篇论文语境下个人的解释,可能存在偏差。

Extinction Coefficient

、Absorption Coefficient
、Scattering Coefficient
:湮灭系数、吸收系数、散射系数。描述发生吸收或者散射事件的概率,与发生位置的气体浓度、性质有关。

Phase Function ,

:相位函数,描述光子在Scattering后朝着各个方向出射的概率,单位为
。论文中的
分别代表了Rayleigh散射、Mie散射和各向同性散射的Phase Function;

Transmittance,

:两个点a、b之间的透光度,通过积分路径上的Extinction Coefficient
得到;

Scattering,

:在
某点x上,各个方向的入射光朝着 某方向v出射散射强度之和。原论文中没有给这个量一个名字,但是后面会提到很多,我这里擅自叫它Scattering。并且按照Bruneton论文中的习惯记为

In-Scattering,

:在
某点上朝着 某方向到达 另一点的散射强度,比Scattering多乘了Transmittance;

Luminance,

:在路径上对In-Scattering做积分得到的光照强度,同时也是相机实际感受到的强度。

此外,

中的下标n表示了属于第几阶散射。

论文方法

论文中介绍具体方法的第5章分别讲述了:

  1. 对大气散射特性的观察结论,大意即为天空中大部分的散射现象是低频的,除了靠近地平线部分会变得高频。
  2. Transmittance LUT的计算,其实就是老方法,不提
  3. Sky-View LUT
  4. Aerial Perspective LUT
  5. Multiple Scattering LUT 重点

Sky-View LUT

在实际的渲染流程中,首先根据相机位置渲染至一张低分辨率的Sky-View LUT上,后期再合成到Render Target中。

Sky-View LUT中包含了当前相机位置接收到的各个角度的Luminance。计算时根据像素对应的视线方向直接做Raymarch得到结果(这里每一步Raymarch中的每一步采样都包含了所有阶的Scattering,如何计算看后文),论文中的例子如下图。

cf2e0d28e5734ab8cbd53f472d73c846.png

如上面提到,在靠近地平线部分大气散射会变得高频,因此UV的映射不是线性,而是靠近地平线部分会分配更多像素,具体公式在论文中写明了,这里就不复读了。

在论文中的测试,PC上只需要200*100的分辨率效果就足够。另外太阳本身是不会渲染在图里的,因为属于高频特征。会在后面再合成上去。

需要注意的是,这里跟Bruneton08已经不一样了,Bruneton08中不会有任何实时的Raymarch,都是LUT查找搞定;而这篇论文中,不管怎么样,在这一步实时Raymarch都是少不了的(其他的Raymarch步骤可以看情况跳过),这也是相比老方法会稍微慢一点的原因。

Aerial Perspective LUT

除了背景的大气,相机和远处物体之间的大气散射也是画面的重要组成部分。不过其实也是老方法了。

  1. 分割Camera Frustum(和Cluster Rendering中的分割一样),计算每个格子到Camera方向的In-Scattering和Transmittance,保存在Volume Texture中;
  2. 在Volume Texture的z轴方向上根据Transmittance累加In-Scattering,使得每一个单元格保存的是该单元格到Camera的Luminance;
  3. 在Opaque渲染之后,做一次Post Processing,采样上述的Volume Texture,对场景中的物体添加Aerial Perspective;
  4. Transparent物体渲染时在VS中采样Volume Texture添加Aerial Perspective。

Multiple Scattering LUT

这篇论文中最神奇的地方就是Multiple Scattering的计算了。在Bruneton08中,Multiple Scattering的计算需要一阶一阶网上算,比如1阶Scattering、Luminance,然后计算2阶Scattering、Luminance……

论文作者在计算Multiple Scattering时,认为高阶散射非常低频,从此出发使用了一些简化,包括:

  1. 大于等于2阶的散射,将Rayleigh散射和Mie散射视为为各向同性的散射
  2. 计算某点的大于2阶的Scattering时,认为该点周围任意一点的Illuminance与其相同

第1点的意思是,对于1阶散射,我们认为Rayleigh、Mie散射是正常的,但是在之后的阶数,我们认为相位函数对于任何方向都是相同的值

。于是我们计算Multiple Scattering LUT时,LUT的维数就少了2维。

第2点,原文的描述有点神秘,写的是“Neighbouring points”,在问了作者之后其实意思是在计算某点的Scattering时,空间中任意一点的某一阶的Scattering都视作和该点相同。因为参与计算的点需要与该点有Line of sight,从整个地球的视角来看确实是Neighboring points。这一条近似看上去是非常粗略的,但是it works。

实际流程中,Multiple Scattering LUT的计算可以一个pass输出到一张32*32的2D LUT完成。只需要2D的原因是因为上述简化中我们使用了各向同性Phase Function,不需要存储相机跟光照方向的关系,只需要存储不同高度、不同光照角度的情况即可。

在pass中,论文中提到,首先计算

,这里的
是在LUT当前像素代表的点上,对整个球面做Phase Function * Luminance的积分得到,按照本文开头提到的习惯记为
。具体计算方式公式为如下:

其中

计算部分的
为地面的反射光,
为阳光到达x点的照度。这里的
是一个单位值的阳光照度,实际的照度数值是在最后乘上去的。

转移函数

第二步,在上述计算完毕后,计算当前像素的Transfer Function

(不是真的Function,对于当前计算的像素来说是一个固定的数值),可以将
转换为更高阶的Scattering。个人认为这是这篇文章中第二Amazing的地方。论文中直接给出了Transfer Function的计算方法:

使用

,有:

这里可能会对

的计算稍微感到迷惑。其实这是在上述1、2点简化的情况下,将原本的计算散射的式子做了化简的结果。我们可以简单地推导一下。首先是传统的
的计算方法:

根据简化1、2,我们认为在计算当前像素时,

在任意一点都是固定的数值,
式可以改写为:

,再代回去(6),两边同除
,将
替换为
,得:

细心的读者可以发现,相比(2)式,(7)式中省去了地面反射。这里我咨询了作者,作者表示确实是忽略了多重散射照射到地面形成反射的贡献。不过保留的话也没办法化简出这么一个

。好在这一部分贡献并不是很多,对最终结果影响不大。

多重散射结果

有了

,我们就可以计算任意
了。接下去就是论文第一Amazing的地方。

根据数学公式,因为

小于1.0(论文中直接说的,我没有算过),我们可以直接得到无穷阶数的
之和:

最后,就可以将

写入二维的LUT中保存了。之后采样这张LUT,就可以得到2阶及以上阶数的散射之和。

52aa2d3fc71b311c5b753ffe083ff288.png
论文中的Multiple Scattering LUT的例图

论文中提到,在PC或者iPhone6s上,该LUT的计算都是在64个方向上做Raymarch,每个方向20个step得到,乍一看很多,但是LUT大小只有32*32,问题不大,论文后面给出的测试iPhone6s上也只消耗0.12ms。

最终计算

根据上文,我们可以得到任意点的所有阶数的Scattering之和,包括一阶Scattering和高阶Scattering之和(

为太阳光对该点的直接贡献):

在计算某个方向上的Luminance时,一路积分过去就行。这也是上文中Sky-View LUT中每个像素的Luminance计算方法。

到此整个算法的流程就已经讲完了。下图是论文中的效果图,包括了和Path tracing、Bruneton的对比。

915a55ba72f5251bc2586db6e32f14ae.png

5a98a182297b1e1e269d84366c24f598.png

总结

这篇论文中,作者通过做出一些对结果影响不大的简化假设,大幅度地降低了Multiple Scattering计算的消耗,并且使用数值方法计算无穷阶Scattering之和变为可能。这毫无疑问是需要非常多的实践经验、数学直觉和大胆尝试才能做到的,让人不得不佩服。

此外在工程方面,这篇文章也是尽可能压缩了各个LUT的大小以得到最好的效率,包括200*100的Sky-View LUT、32*32的Multiple Scattering LUT等等。尽管最后写成论文的就是表中的几个数字,但是这些数据毫无疑问是经过了大量试验得到的。最终在iPhone6s上能跑到1ms以内更是amazing。并且不需要任何的3D贴图,就在VS-PS里直接算就完事儿了。

本文只是挑选了我认为最具亮点的一部分来讲。论文原文中还有许多细节内容,如根据高度自动切换Raymarch方法和Sky-View LUT等,建议有兴趣的读者详读一遍。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值