快速收敛的Stochastic Screen Space Reflections

Stochastic Screen Space Reflections 旨在屏幕空间反射时,加入重要性采样的思想,根据反射表面的粗糙度计算表面法线的概率分布,得到一个锥形分布的反射光线。

主流做法有两种,一个是使用原有法线抖动反射光线 Jitter Ray(如下左图),一个是根据粗糙度抖动法线,进而得到抖动的反射光线 Jitter normal(如下右图)。

Image

更加符合物理规律的当然是Jitter Normal的做法,因为物体微表面本身就是粗糙的,根据概率得到法线的分布,进而得到反射的方向,这是一个很自然的想法。

但Jitter normal的做法有个坏处就是不容易收敛,UE4中glossy表面发射了4根光线来做追踪,配合它强大的TAA才让SSR收敛。

在AMD的SSSR示例里,他们更是夸张的使用了一个巨大的Denoise库,共计使用8xRT 约100MB显存(1080p)来做Denoise。

EA的做法是Jitter Ray,因此他们可以使用RayResue的做法来重用Ray。

我当然是想按照Jitter Normal来做,并且也想像EA一样使用RayReuse,实现之前参考了两个库:https://github.com/Polish-Miko/GravityEngine 和https://github.com/haolange/Unity_ScreenSpaceLighting_Old 。

不过按照他们的做法,1 Ray 4 Resolve或者 1Ray 9 Resolve无论如何都没办法在高粗糙度收敛:

下方是0.3 roughness:

Image

下方是0.5 roughness:

Image

下方是0.7 roughness:

Image

无论如何我都是做了双边滤波和时域滤波的,噪点应该是可以去除的。

观察上方图片,发现噪点随着粗糙度的增加而逐渐增多。

为什么会这样呢?因为前两个库的双边滤波都是用的一个固定尺寸的3x3 Box。

随着粗糙度增加, H的分布应该会更加的发散:

如下图所示:

Image

对于低粗糙度物体,sample Box可能覆盖超过法线分布的区域,最终双边滤波出来会出现Blur,而更加粗糙的物理,应该使用更加大的sample Box,否则Sample Box 没办法覆盖完整的区域面积,Temporal累积时总会漏掉其余部分的贡献,就很容易出现noise。

所以正确的做法应该是让双边的Box随着Roughness变化而变化,最好是呈现一个Cone形状:

Image

这里面应该有一个最佳的公式,但是好像直接用 roughness 乘上一个常数就可以得到不错的效果了:

Image

Image

Image

© - 2024 · 月光下的旅行。 禁止转载