全局光照

4.1k words

效果

原神实时全局光照开关对比

环境光遮蔽

当光照缺乏方向变化,无法展现物体细节时,环境光遮蔽可以提供对于物体形状的视觉暗示
irradiance会随着表面位置的变化而变化,Ka确实由表面位置所决定,这样所得到的结果会更加真实,尖锐折痕处的Ka值较低,表面位置会显得较暗

可见性和obscurance

相互反射

预计算环境光遮蔽

动态计算环境光遮蔽

屏幕空间方法

使用环境光遮蔽进行着色

定向遮蔽

单独使用环境光遮蔽可以极大地提高图像的视觉质量,但毕竟是一个简化的模型。处理大面积光源的时候,所给出的可见性近似很差,更不用说较小的光源或者精确光源。
主要是用于为大面积光源或者环境照明提供遮挡效果,这些方法可以生成柔和的阴影,并且由近似可见性所引起的瑕疵也不是很明显。还可以在常规阴影技术无法运行的时候,提供一些遮挡效果,例如凹凸贴图细节产生的自阴影,以及超大场景的阴影,导致阴影贴图没有足够的分辨率。

预计算的定向遮蔽

动态计算的定向遮蔽

使用定向遮蔽进行着色

漫反射全光光照

预计算传输

假设场景中的几何物体没有发生变化,只有光照发生了变化,那么可以对光线和模型的相互作用进行预计算。物体之间的影响(相互反射或者次表面散射),可以预先进行一定程度的分析,并将结果存储下来,不需要对实际的radiance进行操作。接受入射光线,将其转换为整个场景的radiacne分布(PRT)。
这类技术具有明显的运行时间开销,当在屏幕上显示场景时,需要计算特定光照环境中的radiance。为了实现这一点,需要将一定数量的直接光源注入到系统中,然后应用传输函数来将其传播到整个场景中。
可以用球谐函数来描述它,使用一定数量的构建光源来描述直接光照,就可以对场景如何被这些光源单独照亮进行预计算。
可以使用PCA(主成分分析)技术来对整个集合进行分析。减少每个点所需要的内存量。(LDPRT)

预计算辐照度全局光照(PRTGI)从理论到实战 - AKG4e3的文章 - 知乎

通过球谐函数近似存储光照信息

使用球谐函数来近似存储光照信息是一种常见的方法,它可以有效地减少存储开销并提供较高的渲染质量。球谐函数是一组基函数,可以表示在球面上的函数。在光照领域,球谐函数被用来近似表示给定方向上的光照信息

计算球谐系数
使用光照环境或预计算的光照数据,通过采样一组方向并计算每个方向上的光照颜色。对于每个方向,将光照颜色与球谐函数进行内积运算,然后将结果累加起来。通过对多个方向进行采样和计算,可以得到一组球谐系数,用于近似表示光照信息。
存储球谐系数
将计算得到的球谐系数存储起来,可以使用数组或纹理等数据结构。由于球谐函数具有良好的性质,通常只需要存储较少的系数即可获得较好的近似效果。
重建光照信息
在渲染时,对于给定的方向,使用球谐函数的系数和对应的球谐函数进行内积运算,即可得到该方向上的近似光照颜色。通过对球谐函数的加权组合,可以还原出整个光照环境的近似颜色。

使用球谐函数近似存储光照信息的好处在于,它可以使用较少的系数来表示光照信息,从而大大减少了存储开销。而且球谐函数具有平滑性质,可以提供较为准确的光照近似结果。然而,球谐函数也有其限制,例如无法捕捉高频细节和强烈的光照变化,因此在某些特定场景下可能需要其他更高级的近似方法

方案思路

场景的几何信息
通过探针去获得CubeMap,为了节省计算,只存储指定数量的 Surfel 数据
实时光照计算
运行时计算每个 Surfel 收到的 Radiance,为了计算屏幕像素的光照,而不是单个 Surfel,需要将 Surfel 代表的环境光照信息编码到 Probe 上,像素着色时访问 Probe 得到其周边环境光照信息
https://zhuanlan.zhihu.com/p/541137978?utm_id=0 中, 在Probe的位置烘焙3张128x128的Cubemap存储这些信息,再从probe随机发射64条球形射线,将3个Cubemap采样到的信息作为Surfel存储下来。获取Surfel后,再将一定的范围内(4米)的Surfel索引存为一个Brick,最后再将相应的Brick索引存到Probe里. Surfel 数据可能存在相同,需要求平均与合并, 因为Surfel的精度为1米,而很多物体的大小远小于1立方米,因此在Surfel的精度范围内可能出现差异巨大的法线信息(例如很薄的墙壁),而法线背对某个Probe的Surfel是不会对这个Probe产生贡献的,所以需要在Surfel和Brick的精度范围内把法线差异巨大的各个单位互相分离
阴影的计算,根据世界空间坐标采样ShadowMap结果获取阴影信息,但是不在视锥内产生产生阴影的物体会在绘制ShadowMap时被剔除,因此采样到的Shadow信息不准确,需要在Surfel中存储Shadow信息的Cache,在Surfel访问到可信的Shadow信息时将其保存下来,并一直使用该值到下一次Surfel访问到可信的Shadow信

光照信息编码
通过球谐函数和球谐系数和构建的函数,可以得到给定方向上的光照颜色(对 Radiance 信息编码)
根据当进行球面对称的核函数与原始信号函数的卷积时,可以等价为核函数球谐系数与原始信号函数的球谐系数进行乘法操作
通过计算 Radiance 的球谐系数,简单的和传输函数的球谐系数相乘,再乘以一个固定倍率,就可以得到对应的 irradiance
计算 radiance 的球谐系数
使用蒙特卡洛方法来估算数值
(4Π/n)*(SH()*radiance) 得到系数
数据的混合
计算像素的世界空间坐标、得到当前位置的体素,和周边八个体素的结果进行混合计算
分块加载
为了支持大世界,需要实现PRT数据的分块,只动态加载玩家附件的PRT信息
Probe的自动撒点
在布置PRT分块时,会生成一个相机从上至下拍摄当前分块的深度信息,如果没有获取到深度信息将放弃在当前位置设置分块, 在当前分块的顶部生成相机获取该分块的高度图,精度为4米1个像素,每隔4米在该高度生成一个Probe。当相邻像素之间的深度差超过4米时,会在更低的Probe上方生成新的Probe,新生成的probe高度为较低Probe与较高Probe的高度中点

动态漫反射全局光照

预计分的方式需要进行预计素,离线预计算时间过长。在修正后需要再烘培。

VPL(虚拟点光源) 会从光源向外投射光线,对于这些光线照射到的每个位置,都会放置一个新的光源,用于代表来自该表面元素的间接照明

步骤 + 找到哪些点接受到直接光源 RSM的方法,可以采样其中的一些,得到一些列的虚拟光源 + 注入到场景中的三维格子 使用3d纹理将场景预细分为3d网格 对于每个网格单元,找到封闭的虚拟光源 找出它们的方向辐射强度分布 使用前两层SH压缩辐射强度分布 + 传播辐射度 对于每个网格单元,收集从其6个面接受到的辐射 计算格子受到的辐射度总和,并且使用SH保存 重复这个传播几次,直到变得稳定(4-5次) + 使用格子进行场景的渲染 对于每个着色点,找到它所在的网格单元格 获得网格单元各个方向的radiance 进行着色计算
存在的问题: 漏光,当几何比格子小时,会出现漏光的问题(使用自适应格子 level of detail 解决)

RSM(反射阴影贴图)

从光源的视角来渲染,除了深度信息之外,还会存储有关可见表面的其他信息,例如反照率albedo、法线、直接光照。在进行最后着色的时候,RSM的纹素会被视为虚拟点光源,从而提供单词弹射的间接照明效果。一个典型的RSM中存在数十万个像素,需要通过使用重要性驱动的启发式方法,来选择其中一个子集。可以给予整个RSM来创建一些虚拟光源,并将其放置在屏幕空间中,而不是为每个着色点都从RSM中选择相关的纹素。 很适合手电筒方式的照亮,面积比较小。优点是写起来简单
存在的问题是有多少个直接光源就得做多少个shadowmap 因为不会计算可见性,会导致显示问题。 反射物必须是diffuse、距离根据shadowmap之间的值计算距离

ShaderToy
LPVTest

存在的缺点,无法为间接光照提供遮挡效果,生成的结果看起来还合理,可以接受

光照传播体积

基于体素的方法

VXGI,基于一种体素化的场景表示。几何物体本身使用稀疏体素把茶树的形式进行存储。结构提供了一种类似于mipmap的场景表示,可以对体积空间进行块都的遮挡测试等效果。每个体素块还包含了它们所代表的几何物体所反射出的光线量等信息,以一种定向形式进行存储,因为radiance会在六个主要方向上发生反射。首先会使用反射阴影贴图(RSM),将直接照明注入到八叉树的最低层节点中,然后再根据层次结构向上进行传播。
实时全局光照VXGI技术介绍 - 友人y的文章 - 知乎

使用稀疏八叉树存储光照信息,一个主要问题就是查找成本较高。找到包含给定位置的叶子节点,需要进行一系列的内存查找,还穿插着简单的逻辑缺点。大部分时间花在内存读取,ALU工作很少,经常会出现所有分组都在等待内存返回数据,都没有实际工作执行的情况。
大量warp停滞会导致性能表现不佳,可以使用一组级联的三位纹理来代替八叉树结构。具有相同的尺寸,但是所覆盖的区域面积越来越大。只需要进行一次常规的纹理查找即可完成数据的读取,而不需要进行额外的依赖读取。存储的数据都包含着六个方向的albedo、normal、反弹光照信息。因为级联的位置会随着相机的移动而发生变化,因此物体可能会不断地进出高分辨率区域。
CascatedVoxelConeTracing

屏幕空间方法

可以只使用存储在屏幕位置上的表面信息,来模拟一些漫反射全局光照效果。这些方法并不流行,因为屏幕空间中可用的数据量十分有限,因此会导致更加明显的瑕疵。比如颜色溢出等,通常是由于强烈的直射光照照亮具有相对恒定颜色的大面积区域而产生。
ShaderToy
理论

光照信息存储

不一定要是规则均匀
存储为不规则点云,构建四面体,类似光照探针
手动放置、自动放置
漏光瑕疵的解决
自动设置的探针添加可见性信息,将单个四面体的影响范围限制在相关区域内

镜面全局光照

各种用于渲染视图依赖效果的方法。

局部环境贴图

环境贴图的动态更新

基于体素的方法

平面反射

屏幕空间方法