之前针对RSM和LPV优化技术介绍后,我们可以看出来一个大致的思路的:就是减少计算量提升最大,因此VXGI的优化思路和之前两种算法几乎一样,之前也实现过Global Illumination_Voxel Global Illumintaion (VXGI)有兴趣的可以去简单了解下,本部分主要对VXGI技术进行优化介绍与分析,学习自用,大佬勿喷。
一、VXGI简述
同样,首先我们先来看一下VXGI技术的原理以分析其性能卡点,具体的就不介绍,有兴趣的找原文,本部分只简单介绍:
基于体素的锥体追踪技术(VXGI/VCT)与LPV有一个逻辑相似之处:场景都是以一组空间划分网格的方式进行光照信息存储与应用。但是基于体素的VCT比LPV的网格力度会更细,且网格尺寸更小,几何图形表面的辐射亮度被注入到存储在3D纹理中的体素中,除了物体的位置和直接照明贡献外,不附带任何其他信息。之后针对屏幕空间中的每个世界位置从该点以法线半球为正向采用多个覆盖半球的锥体计算周围不同辐射强度的贡献。最后,对于每个锥体,应用一组射线进行步进迭代,根据距离像素点所在世界空间位置计算不同的mipmap级别来收集体素,从而得到正确的光照数据作为全局光照使用。
其中一个比较好的点是,可以使用一个额外的锥体的用于一些间接的镜面反射。因为预先处理的世界空间的场景关系数据所以它们的计算在物理上意义上是准确的,能够接近真实场景,没有与前面提到的屏幕空间算法反射中没有缺失的物体情况。
每个可见像素的总辐照度的最终结果可以通过以下方法来计算:
其中,𝑆为每个锥的追踪步数,𝐶是锥体的数量。
下图展示了像素点法线半球一个锥体追踪过程:
还有就是体素化场景中的锥体的追踪示意:
因此常规的VCT算法的整体渲染管线流程如下图所示:
可以看出VCT由三个主要的pass组成:场景的体素化、体素化纹理mipmap层级生成和锥体光照追踪三部分,知道了大体流程接下来就是分析具体的可优化点了。
二、RSM优化技术
如前所述,为了收集次级光源表面的辐射亮度(radiance),场景必须近似地在单元格网格中。这些单元格的数量取决于所提供的RSM纹理(通量/正常/世界位置)的分辨率,但是分辨率越高,光照注入和传输的成本就越高。如果原始的RSM的缓冲区是以2048x2048分辨率生成的,这对于生成2048三次方个表面的网格元素,之后无论是注入还是传输都需要执行这么多次的计算。因此,必须通过降低分辨率,减少计算量。
2.1 计算着色器优化
根据上边的文章以看出相对于使用PS直接把所有的计算迁移到计算着色器上是完全可行的,效率会有一定的优化,虽然不是质的提升,但毕竟是优化嘛,苍蝇再小也是肉,所以可以把除了体素化需要使用光栅化GS之外的pass都可以使用计算着色器来替代,其中包括Mipmap的准备、Mipmap层级迭代、锥体光照计算、上采样步骤。
2.2降采样优化
直接看结论:和上边两个优化一样最大的优化点就是通过降低分辨率,减少计算量。
首先来看一下就是针对体素化的3D场景,越小越好,可以采用256256256的3D纹理,当然了效果和效率都是相对的,根据项目自行判断;其次就是锥体光线计算时候涉及到的计算量了,锥体光照追踪pass是算法中最重的部分,也是计算量的大头,它对GPU资源的要求相当高,因为它的逻辑类似于射线步进:屏幕虚拟球体的每个像素都在一个锥(s)中进行多次步进的计算步骤,因此该步骤计算着色器复杂度如下:
其中,+1是用于的高频的镜面锥体光照计算。
有了上述认知,我们就可以针对间接照明纹理进行降采样优化了。
从VCT算法的整体流程中各部分的时间复杂度可以看出,主要还是在锥体关照追踪上,而锥体光照追踪部分取决于屏幕的分辨率。所以我们需要先将3d纹理降采样存储,之后上采样滤波输出即可,因此整体管线便修改为如下所示:
在VCT算法中,一般采用𝑘=2的降采样因子,既可以保证帧率有优化又可以最大程度上使渲染效果不失真,而此时其复杂度就变成了:
别小看2倍的因子,在高分辨率下会有明显的效率提升。而且理论上,也可以采用两个单独的降采样间接漫射锥体光照追踪和间接镜面。
其实也可以不进行上采样滤波直接用,但是部分情况下效果会不是太好,比如下边的情况(上图是降采样后的结果,下图是上采样滤波后的结果):
但是呢上采样加滤波其实耗时很少和之前说的RSM类似都是0.4ms左右,所以完全不用省(而且还可以基于CS来做)。
但是大部分情况其实不仔细看间接光照,差别不是太大,可以直观的看一下下边左图是不使用降采样效果,中图是仅降采样的效果,右图是降采样后再上采样滤波的效果,几乎没什么太大的差别,所以优化目的达到。
和预期一样,降采样优化的性能提升与降采样因子成正比(非严格意义上数值正比)。
在1080P分辨率下,以降采样因子为2为例:可以看出下图的优化对比
对比优化前后Nsight截帧:
降采样优化前:
降采样优化后:
可以看出,注意到在降采样优化后GPU的L2缓存吞吐量从10%左右增加到16%,VRAM的吞吐量从1.8%增加到3.4%。尽管活动SM单元的数量90+%,但是锥体光照追踪计算仍然是以ALU计算为主(SM吞吐量不高,在两种情况下只有40%左右)。
2.3 并行渲染管线优化
VCT中除体素化流程之外,其他每个流程都适合在计算着色器中实现。因此可以把除了体素化之外的流程,都拆开到GPU上其他并行队列中执行,所以我们可以把原始的管线改造成并行管线。
VCT算法的管线流程如上图所示,与RSM的非常耗时的主通道的情况相反,VCT在异步队列中存在效率高的pass,这在情况下异步更有效,并且更少地拆分两个队列的性能差异。非异步版本的性能管线效率已经不低了(除了体素化之外的所有VCT通道只需要~3.4毫秒),下边对比一下异步与非异步版本GPU的执行情况。
原始非异步管线:
异步管线:
从上图可以看出原始非同步情况下某些情况GPU运行的还稍微好一些,从异步队列执行图片中看出,在异步模式下执行VCT计算传递所需的时间是3.79ms左右(原始模式下的3.4ms左右)。与RSM的情况类似,管道在工作分布和各种GPU元件的吞吐量上确实有所不同。例如,在同步管线中,SM和L2吞吐量在VCT计算任务中持续时间更短,而在异步中,它们花费更多的时间,活动时间更少。此外,和RSM异步优化类似由于低工作负载的图形队列运行状态导致顶点和像素Wrap的效率在VCT算法中效率较低。另一方面,图形队列中的传递,如体素化和阴影映射,在异步的帮助下获得了一些性能提升:体素化从从1.76ms降低到1.49ms,阴影映射从0.73ms优化到~0.4ms。
经过多次验证,性能差异如下图所示差异不是太大,结论是有提升但是不多。
总的来说,图形管线的异步并行操作对RSM和VCT算法来说都不能显著优于它们的同步版本,在某些情况下,它们的性能相似,甚至略低。在这个算法中,图形和计算队列都“同时”执行大量的纹理读取和写,这导致了带宽受到限制。
三、总结
RSM、LPV和VCT是实时场景中光栅化除了SurfaceGI外最常用的全局光照方案。RSM在视觉上可能有点“过时”,并且高分辨率下性能会更低,但适用于使用低分辨率渲染目标的移动或手持平台,并且很容易实现。LPV需要更性能还好相对RSM来说,视觉上也还行,优化后内存消耗也不高,但是不上不下,学个思路还行。最后,个人认为从性能和效果上综合来看VCT在这三个算法中算是最优解,VCT技术能够以很少的成本提供了全局光照效果,同一个着色器下少改动即可附带AO(如下图),并且可以通过优化有效地提高效率。