以下为个人学习笔记整理,课程官网传送门作业传送门会议系统传送门

# Real-time Global Illumination

实时渲染中所描述的全局光照实际上就是比「直接光照」多一次的「间接光照」。

# Reflective Shadow Maps(RSM)

由于要用「次级光源(反射物)」去照亮周围的物体,又因为周围物体对「次级光源」的观察方向都是不同的 —— 需要知道「次级光源」各个方向上的光照强度。因此为了简化计算:不考虑观察方向带来的影响,假设所有的「反射物」的「BRDF」都是 diffuse 的。这样从任意方向的观察结果都是一致的。

GAME101 辐射度量学相关内容回顾

GAME101 全局光照回顾。沿用之前推导出来的公式。考虑了「辐射强度」和「距离平方」衰减以及「单位立体角对应的面积」

image-20210610194312340

假设每个「次级光源」都是一个点(patch),那么计算一个物体的「间接光照」,就需要把所有 patch 作为光源计算一次光照。

这里把「次级光源」视作 q 被照亮的物体视作 p

image-20210610194604816

结合上面的公式,就可以得到 p 点沿着 wow_o 方向从「次级光源」接受到的光照强度公式。

image-20210610194800627

image-20210615095054850

  • 由于「次级光源」的「BRDF」假设为 diffuse。
    • 「次级光源」的「BRDF」:fr=ρ/πf_r = \rho / \pi,这里的「BRDF」是「次级光源」而非观察物体的。
    • 「次级光源」沿着 wow_o 方向出射的光线:$L_i = f_r \cdot \frac {\Phi}{dA}, \Phi \text {is the incident flux or energy} $,出射的光照强度等于各个方向上接收到的入射的总光照强度 X 「BRDF」/ 单位区域。

LiL_i 的计算已经解决了,剩下的「Visibility 函数」该如何处理呢?

一种办法是针对任何的「次级光源」都生成一张「shadow map」,不过这显然不太合适。因此就不计算了 😅。

# Not all pixels in the RSM can contribute

  • Visibility 函数(就算是 diffuse 的也很难处理)
  • Orientation:「次级光源」的入射光方向和法线夹角不可能反射到某个物体,例如桌子上的「次级光源」不可能影响 x 的渲染结果。
  • Distance:距离太远了也不行。

image-20210610201552958

这里做一个大胆的假设:「shadow map」上两个像素点的距离,可以直接视作空间坐标内两个点的距离,这种情况下就可以简单的获得每个「次级光源」的作用范围:

image-20210610202540466

  • Acceleration
    • 对某个「shading point」周围选取一定数量的「次级光源」(采样)
    • 类似 PCSS 的一些预处理操作

# What is needed to record in an RSM?

  • depth:深度。
  • world coordinate:世界坐标(计算距离)。
  • normal:法线,计算方向和 coscos 项。
  • flux:通量,计算光照强度。

image-20210610203109509

# Often used for flashlights in video games

image-20210610203437372

  • 优点
    • 容易实现
  • 缺点
    • 很多假设会让结果不准确。
    • 没有考虑「Visibility 函数」。
    • 直接光源越多,要做的「shadow map」就越多。
    • 采样数量和图片质量之间的权衡。

# Light Propagation Volumes(LPV)

# 【step1】Generation

和「RSM」处理类似,用「shadow map」来找出所有的「次级光源」

image-20210611142852618

# 【step2】Injection

  • 将 3D 场景切分为 3D 网格。
  • 每个格子内部是否包含了「次级光源」
  • 对每个格子内的「次级光源」求和,得到以 3D 网格为单位的「次级光源」
  • 用「SH 函数」来进一步描述每个 3D 网格的 球面出射光照 ——2 阶(4 个基函数)就足以描述。

image-20210611143526754

# 【step3】Propagation

  • 计算每个格子的「次级光源」的光照向六个面(不考虑斜对角)传播后的光照(不考虑「Visibility 函数」,所有格子都可以向四周传播光照,不会被遮挡)。
  • 对所有格子内的所有光照求和并用「SH 函数」表示。
  • 重复上述步骤多次,直到整个系统稳定。

image-20210611144128176

# 【step4】Rendering

  • 对任意的「shading point」,查询 3D 网格内对应的格子。
  • 获取该网格内的入射光强度。
  • 并计算「shading point」的光照。

# Any problems?

对遮挡的判断不理想,以格子为单位进行划分的情况下,格子内任意点的光照强度是一致的,就算实际情况中该点被遮挡了。

image-20210611144829287

# Light leaking

image-20210611144950948

# Voxel Global Illumination(VXGI)

# Difference with RSM

  • 场景全部转化为一块块的格子(可以得到所有「次级光源」的格子和光照强度)。
  • 从「摄像机」出发到某个「shading point」并反射出一个视锥,计算视锥覆盖的「格子」(次级光源)的贡献。

image-20210611151839334

# 【step1】Voxelize the entire scene

# 【step2】Build a hierarchy

image-20210611154005877

# 【step3】Pass1 from the light

  • 通过光源计算任何一个「patch」的直接光照方向,以及「patch」表目的发现方向。并对多个「patch」进行合并得到一个更大的层级,记录层级上的入射光照方向分布和法线分布,这样就可以支持 glossy 的「BRDF」—— 当场计算出出射光线分布。

image-20210611154117973

# 【step4】Pass2 from the camera

  • 对 glossy 的表面,沿着反射方向绘制一个圆锥。
  • 根据圆锥的长度,再对应层级大小的位置取「patch」进行光照贡献计算(越远取的层级越大)。

image-20210611155530878

  • 对于 diffuse 的「BRDF」这个视锥如何绘制呢?
    • 用少数几个较大的圆锥来进行计算

image-20210611161901902

# Real-time Global Illumination(screen space)

# What is 「screen space」?

  • 信息都来自于「screen」
  • 相当于对已经渲染过的图片做后期处理

image-20210611163333246

# Screen space Ambient Occlusion(SSAO)

# Why AO?

  • 实现简单。
  • 增强了物体间的相对位置,画面更加立体。

image-20210611163728277

# What is SSAO?

用于在「屏幕空间」对环境光照近似的产物

# 【idea1】

假设环境光在任何位置都是相同的,参考「Blinn-Phong」模型

image-20210611164945028

# 【idea2&3】

考虑不同位置对于环境光的接收程度「Visibility 函数」。

image-20210611165556577

# Theory Ambient occlusion

image-20210611165743080

# rendering equation

  • LiL_i 由于是间接光照,可以直接视作常数,「BRDF」可以当成 diffuse 的,也是常数。
  • 间接光照强度是常数,因此非常的 smooth,可以用「split sum」进行准确拆分并非近似。

image-20210611170914686

  • 另一种理解:相当于对积分范围的平均乘以光照强度积分。

image-20210611171902420

  • why cosθidwicos \theta_i \ dw_i

image-20210611175413574

因为 cosθidwi=dxcos \theta_i \ dw_i = dx_{\perp},所以对半球积分就变成对圆积分,至此:把 3d 空间投影到了屏幕空间。

image-20210611173309322

# Actually Screen Space Ambient occlusion

  • 光照(LiL_i)本身是个常量。
  • 「Diffuse BRDF」——fr=ρπf_r = \frac{\rho}{\pi}
  • 然后把这两个常数项提出来,公式如下:

image-20210611182633672

# Calc「Visibility」

【object space】

  • Raycasting:需要额外打一次射线
  • Depends of scene complexity:场景越复杂越慢

【screen space】

  • Done in a post-rendering pass:在渲染结束后处理。
  • No pre-processing required:不需要预处理。
  • Doesn't depend on scene complexity:不依赖复杂场景。
  • Simple:实现简单。
  • Not physically accurate:但是在物理上不准确。

# Limited radius

间接光照的照射范围有限,因此可以设置一个有效距离。

image-20210611184049599

# Ambient occlusion using the z-buffer

针对某个「shading point」(白色点),取其周围一个球形区域内进行随机采样,得到弱点的样本。

对于每个样本,通过该点的深度值和「shadow map」的深度进行比较来判断该点是否会对「shading point」接收到的「间接光照」产生贡献 —— 红色表示无贡献,绿色表示有贡献。

image-20210611184413904

只需要对「法线」所在的半球做采样操作:剩下半边都是物体内部,一般不考虑穿透物体内部的光线。

image-20210611185134467

image-20210611185954306

# SSAO problem

石凳空间上和地面不会有任何遮挡,但是由于是屏幕空间,因此在石凳和地面的交界处出现了错误的阴影。

image-20210611185518936

# Screen Space Directional Occlusion(SSDO)

「SSDO」非常接近「RSM」,核心思想:

  • 针对每个「shading point」,随机的射出若干个射线
  • 如果射线遇到障碍物,那么障碍物发出的光线视作「间接光照」
  • 如果射线没有遇到障碍物,那么就算作「直接光照」

image-20210615174646374

# Screen Space Directional Occlusion

Comparsion w/SSAO

  • AO:「间接照明」(橙色)+「非间接照明」(黄色)
  • DO:「非间接照明」(橙色)+「间接照明」(黄色)

same as path tracing

image-20210615174921536

# Consider unoccluded and occluded directions spearately

  • Visibility(橙色)。这部分不是「间接光照」,不需要计算。

image-20210615175236388

  • Unvisibility(黄色)。这部分是「间接光照」,需要计算。

image-20210615175249989

# Simple

和「HBAO」类似,对每个「shading point」的可见半球内随机采样。然后连接「摄像机」和「采样点」。判断深度值计算可见性,得到所有能够贡献「间接光照」的采样点(A、B、C)。

再对所有能够贡献「间接光照」的采样点进行距离和法线筛选,得到最终的贡献采样点(B、C)。

image-20210615175729550

不过这样会有问题:

  • 如果摄像机无法看到的「采样点」,会被排除,例图三如点 A(不应该)。
  • 如果在「shadow map」深度比「采样点」小(光线无法照射到),这种情况下又会被计算贡献(不应该)。

# Issues

  • 只能表示小范围的全局光照
  • 可见性不准确
  • Screen space 的通病:对于「摄像机」看不见的物体信息,将会缺失(假设一面墙背后有一个点光源,那么这种情况下,点光源将不会产出任何的光线)。

# Screen Space Reflection(SSR)

在屏幕空间上做光线追踪,不需要几何信息。

考虑任何光线和场景的屏幕空间如何求交。

image-20210616093122052

就效果上来说,像是对地面做了一个镜面反射

# Basic SSR Algorithm

# Mirror Reflection

  • 对地板上所有的片段进行光线反射计算,得到的交点作为改片段的反色光进行着色。

image-20210616111520374

# High smoothness

image-20210616111607212

# Medium smoothness

image-20210616111643004

diffuse 的着色实际上就是取多条反射光线

image-20210616111726486

# Medium smoothness + normals

可以再加上法线使得渲染更有「层次」。

image-20210616112255885

# Variable smoothness

image-20210616112458444

# Process

image-20210616112715357

# Linear Raymarch

  • 根据「shading point」和「摄像机」计算出反射方向
  • 按照一定的步长进行查询,直到遇到「depth」比「shadow map」上记录的深度大时,可以视为光线和场景有交点。
  • 计算交点处的光线贡献。

image-20210616113034358

# Hierarchical ray trace

image-20210616113521384

Generate Depth Mip-Map

核心思想是通过「MipMap」记录某个范围精度内的最小深度,加快查询速度。

每个「MipMap」上的点,记录的是周围 N x N 区域内深度的最小值。

image-20210616113818723

和 3D 空间内的 「BVH」以及「KD-tree」非常类似 ——「BVH」和「KD-tree」介绍

每次移动到下一块区域时,计算移动到的点的深度值,并且和该「MipMap」记录的深度比较:

  • 如果深度值比「MipMap」的要小,说明不会相交,继续移动。
  • 如果深度值比「MipMap」的要大,说明交点就在像素范围内。
    • 有交点的情况下,再对该区域的更「深」一层的「MipMap」进行查询,直到找到对应的交点。

image-20210616114656131

# Hidden Geometry Problem

因为「Screen space」本身的问题,反射结果缺少了手掌和手指的背面。

image-20210616143051276

# Edge Cutoff

另一种是物体本身超出了屏幕,这种情况下会丢失原本超出屏幕的信息。

image-20210616143301888

通常会采用一个「距离衰减」的方式让画面不至于穿帮

image-20210616143408227

# Shading using SSR

这里和「path tracing」的处理一致,计算光线打到的物体所反射出的光线,并且反射物(次级光源)必须也是「diffuse」的。

image-20210616143912016

# Support

# Sharp and blurry reflections

支持光滑和粗糙物体的处理(BRDF)。

image-20210616173756607

# Contact hardening

根据「reflection ray」的视锥大小,对不同范围内进行「filtering」,就可以实现近处清晰,远处模糊的效果。

image-20210616173940713

# Specular elongation

取决于地面的「BRDF」,各项同性情况下可以实现拉伸的效果

image-20210616174057346

# Per-pixel roughness and normal

地面的法线分布可以实现大理石等材质效果。

image-20210616174211437

# Other approach

对 BRDF 的反射区域内选取更加重要(影响占比高)的方向进行采样,而不需要随机在范围内采样。

image-20210616174554218

空间上的复用,tracing 一个「shading point」时,得到的点(蓝点)顺带计算一下周围「shading point」的贡献。

image-20210616174908189

对 screen space 进行 filtering。然后就不需要对多个方向进行 tracing 就可以得到多个 tracing 的平均。

image-20210616175227152