常见反射方案总结

a). SSR

优点: 实现简单,效果较好;

缺点:

  1. 只能反射屏幕内的物体(屏幕空间算法的通病);
    • 解决方式:SSR作为主方案,Reflection Probe作为备选项,在SSR失效的地方(如屏幕边缘)对两者做平滑过渡;
  2. 需要Ray Marching、频繁读取纹理,可能造成IO瓶颈;
  3. 被反射物只有漫反射的时候才是完全物理正确的;
  4. Ray Marching次数限制,容易出现物体断裂;
    • 解决方法: 一般会引入Thickness来防止物体出现断裂,即ray marching的点除了深度需要大于深度图的深度值,还需要步进的步数小于Thickness;

优化:

  1. Hierarchical Z;
  2. Dither;
  3. 下采样;

b). Stochastic SSR

针对情况: Gloosy物体(对于普通SSR来说,只可通过roughness对反射图进行blur)

整体思路为

  1. 将屏幕划分为Tile,进行一次低分辨率的光线步进,评估Tile的重要性,需要多少射线

  2. 根据材质粗糙度判断使用何种的RayMarching

    • 昂贵的射线(用于smooth表面):借助Hi-Z的精确tracing,能得到准确的命中点
    • 便宜的射线(用于粗糙表面):简单的线性步进,反正之后会粗滤波
  3. 使用重要性采样求RayMarching结果

  4. 时域空域光线复用(本质是计算 brdf/p(x) 的加权和),进行插值滤波

Tile评估

  1. 将屏幕划分为多个Tile,对于每一个Tile以1/8分辨率发射射线

  2. 判断射线(的反射光线)是否击中

    1. 若所有光线都没命中,则跳过这个Tile的步进
    2. 根据命中的比例和命中信息的差异,判断这个Tile中的像素需要多少个光线
    3. 根据着色点的粗糙度,决定使用何种RayMarching

c). 平面反射

缺点: 可能增加一倍的Draw Call;

优化手段:

  1. 剔除影响不明显的小物件;
  2. 如反射物为镜子之类的,可以结合Portal或者手动计算去剔除镜子外的物件;

d). IBL+Relection Probe

略过

e). Pixel Projected Reflection(PPR、SSPR)

PPR 将整个图像,按照平面的位置进行翻转,在屏幕中进行投影,即可直接得到反射的位置,写入数据并得到一张反射的贴图。

v2-2eaa5f56c2c7d7ba4db44ca06ad73a42_r

因为场景中的像素,并不能完全保证覆盖整个反射平面,因此往往会产生一些缝隙。UE4中采用一种简单的修复缝隙的方式,是在写入偏移时,将目标像素周围2x2像素直接全部写入偏移值。

  1. 根据深度图,还原场景深度,算出对应点世界坐标,将其投影到平面上,然后将其在屏幕中的偏移量,将偏移量进行编码,写入到 Intermediate Buffer当中;
  2. 从Intermediate Buffer中还原出屏幕空间的偏移,采样屏幕中相应坐标的像素点,将结果写入到反射图中;
  3. 使用反射图,绘制出反射面的效果。

【参考资料】

游戏中的全局光照(五) Reflection Probe、SSR和PPR - 张亚坤的文章 - 知乎

Unity StochasticSSR-01 - CGBull的文章 - 知乎

Stochastic Screen Space Reflections论文阅读 - Reuben的文章 - 知乎