Games202-4 Real-time Global Illumination(in 3D)

a). Introduction

  • In RTR, people seek simple and fast solutions to one bounce indirect illumination

GI00b

  • Primary LIght Source(真正的光源,太阳)

  • Secondary Light Source(次级光源,Q点)

    GI00a

  • 观察(要得到$p$点的间接光照我们需要做什么):
    1. 得到Secondary light source(哪些点被光源照射到)
      • 方法: Shadow Mapping
    2. 得到各个Secondary light source对 $p$点 Radiance的贡献
      • 方法: 解渲染方程
  • 以下是实时渲染中常用的在3D空间中(意为渲染效果不取决于相机位置/屏幕空间)的GI方法(主要针对one bounce indirect illumination):
    • Reflective Shadow Maps (RSM)
    • Light Propagation Volumes (LPV)
    • Voxel Global Illumination (VXGI)

b). Reflective Shadow Maps (RSM)

GI00a

  • 得到Secondary light source(哪些点被光源照射到)
    • Shadow map中每一个Texel都是一个作为Secondary light sourc的面片(Surface patch)
      • Shadow map做阴影中是光源视角的$Depth$,和相机视角的比较;这里是光源视角的$Depth$和 点$p$ 视角比较
  • 得到各个Secondary light source对 $p$点 Radiance的贡献
    • 但是,对于不同的 点$p$ 次级光源入射方向是不一定的。即,即使观察角度固定,同一个Shadow map中的Surface patch,对不同的 $p$ 贡献不同;
  • 假设:
    • 次级光源均为Diffuse(观察角度固定,同一个次级光源对不同 点$p$ 的贡献相同)
    • Therefore, outgoing radiance is uniform toward all directions

b.1). 得到各个Secondary light source对 $p$点 Radiance的贡献

RSM_01a

  • 对于每个diffuse reflective patch(点$q$)

    • 点$q$ 的BRDF: $f_{rq} = \rho/\pi$

    • $L_i(q\rightarrow p) = f_{rq} \cdot \frac{\Phi}{d A}$ ( $\Phi$ 是光源的辐射通量,将该式带入渲染方程,${d A}$ 被消除)

      • ${||x-x_{q}||^{4}}$ 是因为分子上$x-x_{q}$是未归一化的向量;
      • $\Phi_p$ 为 $f_{rq} \cdot {\Phi}$
      • 将$E_p(x,n)$ 乘上 点$p$ 的BRDF即可得出$L_o$
      • $V$:Visibility项就不算了
  • Not all pixels in the RSM can contribute

    RSM_04

    • Visibility (难处理,不管了)

    • Orientation(方向,Reflector的反射方向只在法向半球上,法向半球的方向覆盖不到的Shading Point自然不受该Reflector的影响)

    • Distance(只有和Shading Point近的Reflector才做贡献)

      • 假设: 世界坐标下,两点接近 $\rightarrow$ Shadow Map(世界空间转换到光源空间)中距离比较近,且深度相差不大;

      • 进一步加速(类似于Step 1 and 3 in PCSS),在shading point转换到Shadow Map后对应点$(s,t)$ 的一定范围内,做随机采样

        RSM_Distance

b.2). 光源视角下储存的信息(Shadow Map)

RSM_Record

  • 深度
  • 世界坐标
  • 法线
  • 辐射通量(flux)
  • etc.

b.3). Pros And Cons

  • Pros:
    • 好写(类似于Shadow Map)
  • Cons:
    • 计算量随光源(Primary Light Source)数量增多线性增加
    • Visibility无法处理
    • 很多假设:diffuse reflectors, depth as distance, etc.
      • 只能处理次级光源为Diffuse
    • 质量依赖于采样率

c). Light Propagation Volumes(LPV)

  • CryEngine3 里用到了,在孤岛危机里应用
    • 快而且质量好
    • 同样也只能处理次级光源为Diffuse

LPV_CryEngine

  • Key idea: 光线直线传播中,Radiance大小不变;
  • Key solution: 通过3D网格(体素,Voxel),传播Secondary Light Source/dirctly illminated surfaces的Radiance到其他地方;
  • Steps:
    1. 生成场景中被直接光照照射到的Radiance point(即Secondary light source);
    2. 将Radiance point注入到体素中;
    3. Radiance在体素中传播
    4. 传播稳定后(一般迭代4、5次),通过体素中储存的Radiance进行Shading;

c.1). 做法

Step 1: Generation

  • 找到Secondary light source
  • 使用Reflective Shadow Maps (RSM);

LPV_Step01

Step 2: Injection(注入)

  • 预先划分好3D网格(体素);
  • 对于每一个体素,找到其内部的Secondary light source;
  • 将他们出射的Radiance大小和方向看做是球面函数,投影到2阶(4个)的球谐函数上

LPV_Step02

Step 3: Propagation(传播)

LPV_Step03

  • 对于每一个Voxel,都会传播到相邻的6个面(3D,前后左右上下,不会斜向传播),也会接收6个面的Radiance;
  • 接收6个面的Radiance并相加后,再次使用SH表示;
  • 重复上述步骤,直至传播接近稳定(一般整体迭代4-5次)

Step4: Rendering

  • 对于每一个着色点,找到他们所处的Voxel;
  • 使用该Voxel中存储的Radiance(from all direction, 是一个SH表达的球面函数),进行Shading;
    • 因为存储的是球面函数形式的Radiance,所以既可以做Diffuse也可以做Gloosy

LPV_Step04

  • 造成的问题: 由于同一个Voxel中Radiance相同,对于薄的几何体可能造成Light leaking

    LPV_LightLeaking

d). Voxel Global Illumination (VXGI)

  • 与RSM两点主要的不同
    • 将被光源直接照射的像素变为带有层级的体素(hierarchical voxels)(即Secondary light source不再看成surface patch,而是hierarchical voxels)
    • 光线传播方式:
      • 从摄像机开始传播,进行锥形传播(Cone tracing,比如光线在Gloosy表面弹射,出射方向为一个锥形),计算锥体相交的Voxel对该点的Radiance贡献;

d.1). 做法

VXGI_00


Pass 1: from the light

  • 储存每个点的入射Radiance,并储存到对应的Voxel中;
  • Voxel中存储Incident lighting和normal的分布,以便支持Gloosy等材质;
    • 存储Lobe分布的基础:Cone Trace
  • 根据这两个分布,即可得出 出射Radiance 的分布情况;

VXGI_Pass01

Pass 2: from the camera

  • 对于Gloosy的表面,追踪1个朝向反射方向的圆锥;
  • 根据圆锥的(grow)大小,查询相应层级;

VXGI_Pass02

  • 对于Diffuse,追踪多个Cones

    VXGI_Pass02_Diffuse