美文网首页
体积效果参考文章

体积效果参考文章

作者: 离原春草 | 来源:发表于2020-07-03 22:53 被阅读0次

    如果太阳光线被一个处于包含浓密气体粒子(molecules & aerosols)空间的物体所遮挡住的话,在这个物体边缘会出现从太阳位置出发的射线光束集,这种现象有很多名字:crepuscular ray(黄昏之光),sunbeams,sunbursts,star flare,god rays以及light shaft,中文就比较统一,通常称之为体积光(由于其表现形式呈现出一种对光照可见体积的强烈暗示而得名)。

    体积光是一种大气散射的效果,其他与大气散射相关的效果有1. 体积雾; 2. 体积云。这些效果的计算方法其实大同小异,都是通过raytracing的方式对视线射线进行raymarching,对每个采样点计算对应的大气散射数值,并将这些数值累加起来得到最终的结果。

    出于总结归纳以及后续查阅方便的考虑,这里会罗列一些阅读过的,与体积相关的,觉得有启发意义一些材料(出于偷懒的目的,材料未做任何排序,因此无需按照先后顺序进行阅读,这个排序也不代表重要性以及依赖关系):

    1. 游戏开发相关实时渲染技术之体积光

    本文列举了体积光在游戏中的技术演变历史,按照难易程度包含了如下的一些实现路径:
    1.1 Billborad特效实现:噪声+Mask实现基本效果,通过UV动画+粒子进行增色
    1.2 后处理径向模糊算法(具体可以参考这篇文章):通过对天空(未被物件遮住的区域)进行累加,并沿着路径进行拖尾模糊的方式来模拟光线在物体边缘上产生的体积光,方案虽然简单,但是其中的问题倒是不少,性能上应该是比较省的,可以考虑用在低端机上面。这种方案的不足在于当光源处于相机之外时,方案就不再可用了。
    1.3 真实感体积光实现方案:中间介绍了目前各大厂使用的raytracing体积光方案的基本原理,并给出了简要的原理说明以及相关的优化策略,虽然比较简陋,不过作为一篇科普文章来说基本上是足够了。

    1. [GPU Gems 2]Accurate Atmospheric Scattering

    这篇文章给出了一种用GPU实现的O'Neil大气散射算法,并通过曲线模拟的方式对算法做了进一步优化,移除了LUT的采样操作,使得可以在ES2.0之类的低版本API上完成对大气散射的模拟实现,如果有低配版的大气散射实现需求,可以考虑参考这个方案。

    1. Rendering Outdoor Light Scattering in Real Time, Preetham & Hoffman 2003

    这是Preetham & Hoffman在2003年发表的一篇关于大气散射原理分析与实时渲染简化方案的文章,其中详细推导了大气散射的计算公式,并根据实际情况提供了一套可行的简化实施方案,如果想要应用逼近真实的大气散射效果,这个论文是一个不错的入门教程。

    1. 【GDC 2014】Taking Killzone Shadow Fall Image Quality Into The Next Generation - Valient

    《杀戮地带:暗影坠落》在GDC2014中给出了他们的体积光实现方案,在他们的方案中,需要着重注意的是他们使用的采样sample的排布方式,通过随机化采样step的方案,他们用8个采样点实现了与128个等长step采样点相近的质量,此外体积光与TAA之间的结合方式——隔帧切换一套step数值——也值得关注一下。

    1. [EUROGRAPHICS 2009] Real-time Volumetric Lighting in Participating Media

    这篇文章给出了与传统的离线方案不同的运行时体积光计算方案,通过忽略对效果影响不大的多次散射光照结果,而将重点集中在单次散射上,极大降低了计算的消耗,使得运行时方案称为可能;此外还通过将利用shadow map的结果来对采样点的可见性进行修正以增强效果的真实感(否则得到的就是雾效而非体积光了)。
    文章给出了光照inscattering计算的具体公式以及实现的shader源码(或者伪代码),在实施相关方案的时候可以拿来参考一下。
    此外,这篇文章还给出了一个interleaved采样方案用于进一步降低采样消耗,这个方案是基于相邻像素之间相近的采样点的结果接近一致的观察结果提出的,因此可以考虑将一套采样点均分到多个像素(假设选取MxM个相邻像素)的采样上,并对这些相邻像素的采样结果进行累加来作为当前像素的采样输出结果。通过这种方式可以将采样消耗降低为原来的1/(MxM)。

    1. 【Siggraph 2019】Creating the Atmospheric World of Red Dead Redemption 2

    RDR2也是只针对单次散射进行体积效果的计算,且给出的是一套针对全材质的统一光照模型,能够实现体积效果尺寸的自适应,且能够在室内与室外效果之间做到自然过渡。
    前面说过,不论是体积光,还是雾效或者云层,实际上都可以看成是光照与粒子交互后的散射效果,都是通过ray marching来进行计算,因此是有可能通过统一的模型来进行模拟的,RDR2这边首次尝试将这些效果的实现方式进行统一,这种方式方法值得肯定与借鉴。
    6.1. 云层渲染:
    6.1.1 使用两个通道的云层贴图(CloudMap)来表示两个不同高度的云层密度,云层贴图是根据天气以及一天的时辰来进行更新的,这个数据的生成有噪声贴图的参与
    6.1.2 使用一个一维的云层高度贴图(Cloud Height LUT)来表示云层的形状,这个贴图对应于不同高度的云层形状类型(cumulus,stratus等),考虑到不同天气下的云层应该具有不同的形状,因此这里会将多个不同天气下的LUT集合成一张2D的LUT。
    6.1.3 云层的高频细节通过云层密度贴图跟云层高度贴图通过一定的算法计算得到
    6.2 雾效渲染
    全局雾效渲染通过一张可以根据天气以及TOD进行更新的FogMap来实现,FogMap三个通道分别对应于fog start height, falloff distance以及fog density。
    局部雾效通过Fog Volume(手工放置,或者挂接在粒子系统上)来实现

    1. 【Siggraph 2015】Real-Time Volumetric Cloudscapes of Horizon Zero Dawn

    这是《地平线零》的体积云实现方案。
    在这个方案中,云朵的建模是通过对噪声进行叠加与计算完成的,类似于Fractal Brownian Motion(简称FBM)方法,不过使用的是不同的噪声,原方法中使用的Perlin噪声得到的结果真实感不够强烈,这里添加了一种是菜花一样的Worley噪声来对原方案进行修正,最终就是需要用到Perlin-Worley噪声来完成云朵的建模。为了降低贴图采样频率,噪声数据最后会存储到三张贴图中:其中两张3D贴图(第一张贴图包含四个通道,对应于不同频率的Perlin-Worley噪声数据,用作云朵的形状建模;第二张贴图三个通道,对应的是不同频率的Worley噪声,用作云层的细节建模),一张2D贴图(对应的是3个通道的curl噪声,用于模拟涡流效果)。
    在FBM方法中,会需要用到高度梯度数据来对噪声的细节进行修正,这里为了能够模拟最重要的三种云效,这里直接上了三张高度梯度贴图来对不同云效进行处理。
    云层建模完成后,下一步就是要在上面实现对应的光照效果,这里主要需要对三种效果进行模拟:
    A. 太阳光散射
    B. 观察者面向太阳时的云层银边
    C. 观察者背向太阳时的暗边
    这篇文章还通过图形的方式给出了光照在云层/大气中的交互过程,并给出了对应的模拟公式以及不同公式作用下的效果,可以看得出来作者对整个过程的理解是非常深刻的。
    此外,原文作者还在GPU Pro 7中公布了其整套方案的实现细节,具体可以参考这边给出的另一篇分享:【GPU Pro 7】Real-Time Volumetric Cloudscapes

    通用tips

    1. 为了降低消耗,体积光通常是在半分辨率RT上进行计算[4]
    2. 在raymarching中,使用随机step采样点,在上采样之后,有助于移除regular采样点导致的pattern[4]
    3. 有条件(性能足够)的情况下,可以通过添加粒子效果来为体积光进行增色[4]
    4. 通过TAA类似的reprojection方案来增强显示质量[4]
    5. 通过interleaved sampling方案将采样分散到多个像素上执行,从而进一步降低渲染消耗[5]
    6. 采样step在非关键区域(比如穿出大气层,或者云层之外)可以加大步长来降低消耗[7]
    7. 采用分帧更新的方式来降低采样消耗(将屏幕空间分成NxN个像素组成的blocks,之后对于每个block,一帧只更新其中的一个像素,其他的像素通过reprojection采用上一帧的结果)[7]

    相关文章

      网友评论

          本文标题:体积效果参考文章

          本文链接:https://www.haomeiwen.com/subject/lfzeqktx.html