Volumetric Light Effects in Killzone: Shadow Fall
在《杀戮地带 :暗影坠落》中的体积光效果实现

本文讲的是《杀戮地带 :暗影坠落》体积光的实现,文章里优化体积光的技术点例如降采样、扰动、模糊等在现在已经是非常常用的技巧点了,现在看这篇文章更像是对这些知识点复习一遍。
文章中主要考虑一下几个问题:控制体积光的形式,如何优化体积光的计算,半透明物体和体积光如何兼容。
1,控制体积光的形式
为了实现控制体积光的区域,文章中表示他们为每个光源规定了一个形状来表示光照影响范围,点光源是一个圆,聚光灯为一个锥形,平行光/太阳光则设置为整个屏幕。

在体积光的步进算法计算光照强度之前会先判断步进点时候在这个范围之内,这个有点类似于体积云和体积雾里Bound。
2,优化体积光的计算
优化计算主要分三步,一,降低计算分辨率。二,调整步进幅度,减少步进步数。三,抖动模糊。
一,降低计算分辨率。
一般体积光计算的时候屏幕有多少个像素就算多少次,如果主动降低分辨率那计算效率就会显著提升,但是效果也会影响。
文章中选择了使用降一半分辨率,权衡了效果与性能。

二,调整步进幅度,减少步进步数
一半体积光计算的时候,每个像素点步进的幅度是一致的,文章中通过采样一个扰动贴图,让相邻的计算点步进幅度会有不同,以此减少整个计算过程中的步进数量。

三,抖动模糊
为了弥补上述操作使得体积光效果的下降,在最终计算完毕的体积光中还使用双边高斯滤波来过滤扰动采样结果,从而获得一个相对平滑的图像。


3,半透明物体和体积光的兼容
体积光和半透明物体因为渲染顺序的不同都会造成错误的遮挡,因为步进算法会考虑深度图,而半透明物体一般是不写入深度的,以至于在体积光计算的时候很难考虑的到半透明物体的影响。
首先文章用3D纹理的方式,以深度为Z坐标分层存储空间上散射量的计算结果。

这张3D纹理的宽和高拥有原生渲染分辨率的八分之一大小,在深度上有16张切片。每张切片上的每个像素储存一个16-bit大小的浮点数,用于储存128m范围内与下一张切片之间区域的散射量。
这个纹理不是最终需要的纹理,以这个纹理为基础文章以屏幕空间为XY坐标,深度为Z坐标。计算屏幕像素点上每个深度切片的累计的散射量:

这样就获得了一个3D纹理查找表,在体积光步进计算光照量的时候通过深度就可以直接或当前位置的散射量,这样通过就可以通过控制切片的从而能在空间上控制体积光的效果。
同样的在处理半透明物体和体积光兼容的时候也采用了类似的思路,文章以深度为Z轴,存储了不同深度下体积光的积累量。
这样在渲染半透明物体的时候就能知道有多少体积光量在透明物体前和透明物体后,从而调整表面颜色。

表面颜色混合算法:

文章提及的后续优化:
1,极线采样:这个在3.2 大气散射的极线采样中有提到,本质相同
2,压缩算法优化深度值的存储,从而避免3D纹理
参考资料:
学习笔记-GPU PRO5 Volumetric Light Effects in Killzone:Shadow Fall