# Games101 笔记

Games101 笔记

原视频 GAMES101 - 现代计算机图形学入门 - 闫令琪

# Lecture2 线性代数综述

Games101 使用右手坐标系

# 向量的点乘

公式:ab=abcosθ\overrightarrow{a} \cdot \overrightarrow{b} = |\overrightarrow{a}| |\overrightarrow{b}| \cos{\theta} \kern 0.1pt
判断向量前与后:点乘 >0> 0 同方向;点乘 <0< 0 反方向
点乘作为投影:若 a\overrightarrow{a} \kern 0.1pt 是单位向量,那么点乘的结果是 b\overrightarrow{b} \kern 0.1pta\overrightarrow{a} \kern 0.1pt 方向上的投影长度

# 向量的叉乘

坐标公式:a×b=(y1z2z1y2,z1x2x1z2,x1y2y1x2)\overrightarrow{a} \times \overrightarrow{b} = (y_1z_2 - z_1y_2, z_1x_2 - x_1z_2, x_1y_2 - y_1x_2) \kern 0.1pt
模长公式:a×b=absinθ|\overrightarrow{a} \times \overrightarrow{b}| = |\overrightarrow{a}| |\overrightarrow{b}| \sin{\theta} \kern 0.1pt
模长等于以 a\overrightarrow{a} \kern 0.1ptb\overrightarrow{b} \kern 0.1pt 为边的平行四边形的面积

输入两个向量,输出一个同时垂直与这两个向量的新向量。方向判断使用右手螺旋定则,四指从 a\overrightarrow{a} \kern 0.1pt 的方向向 b\overrightarrow{b} \kern 0.1pt 的方向握紧,大拇指指向的就是新向量的方向

判断两个向量的左右关系:a×b\overrightarrow{a} \times \overrightarrow{b}得到结果与 zz 轴同向,是正的,说明 bbaa 的左侧

判断点 PP 是否落在三角形内部

  • AB×AP>0\overrightarrow{AB} \times \overrightarrow{AP} > 0 \kern 0.1pt 说明 PPABAB 左侧
  • BC×BP>0\overrightarrow{BC} \times \overrightarrow{BP} > 0 \kern 0.1pt 说明 PPBCBC 左侧
  • CA×CP>0\overrightarrow{CA} \times \overrightarrow{CP} > 0 \kern 0.1pt 说明 PPCACA 左侧
  • 若满足以上三点,则说明点 PP 落在三角形 ABCABC 内部

# 矩阵

两个矩阵必须要可以相乘 (M×N)(N×P)=(M×P)(M \times N) (N \times P) = (M \times P) \kern 0.1pt
img

# 矩阵乘向量

img

# 矩阵的转置

img

# 单位矩阵、矩阵的逆

img

# 向量的点乘、叉乘(矩阵形式)

img

# Lecture3 变换简单总结

# 缩放变换

img

# 镜像变换

img

# 错切变换

img

# 旋转

默认绕 (0, 0) 转,默认逆时针旋转为正向旋转
img

公式推导
img

如果用一个矩阵乘以输入可以得到输出的坐标,那么称这个变换叫线性变换
img

# 平移

平移可以写成
x=x+txx = x + tx
y=y+tyy = y + ty

同阶矩阵只能进行旋转,为了解决平移这个特例,人们引入齐次坐标
img

# 2D 变换的齐次坐标形式

先旋转后平,从向量开始从右向左计算(矩阵 * 矩阵 * 向量)
img

# Lecture4 变换进阶篇

img

# 3D 变换

3D 变换相对于 2D 变换来说只是多增加了一个维度,可由 2D 变换举一反三得来
img

# 3D 旋转

img

# 罗德里格斯旋转公式

我们说在三维空间内绕某一轴旋转,默认这个轴是过原点的
罗德里格斯旋转公式描述了绕任意过原点的轴的旋转
img

对于绕 不过原点的轴 的旋转,我们需要将轴平移到原点,点也跟着平移,然后绕轴旋转,最后将点平移回去

# 视图 / 相机变换

在这一步,我的理解过程与老师讲的不同,但都是正确的,并且本质也是相同的

从坐标系变换的角度理解
在世界坐标空间中,所有物体都有相对于世界原点的位置,以及相对于世界坐标轴的旋转。旋转在理解时可以简单考虑欧拉角,即绕某轴旋转多少度,而真正计算时,在内部存储的是四元数。
观察摄像机,若以摄像机的坐标和旋转建立坐标系,摄像机即为坐标原点,摄像机永远看向 -Z 轴。
观察其他物体,其他物体的坐标是在世界坐标空间中的(如果不是,则需要转换到世界空间),而我们要做的就是将其他物体的坐标转换到摄像机空间中。
从局部坐标转换到世界坐标的矩阵更容易描述,所以我们只需要求出这个矩阵,然后应用矩阵的逆即可。注:正交矩阵的逆等于转置

在计算机图形学里,我们约定俗成:所有 非世界基底 的基向量坐标,统一用世界空间作为参考系来描述
世界基底:坐标是自身下的 (1,0,0),(0,1,0),(0,0,1)(1, 0, 0), (0, 1, 0), (0, 0, 1)
模型空间基底、切线空间基底、相机空间基底等所有其他基底:它们的基向量坐标,全部写成 世界空间基底下的坐标值

AA 为世界空间,BB 为相机空间,点 bbBBAA 空间下的坐标,BB 空间的基底为 r,u,fr, u, f,在 BB 中一点 PB=(x,y,z)P_B = (x, y, z) \kern 0.1pt,由于 r,u,fr, u, f 本身就是世界空间下的向量,因此偏移在世界空间中直接为 PA=xr+yu+zf+bP_A = xr + yu + zf + b \kern 0.1pt
将它转换成矩阵形式:

MBA=[rxuxfxbxryuyfybyrzuzfzbz0001]M_{B \rightarrow A} = \begin{bmatrix} r_x & u_x & f_x & b_x \\ r_y & u_y & f_y & b_y \\ r_z & u_z & f_z & b_z \\ 0 & 0 & 0 & 1 \end{bmatrix}

PA=MBAPBP_A = M_{B \rightarrow A} \cdot P_B

可以这样理解:(x,y,z)(x, y, z) 描述的都是在三个基底上的缩放比例,因为基底在世界空间下,基底是向量,默认以原点为起点,所以可以直接获得三个基底上坐标,此时坐标已经在世界空间下,但它原本处于相对于 BB 的位置,所以最后加上 bb 点的平移即可得到 PAP_A

# 投影

# 正交投影

需要先完成相机变换

对于二维投影来说,直接把 ZZ 轴坐标舍弃,就能得到物体在 xyxy 平面上的投影,要把得到的图像平移并且缩放到 [1,1]2[-1, 1]^2 \kern 0.1pt 中,方便之后的计算

对于正交投影来说,视口是个 [l,r],[b,t],[f,n][l, r], [b, t], [f, n] 的长方体,想让他变成 [1,1]3[-1, 1]^3 \kern 0.1pt 只需要 先找到立方体的中心点完成平移,然后将边长 rl,tb,nfr - l, t - b, n - f 缩放到长度 22
此时物体肯定会被拉伸,在之后的视口操作中会恢复拉伸
img

# 透视投影

img

先将 FrustumFrustum 远平面及远平面到近平面之间的所有平面挤压到近平面大小,变成 CuboidCuboid 的样子,然后做一次正交投影
对于除近平面外的任意一个点,通过挤压后该点的高度 yy 要变成和近平面一样的 yy'
从侧面看 FrustumFrustum,如下图,可以形成两个相似三角形,即可得出 y=nzyy' = \dfrac{n}{z} y \kern 0.1pt,同理 x=nzxx' = \dfrac{n}{z} x \kern 0.1pt

img
img

此时我们就能得到矩阵的一部分了,如下图
img

接下来开始补全矩阵。首先要明确:近平面的点不会发生变化、远平面的点 zz 值不会发生变化
img

对于近平面上的点 (x,y,n,1)(x, y, n, 1) 经过矩阵变换后仍为 (x,y,n,1)(x, y, n, 1),同时乘 nn 后得 (nx,ny,n2,n)(nx, ny, n^2, n),由此可得第三行前两个数一定为 00,即 (0,0,A,B)(x,y,n,1)T=n2(0, 0, A, B) (x, y, n, 1)^T = n^2,进而 An+B=n2An + B = n^2
对于远平面上的中间点 (0,0,f,1)(0, 0, f, 1),经矩阵变化后还是中间点 (0,0,f,1)(0, 0, f, 1),同时乘 ff 后得 (0,0,f2,f)(0, 0, f^2, f),可得 (0,0,A,B)(0,0,f,1)T=f2(0, 0, A, B) (0, 0, f, 1)^T = f^2,进而 Af+B=f2Af + B = f^2
由以上两个结果可得 A=n+fA = n + fB=nfB = -nf
至此可解出

Mpersportho=[n0000n0000n+fnf0010]M_{persp \rightarrow ortho} = \begin{bmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & n + f & -nf \\ 0 & 0 & 1 & 0 \end{bmatrix}

另外,内部的点在经过变换后会向原平面靠近。将中间点进行变换后应用齐次除法即可得到这个结果,证明过程略。

# Lecture5 光栅化

现在,所有物体都处在了 [1,1]3[-1, 1]^3 \kern 0.1pt 的立方体中,接下来就要把他画在屏幕上,这一步就叫做光栅化

在做透视投影时候需要将一个四棱梯挤压成正方体,就需要先定义一个视锥体(四棱锥)
img

在这一步我们需要两个重要的变量来定义视椎体:宽高比(Aspect ratio) 和 可视角度(FOV)
近平面与远平面的宽高比相同,垂直和水平的 FOV 可以互相转换
img

要把图像投影到屏幕上就需要先定义屏幕,在图形学中,屏幕就认为是一个装了像素的数组(如数组大小 1920×10801920 \times 1080 \kern 0.1pt)。像素是最小单位,每个像素由 RBG 构成

# 屏幕空间

屏幕坐标系如下图
img
像素的坐标以左下角为准,如图中蓝色像素坐标为 (2,1)(2, 1),像素的中心为 (x+0.5,y+0.5)(x + 0.5, y + 0.5)

做缩放并平移就可以转换到屏幕空间,此时暂时忽略 zz
img
img

# 隔行扫描

以前的显示设备要成像,都是在屏幕上画很多线,画满整个屏幕就形成了一帧画面
隔行扫描:在第一帧只画 1、3、5 等奇数线,在第二帧只画 2、4、6 等偶数线
利用人眼的视觉残留特性,这样人们即发现不了画面的异常,还能使机器工作量减半,如今还有某些视频压缩技术采用了这个思想
隔行扫描会造成严重的画面撕裂,特别是对于高速运动的画面来说

# 现代的一些显示设备介绍

Lecture 05 Rasterization 1 (Triangles) P5 - 32:35

# 三角形

img

光栅化使用最基本的三角形

  • 三角形是最基本的多边形,没有比三角形边更少的多边形
  • 其他多边形都可以拆分为三角形
  • 三角形的三个顶点必定在一个平面内
  • 容易定义三角形的正反
  • 三角形的三个点定义好后,三角形内任意一点可以通过线性的插值来计算得到(重心坐标的插值方法)

# 简单近似采样

给定一个连续的函数 f(x)f(x),当 xx 等于 11 时得到的 f(1)f(1) 就是 11 的采样,所以采样就是把一个函数离散化的过程。只要有一个定义在屏幕空间的函数,那么我们就能算出来不同像素中心的值是多少

给定一个三角形,在像素的中心进行采样,来判断中心是否落在三角形内
img

遍历所有像素开销太大,我们需要计算一个包围盒以减少遍历的开销,蓝色区域就叫做包围盒(轴向包围盒 / BoundingBox / AABB)
img

采样完成后,因为每个像素都是最小单位,像素内的颜色必须一样,所以我们会得到这样一副图。这看起来和初始的三角形差别很大,有明显的锯齿(Jaggies / Aliasing)
img

# Lecture6 反走样

# 采样理论

将到达光学元件上的光的信息离散成像素,对这些像素采样,形成了照片
采样不只发生在位置上还能发生在时间上,对图像在时间上进行采样,形成了视频

# 采样产生的问题

  • 走样
  • 摩尔纹
  • 车轮效应

原因就是信号的变化太快了,以至于采样的速度跟不上

# 反走样处理方法:采样前模糊

img

不能先采样再模糊,只能先模糊再采样

# 频域、时域

频域和时域是对信号或系统的两种不同的表示方式。
频域表示是通过分析信号的频率分布来表示信号的方式。在频域中,信号被分解为一系列不同频率的分量,每个分量对应着信号中的一种特定的周期性成分。
时域表示是通过直接分析信号在时间上的变化情况来表示信号的方式。在时域中,信号的变化被直接表示为在时间上的变化,而不是在频率上的变化。

img

# 傅里叶级数展开

任何一个周期性的函数都可以变成一系列正弦余弦的线性组合和一个常数项

img

# 傅里叶变换

可以把一个函数 f(x)f(x) 通过变化变成 F(x)F(x)F(w)F(w) 还能通过逆变换变成 f(x)f(x)
img

对五个不同频率的函数波形进行采样
通过 f1(x),f2(x)f_1(x), f_2(x) 的采样点,我们可以大致还原出 f1(x),f2(x)f_1(x), f_2(x) 的函数波形
但是从 f3(x)f_3(x) 开始,还原出的波形和原来的函数有较大出入,越往下越明显
这里就可以理解什么叫采样的频率跟不上信号变化的频率了
img

我们对蓝色函数进行采样,得到黑色的函数。但假如原本就有这样一个黑色的函数。我们同时对蓝色和黑色进行采样,两个截然不同的函数,得到的采样结果完全相同,这就被称为走样(Aliases)
img

# 滤波

滤波就是抹掉一些特定的频率
傅里叶变换可以把一个函数从时域变到频域
右边的图像就是左边的照片通过傅里叶变换得到的
右边图像表示的就是有多少信息
中间部分是低频信息,越往外越高频
img

# 高通滤波

在频域空间内完全抹掉低频信号,将结果还原成图像,形成左图
当某一图像的周围发生了剧烈变化(高频),我们就认为他是边界。高频的东西在图像上表示的就是图像的边界
img

# 低通滤波

与高通滤波同理,得到模糊的图像
img

去除高频和低频,只留一部分
img
img

# 卷积

移动窗口(Filter),将窗口中三个数和覆盖信号的三个数做点乘,填到结果中
img
img

# 卷积的一些定理

时域的卷积 = 频域的乘积

可以拿到一幅图直接用一个卷积滤波器进行卷积操作
也可以先傅里叶变换这幅图,将这幅图变到频域,然后将卷积滤波器变到频域上,最后将两者相乘,乘完后得到的频域的结果,将其逆傅里叶变换,变到时域上
img

在时域中图像变大,在频域中会变小:Lecture 06 Rasterization 2 (Antialiasing and Z-Buffering) P6 - 49:06

什么是采样,什么是走样:Lecture 06 Rasterization 2 (Antialiasing and Z-Buffering) P6 - 51:29
img

  • 左边一列是时域,右边一列是频域
  • 对 (a) 图像进行 (c) 的采样,得到 (e)
  • 对应的操作在频域中就是 (b) (d) (f)
  • 时域的采样在频域中就就体现为频域信号的复制

采样不同的间隔,会引起频谱不同间隔进行复制,所相交的部分就是走样
img

# 反走样

如果先采样再模糊:先采样就是把信号的频谱进行搬移,它会有频谱的混叠,这个时候直接采样的结果仍然是混叠的,后面的模糊操作也不会起作用
先模糊再采样:先对图像做模糊(把高频信息拿掉),再采样
img

把高频信息砍掉,砍掉虚线方块以外,在以原始采样频率进行采样,这样频域图像就不会发生混叠,也就没有走样了
img

对覆盖面积求平均,也就是卷积
img

# 多重采样抗锯齿 MSAA (Multisample Anti-Aliasing)

通过更多的样本来近似三角形的覆盖率,并不是提高采样频率
把一个像素划分为几个小点,判断这些小点是否在三角形内,再把结果平均起来,就知道三角形覆盖了这个像素的百分之多少
img
img
img

MSAA 解决的其实是对信号的模糊操作:并不是简单的提高了采样的频率,只是用来做第一步模糊,求三角形的覆盖率
在工业界并不是直接将每个像素平均分了四份,而是采用了一些独特的图形,而且一些边缘的像素还会被复用
img

# 其他抗锯齿

FXAA 快速近似抗锯齿,是一种图像处理技术,它先获得有锯齿的图像,然后找到边界,最后将边界换成没有锯齿的边界
关于 FXAA 可以看一下 Games104 第 7 讲,里面有一小节专门讲抗锯齿 网页链接

TAA 时间抗锯齿,是最常用的图像增强算法之一,这是一种基于着色器的算法,使用运动矢量组合两帧,以确定在何处对前一帧进行采样。在每一帧对屏幕区域内的像素进行一个抖动操作,这样当连续的多个帧的数据混合起来以后,就相当于对每个像素进行了多次采样,他将采样点从单帧分布到多个帧上,使得每一帧并不需要多次采样增加计算量,但 TAA 往往会盲目地跟随移动物体的运动矢量,从而造成屏幕上的细节模糊不清

# Lecture7 着色 Shading

# 画家算法

先画最远的物体,逐渐画近的物体,让近的物体覆盖远的物体
但它不能处理所有情况,例如这张图的三个三角形互相遮挡,没办法定义深度关系,就不能采用画家算法
img

# Z-Buffer

判断每个像素的深度:深度越小,物体越近;深度越大,物体越远
img

在渲染时需要额外存一张深度图。深度图逐像素记录,如果发现新物体的深度小于记录的深度,说明新物体要遮挡住旧物体
img
img

特殊情况

  • 暂时假设不存在深度相同的像素。在浮点数的表示中,两个浮点数完全相同的概率很小。但实际上还是会有这种情况的,此时需要特殊处理
  • Z-Buffer 处理不了透明物体,暂不考虑

# Lambert 光照模型

局部着色:对着色的描述是一个点,只考虑这一点的颜色,并且不考虑阴影
Lambert 是各向同性的

下图中,v,l,nv, l, n 都是单位向量
img

同样的光,以不同角度照上去,明暗不一样
物体表面法向量 nn 和光源方向 ll 的夹角 θ\theta \kern 0.1pt,决定了明暗强度。表面吸收的光能越多,表面越亮。
img

光的能量都集中在一个球壳上,考虑能量守恒,一开始球壳的表面积小,单位面积上光的能量多,光越向外扩散,单位面积的能量就越小
通过球面公式可以计算出,距离光源为 rr 的球壳上,单位面积上能量为 Ir2\dfrac{I}{r^2} \kern 0.1pt
img

由以上分析,我们得到了 diffuse 公式
img
kdk_d \kern 0.1pt 表示该点颜色的反射率,它是一个 RGBRGB 颜色值。若 kd=0k_d = 0 \kern 0.1pt,则该点吸收了所有光,该点表现为黑色;若 kd=1k_d = 1 \kern 0.1pt,则该点反射了所有光,该点表现为白色
Ir2\dfrac{I}{r^2} \kern 0.1pt 表示有多少光到达了着色点
nln \cdot l \kern 0.1pt 为法线与光线的夹角的余弦值,这个值为负时没有意义
img

# Lecture8 Shading, Blinn-Phong reflectance model 着色

# Blinn-Phong 高光

观察的方向越接近镜面反射的方向 越能看到高光
img

当观察方向接近镜面反射方向的时候 = 法线方向 nn 接近于 半程向量 hh,Blinn-Phong 模型只需要这两个值
如果用视线方向 vv 和高光方向 RR 来判断能否看到高光,就是 Phong 模型(计算量大)
img

正常情况下,我们认为高光都是很小很亮的区域。所以要用指数缩小这个区域,随着指数增加,能看到在角度差较小时才可以看到高光,这样就算一个合理的模型。在布林冯模型下,指数选在 100 到 200 之间,高光角度大约在 3~5° 之间
img
img

# 环境光照

一个光线可以弹射很多次,从四面八方打到任何一个点,这些光就是环境光。在这个经验模型中,假设一个点受到的环境光永远都是相同的,强度为 IaI_a,环境光的反照率为 kak_a
img

# Blinn-Phong Reflection Model

环境光 + 漫反射 + 高光
img

# ShadingFrequencies 着色频率

三个球具有完全相同的空间信息,着色频率不同后表现不一样
img

FlatShading(面着色)
img

GouraudShading(顶点着色)
img

PhongShading(像素着色)
img

当几何足够复杂时用 FlatShading 得到的效果也很好;当几何的面数大于像素数量时 FlatShading 的性能比 PhongShading 更差
img

# 如何求逐顶点的法线

找到与顶点相邻的面,将法线根据面积做加权平均
img

# 图形管线 / 实时渲染管线

img

  • 顶点处理:将三维空间的点投影在平面上
  • 三角形处理:将这些点连接形成三角形
  • 光栅化:将三角形离散成为屏幕上的未经处理的像素
  • 着色:给像素上色
  • 后处理:深度缓冲,处理遮挡关系,MSAA 等抗锯齿
  • 以上操作都在硬件中处理好了,也就是 GPU 工作流程

# Shader

现代 GPU 中,这套渲染管线某些部分是可编程的,可以由开发者去定义 顶点 / 像素着色,这部分代码就叫 Shader
如果写的是顶点操作,这个 Shader 就叫做 VertexShader(顶点着色器)
如果写的是像素操作,这个 Shader 就叫做 FragmentShader(片段 / 片元着色器) 或 PixelShader(像素着色器)
img

# TextureMapping 纹理映射

3D 物体的表面其实都是 2D 的,通过这种方式可以和一张图有一一对应的关系,这张图就叫纹理。这张图可以 平铺 / 裁剪 / 拉伸 到任何物体表面
img

纹理上的坐标系通常以 UV 来表示,通常约定 U 和 V 的范围为 [0, 1]
img

纹理不断重复贴到模型上可以得到不错的效果,若纹理能在场景中很自然的无缝衔接,说明这个纹理本身设计的好,这种纹理叫 TilableTextures

# Lecture9 Shading 纹理处理

# 重心坐标

在三角形 ABC 所在的平面中任意一点 (x, y),都可以用三角形三个顶点的线性组合来表示
与三角形在同一平面内的点满足 α+β+γ=1\alpha + \beta + \gamma = 1 \kern 0.1pt
在三角形内的点满足 α,β,γ0\alpha, \beta, \gamma \geq 0 \kern 0.1pt
img

设三角形内一点 P(x,y)P(x, y),连接 PA,PB,PCPA, PB, PC,会形成三个小三角形 AA,AB,ACA_A, A_B, A_CPP 的重心坐标就是小三角形面积占大三角形面积的比
这里有一个特殊的点,三角形重心,三角形重心将三角形划分为三个等面积的小三角形
img

面积计算方式如下

α=(xPxB)(yCyB)+(yPyB)(xCxB)(xAxB)(yCyB)+(yAyB)(xCxB)\alpha = \dfrac{-(x_P - x_B)(y_C - y_B) + (y_P - y_B)(x_C - x_B)}{-(x_A - x_B)(y_C - y_B) + (y_A - y_B)(x_C - x_B)}

β=(xPxC)(yAyC)+(yPyC)(xAxC)(xBxC)(yAyC)+(yByC)(xAxC)\beta = \dfrac{-(x_P - x_C)(y_A - y_C) + (y_P - y_C)(x_A - x_C)}{-(x_B - x_C)(y_A - y_C) + (y_B - y_C)(x_A - x_C)}

γ=1αβ\gamma = 1 - \alpha - \beta

叉积计算方式如下

cross(u,v)=uxvyuyvx\operatorname{cross}(u, v) = u_x v_y - u_y v_x

α=cross(PB,CB)cross(AB,CB)\alpha = \frac{\operatorname{cross}(P - B, C - B)}{\operatorname{cross}(A - B, C - B)}

β=cross(PC,AC)cross(BC,AC)\beta = \frac{\operatorname{cross}(P - C, A - C)}{\operatorname{cross}(B - C, A - C)}

γ=1αβ\gamma = 1 - \alpha - \beta

齐次除法是非线性的,对于三维空间中的点,不能保证其被投影后的重心坐标不变。如果想插值三维空间中的属性,方法一是插值三维空间中的坐标,方法二是将这三个比例恢复到三维空间的权重关系。
这里给出方法二的深度和法线的计算方式,其他同理

差值公式αa0w0+βa1w1+γa2w2αw0+βw1+γw2\text{差值公式} \kern 2pt \frac{\alpha \frac{a_0}{w_0} + \beta \frac{a_1}{w_1} + \gamma \frac{a_2}{w_2}}{\frac{\alpha}{w_0} + \frac{\beta}{w_1} + \frac{\gamma}{w_2}}

透视校正因子Z=1αw0+βw1+γw2\text{透视校正因子} \kern 2pt Z = \frac{1}{\frac{\alpha}{w_0} + \frac{\beta}{w_1} + \frac{\gamma}{w_2}}

深度插值zp=(αz0w0+βz1w1+γz2w2)Z\text{深度插值} \kern 2pt z_p = \left(\alpha \frac{z_0}{w_0} + \beta \frac{z_1}{w_1} + \gamma \frac{z_2}{w_2} \right) \cdot Z

法线插值n=(αn0w0+βn1w1+γn2w2)Z\text{法线插值} \kern 2pt n = \left(\alpha \frac{n_0}{w_0} + \beta \frac{n_1}{w_1} + \gamma \frac{n_2}{w_2} \right) \cdot Z

关于透视校正因子:在透视投影后,正确的线性变量变成了 aw\dfrac{a}{w} \kern 0.1pt,而不是 aa,所以线性插值的是 aw\dfrac{a}{w} \kern 0.1pt,然后再恢复 a=插值(aw)插值(1w)a = \dfrac{\text{插值}(\dfrac{a}{w})}{\text{插值}(\dfrac{1}{w})} \kern 0.1pt

屏幕上的采样点 (x,y)(x, y) 可以用重心坐标算出在纹理中采样的 uvuv,得到对应纹理

# 纹理放大

对于任意一点,可以找到对应纹理上的位置,位置可能不是整数,将位置坐标四舍五入,然后取纹理上的值
当低分辨率纹理应用到高分辨率的屏幕上,纹理就会被拉大。一个 texel 可能会被映射到多个 pixel 上,这会导致明显的锯齿
img

Bilinear 双线性插值:先将横向两点做差值,得到上下两个结果,然后将这两个纵向的值做差值
img

Bicubic 双三次插值:将周围 16 个点进行立方插值

# 纹理缩小

当高分辨率纹理应用到底分辨率的屏幕上,纹理会被缩小,一个屏幕上的像素对应了纹理上的多个纹素,使图像看起来就变得模糊
如果直接简单的使用线性插值进行采样会得到右图,远处有摩尔纹近处有锯齿
img

远处的一个像素会覆盖很大一片的纹理区域,单纯以像素的中心采样是不对的。这其实就是转变为了采样率不足的问题,之前解决采样率不足的问题我们可以使用 MSAA,每个像素内分为若干小像素进行采样,但花费了 512 倍的性能
img

# Mipmap

将原纹理提前用滤波处理得到很多更小的图像,当物体远离相机时,直接查询较小的纹理,得到正确的结果像素。Mipmap 仅适用近似的、正方形的查询。Mipmap 占用的额外空间是原来的 13\dfrac{1}{3} \kern 0.1pt
img
img

要查询屏幕空间内的某像素在纹理空间内占多大区域,可以将自己中心和邻居的中心分别投影到纹理空间内,这样就能知道在纹理空间中该点和邻居点之间的距离,所求的区域可以近似为以 LL 为边长的正方形区域
img

但是会出现不连续的纹理映射,因为查找的纹理都是整数层,比如我们无法直接查询 1.5 层的 Mipmap
img

在两层之间进行插值可以解决这个问题,这称为三线性插值
img
img

在远处产生的图像很模糊,因为 Mipmap 是近似的、正方形的查询,而且三线性插值也是近似的
img

# 各向异性过滤

屏幕上的像素映射到纹理上不一定是正方形,对于不是正方形的 Mipmap 就无法处理。
如下图,对于右边不是正方形但是是比较规则的矩形,我们可以用其他方法提供查询
img

将原图宽度不变长度压缩,长度不变宽度压缩就可以提供矩形的查找,即为各向异性过滤
经常看到的各向异性过滤 x2, x4 等,指的是要生成多少层的压缩图,x2 就是一层,x4 就是两层。占用的空间逐渐向三倍靠拢
img

但各向异性过滤也只是能解决映射在纹理空间是比较规则的矩形的情况,当出现不规则矩形的时候也无法处理
img

EWA 过滤:可以将任意形状拆分为很多大小不同的椭圆,经过多次查询,就能查询出最终的结果。但是代价是需要多次查询的时间

另外:在玩游戏时,可以将各向异性过滤开到最大,这只会占用显存,对算力的消耗很小

# Lecture10 Geometry1 几何

# EnvironmentMap 环境光贴图

纹理本质上就是提供了一个快捷的查询,不只局限于图像,光照也能同理进行查询。光照贴图认为光照是无限远的,忽略了光的位置信息
img

光滑的金属球反射出来的就是环境光。所以我们可以把环境光储存在球上面,并且也能把它展开成平面。但展开后发现球形图的上下会扭曲。虽然我们能描述球上不同的位置,但无法均匀的描述
img

CubeMap: 将信息记录在球的外接立方体,这样信息就变得均匀了
img
img

# BumpMapping 法线贴图

法线贴图是为了在不增加三角形面数的情况下,在着色时显示更多细节。对某一点进行着色时,需要判断该点的法线方向,从而计算光照和颜色。需要从原本的模型表面映射到法线贴图中,查询新的法线位置
img

从高度图获取法线:高度贴图可以实现动态变化,从而获得动态的法线
简单示例:如下图,先算该点切线。切线可以用该点与下一个点的位置差计算出来。将切线逆时针旋转 9090^\circ \kern 0.1pt,求归一化,得到法线
img
二维的贴图中求法线:对 u,vu, v 坐标分别求导,算出切线,旋转得到法线。也就是通过高度的变化程度计算法线
img

法线贴图:法线贴图里每个像素已经存好了,只需要从贴图读取,转到 [1,1][-1, 1],变换到世界空间,这样就可以直接使用。但是法线是固定的,无法像高度贴图那样动态变化

# 位移贴图和环境光遮蔽贴图

位移贴图会改变几何信息,对顶点做位移
img

环境光遮蔽也能预先计算好,存储到纹理中
img

# Shadow mapping

光栅化下对全局光线传输、阴影的处理十分麻烦

  • 使用光栅化绘制阴影
  • 基于图像的算法
    • 不需要场景的几何信息
    • 有走样现象
    • 未被阴影遮挡的点必须同时被光源和相机捕捉到

步骤:

  • 由光线渲染:光源深度图像 -> 阴影图
  • 由摄像机渲染:来自摄像机的标准图像(带深度信息)
  • 投影到光:将视野中的可见点投射回光源
    • 光源可见 -> 颜色
    • 已屏蔽 -> 阴影

问题:

  • 走样、分辨率
  • 数值精度问题:涉及浮点深度值的相等性比较,意味着存在尺度、偏差、公差等问题。
  • 经典的 shadow mapping 只能处理点光源或平行光源这种有明显边界的光源,生成的阴影称之为硬阴影

软阴影与硬阴影

  • 硬阴影:边缘锐利,完全没有光源
  • 软阴影:边缘虚化。阴影靠近物体的位置完全没有光源,形成全影;阴影边缘有部分光源,形成半影

# 隐式几何

隐式表达:隐式几何用来表达该几何点之间的关系。隐式表达的函数很难从函数看出函数形成的面是什么形状的,但可以轻松的知道某一点是否在这个平面上,或物体内外
img

显式表达:给定点的空间坐标 uvuv,遍历所有点就可以在空间中画出该物体,用平面中的 uvuv 去映射到空间中,表示空间上的面。优点就是可以看出函数形成的面是什么形状的,但无法轻松的知道某一点是否在这个平面上
img
img

两种表达各有各的用途,没有好坏之分,根据需要选择

# Constructive Solid Geometry - CSG

属于隐式几何,通过基本几何的布尔运算,得到新的几何
img

DistanceFunctions(距离函数)
不直接描述几何表面,描述空间中的每一点到几何表面的最短距离
阴影处是物体,阴影与留白一起,构成物体所处的空间。AABB 的混合,不仅混合了物体,还混合了空间,最终效果应该是混合后的物体在混合后的空间中的占比一半
例示中比较反直觉的是 blend(A,B)blend(A, B) 所处空间的大小,看起来依旧是 11
img

对于两个物体,Blend 两个物体的距离函数即可得到如下效果
img

对于有向距离场的具体知识可以单独学习,可以参考 BV1Qz4y1p7CE

# 水平集 LevelSet

将函数的表述写在格子上,只要找到所有为 0 的地方就能尝试描述这个物体的表面,概念等同于地理上的等高线
img

# Lecture11 Geometry2 曲线和表面

# 表面

点云:通过大量点来表示表面,只要点足够细、足够多,就能表示任何表面。一般情况下,做三维扫描会得到点云。将点云变成三角形面也是研究点之一。
网格:使用四边形或三角形组成网格,网格是使用的最广泛的表示方法。例如:.obj 文件实际上是文本文件,他将空间中的点、法线、纹理坐标分开存储,然后再记录他们之间的关系。

# Bézier Curves 贝塞尔曲线

一条 由任意 3\geq 3 \kern 0.1pt 个点 定义的曲线。分为起点、终点、中间点,中间点定义切线方向。
直观理解:取 t[0,1]t[0, 1] 在每条线段上做差值,得到新的点,将他们连线并进一步差值,直到最后一个点,这个点就是贝塞尔曲线在 tt 进度下的位置
img
img

计算方法
img

一些性质
img

高阶贝塞尔曲线很难控制,任何一个点就能影响全局,可以使用 Piecewise Bézier Curves 改善

  • 串联许多低阶贝塞尔曲线
  • 每次四个控制点
  • 保证光滑(切线不突变):内部控制点前后的切线点共线
  • 工具 Bezier Curve Edit
    img

几何连续

  • c0c^0 连续:两个函数在值上连续。一个线段的终点 aa 是另一个线段的起点
  • c1c^1 连续:两个函数的一阶导数连续。在 c0c^0 的基础上,aa 左右两个点与 aa 链接后共线,并且与 aa 的距离是 1:11 : 1
  • 以此类推

样条:一条连续曲线,通过给定的点集,并具有一定数量的连续导数(一种受控曲线)
基函数样条(B-splines):Bernstein Polynomial 作为基函数,满足局部性,是贝塞尔曲线的超集。可能是图形学里面最复杂的一部分
深入学习样条:https://www.bilibili.com/video/av66548502

# 贝塞尔曲面

两个不同时间 t (u,v),4x4 个点,四条 4 个控制点的贝塞尔曲线,取同一时间 u 获得四个控制点,用这几个控制点再做一次贝塞尔,取时间 v,即获得最后的曲面上的点
img
img

# Lecture12 Geometry3 几何

# Mesh 网格

  • Mesh subdivision 网格细分
  • Mesh simplification 网格简化
    • 简化后要尽量保持原本的外形
  • Mesh regularization 网格正规化
    • 修改样本分布以提高质量
    • 不丢失模型原本的外观

# Loop Subdivision

细分的应用场景 1:Displacement mapping 位移贴图 需要模型足够细致,于是需要细分,最好是动态细分。(Loop 是发明者名字,跟循环没关系)

需要使用三角形 Mesh

  • 连接三角形三条边的中点,将 1 个三角形分割成 4 个
  • 形状需要改变
    • 根据权重分配新的顶点位置,新老点分别改变

img
img

# Catmull-Clark Subdivision (General Mesh)

Non-quad face:非四边的面
Extraordinary vertex:奇异点,指 degree != 4 的点
img
img
img
img

# 网格简化

目标:在保持整体形状的前提下,减少网格单元的数量
应用:移动端、LOD

边缘坍塌:顶点合并。使用 Quadric Error Metrics(二次误差度量),顶点放在二次误差之和最小的地方

利用二次误差进行简化

  • 迭代的合并分数最小的边缘
  • 需要找到分数最小的边,并且要对其周围的边做更新,所以用优先队列实现
  • 贪心算法,非全局最优

# Lecture13 Ray Tracing

# Why Ray Tracing

  • 光栅化很难处理的部分
    • 全局光照(也有一些技巧,但是不能保证正确性)
    • Soft Shadows 软阴影
    • Glossy reflection 镜面反射
    • Indirect Illumination 间接照明
  • 光栅化:快速近似、质量低
  • 光线追踪:准确、非常慢
    • 更多用于离线渲染

光线:

  • 假设光线沿直线传播(实际物理上不是这样的)
  • 假设光线交叉互不影响(实际物理上不是这样的)
  • 从光源到人眼 与 从人眼到光源 是可逆(光路可逆性)
  • Tracing:从相机出发,向场景投射光线

光线投射:

  • 通过向每个像素投射一条光线来生成图像
    • 从眼睛出发,经过像素点,射向场景
    • 判断最近碰撞物体,Shading 计算颜色
  • 通过向光源发射光线来检查阴影

img

# Whitted-Style Ray Tracing

光线弹射多次(递归),每次折射点都计算一次颜色值,最后累加
img

射线方程:r(t)=o+td0t<\mathbf{r}(t)=\mathbf{o}+t \mathbf{d} \quad 0 \leq t<\infty \kern 0.1pt (o:起点,d:方向)

对于隐式表面
点 p 在表面上有 p:f(p)=0\mathbf{p}: f(\mathbf{p})=0 \kern 0.1pt,射线与表面相交时 p 也在射线上,得到 p=o+tdp = o + td \kern 0.1pt,进而 f(o+td)=0f(\mathbf{o}+t \mathbf{d})=0 \kern 0.1pt,以球体为例:(o+tdc)2R2=0(\mathbf{o}+t \mathbf{d}-\mathbf{c})^{2}-R^{2}=0 \kern 0.1pt (c:中心,R:半径)

对于显示表面(三角网格)
几何上,射线可以做内部(外部)测试(奇数个交点表示在物体内,偶数个交点表示在物体外)。渲染上,直接作用于能见度、阴影、灯光...
方法一:射线与每个三角形相交,理论上没有问题,但是直接这样计算太慢了,需要使用加速结构辅助,例如:KD Tree,Bounding Box
方法二:光线与平面求交 + 交点是否在三角形内。平面由法线 NN 与平面上的一点 pp' 定义,平面方程与光线方程组合,得到 (pp)N=0t=(po)NdN(p - p') \cdot N = 0 \kern 2pt \Rightarrow \kern 2pt t = \dfrac{(p' - o) \cdot N}{d \cdot N} \kern 0.1pttt 为正实数。
方法三:更快捷的计算交点算法,可以直接给出重心坐标:Möller Trumbore Algorithm
img
判断合理:t 为正
判断在三角形内:重心坐标三个系数均为正

# 包围盒

Bounding Volumes 包围盒:使用简单的体积将复杂物体包围,若射线碰不到包围盒,就肯定碰不到里面的物体

常用的包围盒 Axis-Aligned Bounding Box (AABB)

  • 三对平面形成的交集 xmin,xmax,ymin,ymax,zmin,zmaxx_{min}, x_{max}, y_{min}, y_{max}, z_{min}, z_{max} \kern 0.1pt
  • 判断求交:三组进入和退出包围盒的时间 (tmin,tmax)(t_{min}, t_{max}) \kern 0.1pt 如果有交集(即有同时在三对平面内的时间),则与盒子有交
  • tenter=max(tmin),texit=min(tmax)t_{enter} = max(t_{min}), \kern 2pt t_{exit} = min(t_{max}) \kern 0.1pt
  • 如果 tenter<texit&&texit>=0t_{enter} < t_{exit} \kern 4pt \&\& \kern 4pt t_{exit} >= 0 \kern 0.1pt,我们知道射线会在盒子里停留一段时间,所以它们必然相交
  • 当平面与坐标轴垂直时计算更简单

# 均匀空间划分 - 网格

预处理 - 构建加速网格

  • 找到包围盒
  • 创建网格
  • 将每个对象存储在重叠的单元格中

光线求交

  • 按光线遍历顺序逐步遍历网格(Bresenham 线扫描)
  • 对于每个网格单元,测试与该单元中存储的所有对象的交集

注意:

  • 格子不能太密集或稀疏
    • 网格数量 = C * 场景中物体的数量
    • 3D 场景中 C ≈ 27
  • 当物体分布均匀时,比较好用
  • 在 “体育场里的茶壶” 问题中失效

# 空间划分

Oct-tree

  • 八叉树会均匀切分空间
  • 八叉树的每个节点表示一个正方体的体积元素,每个节点有八个子节点,将八个子节点所表示的体积元素加在一起就等于父节点的体积。
  • 当划分的正方体是空的,或者正方体内的物体足够少,即可停止划分
  • 二维空间中称之为四叉树,八叉树是在三维空间的扩展
  • 八叉树与维数有关,高维数会使叉数增多

KD-Tree

  • 每次只沿某一个轴划分
  • 划分空间,存入二叉树
  • 内部节点存储以下信息
    划分轴:x、y、z
    划分位置:沿轴方向划分的平面坐标
    子节点:指向子节点的指针
    叶节点:存储物体
  • 光线从根结点开始向下遍历,若有交点则深入(可能与其子节点都有交点,继续判断),若无交点则离开(不可能与其子节点有交点),碰到叶子节点则与其中所有物体求交

img

KD-Tree 的问题

  • KD-Tree 需要将空间划分成几个包围盒,这些包围盒与三角形的包含情况求解困难(可能出现三角形三个顶点都不在包围盒内,三角形却有一部分在包围盒内的情况)
  • 一个物体可能存在于多个叶子节点中
  • 如果空间切分已经不适合当前物体分布,往往需要重建,代价高

BSP-Tree

  • 二叉空间分割树
  • 一种通过使用超平面作为分割,递归细分空间为两凸集的算法
  • 每次取任意方向将空间分为两部分(很麻烦)
  • 生成 BSP 树可能很耗时

SVH,Sparse Voxel Hierarchy

  • 稀疏体素层级结构
  • 把空间离散成体素网格,然后只存储有东西的体素区域,并用层级结构从粗到细组织它们
  • 适合稀疏体积数据。比如云、烟、雪、雾、SDF、占据场、体素地形,大部分空间是空的,SVH 可以只保存有意义的区域

# 物体划分 - BVH

BVH 是以物体为单位划分空间的二叉树,两个子节点分别存两部分物体的 AABB 包围盒,一个物体只可能出现在一个包围盒中

如何划分很有讲究,不好的划分会使包围盒重合,降低效率

  1. 寻找包围盒
  2. 递归地将对象集合拆分为两个子集
    • 选择要拆分的维度
    • 启发式方法 1:始终选择节点中最长的轴
    • 启发式方法 2:在中间对象的位置分割节点(中位数)
  3. 重新计算子集的边界框
  4. 必要时停止
    • 启发式方法:当节点包含的元素很少时停止(例如 5 个元素)
  5. 在每个叶节点中存储对象
  6. 动态场景下,当物体移动、增加物体、减少物体等情况发生时,需要重建 BVH

节点表示场景中的图元子集,包含子树中的所有对象。内部节点存储包围盒和子节点指针,叶节点存储包围盒和对象列表。
img

遍历

  • 如果未命中,直接返回
  • 如果命中,和下面两个子节点求交
  • 如果已经到了叶子节点,和其中的物体求交找最近
  • 如果两个叶子节点都命中了,则需要返回距离最近的

遍历优化 - 剪枝

  • 记录当前最近交点距离。当命中三角形时,记录命中距离。初始是无穷大,每找到一个更近的物体交点,就更新它
  • 分别计算左右子节点 AABB 的进入距离,距离越小说明射线越早进入这个子节点,越应该优先遍历
  • 如果 节点的 AABB 进入距离 比 当前最近交点距离 远,说明子树里所有物体都不可能更近,所以直接跳过

相比于空间划分法,物体划分法目前有更多应用

# Lecture14 - 15 光的传播理论

国内的图形学课程都没有的部分

Whitted Style Ray Tracing 无法保证正确性

辐射度量学:精准度量光的一系列物理量 Physics-Based

  • 路径追踪的基础
  • 照明测量系统和单位
  • 精确测量光的空间特性
    • radiant flux 辐射通量
    • irradiance 辐照度
    • radiosity 辐射度
    • radiance 辐射亮度
    • intensity 强度
  • 以物理上正确的方式进行照明计算

# 辐射能和辐射通量(功率)

img
img

Radiant energy

  • Radiant energy:电磁辐射的能量
  • 符号:Q
  • 单位:J(Joule焦耳)J \kern 2pt (Joule \text{焦耳}) \kern 0.1pt

Radiant flux (power)

  • Radiant flux (power):单位时间内发射、反射、传输或接收的能量(单位时间能量 -> 功率)
  • Flux:通量:单位时间内流过传感器的光子数
  • 符号定义

    ϕ=dQdt\phi = \dfrac{dQ}{dt}

  • 单位:W(Watt)W \kern 2pt (Watt) \kern 0.1ptlm(lumen流明)lm \kern 2pt (lumen \text{流明}) \kern 0.1pt

Radiant(luminous) Intensity

  • Radiant (luminous) Intensity:点光源单位立体角发射的功率
  • 符号定义

    I(ω)=dΦdωI(\omega) = \frac{\mathrm{d} \Phi}{\mathrm{d} \omega}

  • 单位:W/srW/sr \kern 0.1ptlm/sr=cd(candela坎德拉)lm/sr = cd \kern 2pt (candela \text{坎德拉}) \kern 0.1pt
  • 立体角
    • 弧度:弧长 / 半径
    • 弧度在三维的延伸 -> 立体角:面积 / 半径 ^2

      Ω=Ar2\Omega=\frac{A}{r^{2}}

    • 单位:sr(steradians)sr \kern 2pt (steradians) \kern 0.1pt
    • 单位立体角

      dA=(rdθ)(rsinθdϕ)=r2sinθdθdϕdA = (r d \theta)(r \sin \theta d \phi) = r^2 \sin \theta d \theta d \phi

      dω=dAr2=sinθdθdϕ\mathrm{d} \omega=\frac{\mathrm{d} A}{r^{2}}=\sin \theta \mathrm{d} \theta \mathrm{d} \phi

    • 整个球面的立体角 02π0πsinθdθdϕ=4π\int^{2 \pi}_0 \int^\pi_0 \sin \theta d \theta d \phi = 4 \pi \kern 0.1pt
  • 方向性:用 ω\omega \kern 0.1pt 来表示方向
  • 点光源:

    I=ϕ4πI = \frac{\phi}{4\pi}

Irradiance

  • Irradiance: 单位面积功率
  • 垂直方向光线照射在表面上

    E(x)dΦ(x)dAE(\mathbf{x}) \equiv \frac{\mathrm{d} \Phi(\mathbf{x})}{\mathrm{d} A}

  • 单位:W/m2W/m^2 \kern 0.1ptlm/m2=luxlm/m^2 = lux \kern 0.1pt
  • 垂直方向光线
    • 不垂直的情况需要根据角度计算
    • 兰伯特余弦定律
    • 不适用于点光源的能量散布
    • 无方向性
  • 距离圆心越远,面积越大,而角度不变(Intensity 不变),所以 Irradiance 有衰减

Radiance

  • Radiance: 光在特定方向上传输时,在单位立体角、单位投影面积的辐射通量
  • 描述环境中光的分布
  • 光沿射线传播

    L(p,ω)d2Φ(p,ω)dωdAcosθL(\mathrm{p}, \omega) \equiv \frac{\mathrm{d}^{2} \Phi(\mathrm{p}, \omega)}{\mathrm{d} \omega \mathrm{d} A \cos \theta}

  • 单位:Wsrm2\dfrac{W}{sr \kern 4pt m^2} \kern 0.1ptcdm2=lmsrm2=nit\dfrac{cd}{m^2} = \dfrac{lm}{sr \kern 4pt m^2} = nit \kern 0.1pt
  • 辐射率 = 单位立体角辐照度 = 单位投影面积的强度
    • Radiance = Irradiance per solid angle = Intensity per projected unit area
  • 有方向性
  • 入射辐射亮度是到达表面的、单位立体角上的辐照度
    • 某个小面接受来自某个方向的光线

      L(p,ω)=dE(p)dωcosθL(\mathrm{p}, \omega)=\frac{\mathrm{d} E(\mathrm{p})}{\mathrm{d} \omega \cos \theta}

  • 出射表面辐射亮度是离开表面的、单位投影面积上的辐射强度
    • 某个小面发出向某个方向的光线

      L(p,ω)=dI(p,ω)dAcosθL(\mathrm{p}, \omega)=\frac{\mathrm{d} I(\mathrm{p}, \omega)}{\mathrm{d} A \cos \theta}

Irradiance 和 Radiance 之间的区别就在于是否有方向性

  • Irradiance: 区域 dA 接收到的总功率。四面八方的光线积分起来
  • Radiance: 区域 dA 从方向 dω 接收到的功率

    dE(p,ω)=Li(p,ω)cosθdωE(p)=H2Li(p,ω)cosθdω\begin{aligned} d E(\mathrm{p}, \omega) &=L_{i}(\mathrm{p}, \omega) \cos \theta \mathrm{d} \omega \\ E(\mathrm{p}) &=\int_{H^{2}} L_{i}(\mathrm{p}, \omega) \cos \theta \mathrm{d} \omega \end{aligned}

    • H2H^2 \kern 0.1pt 半球面

# Bidirectional Reflectance Distribution Function (BRDF) 双向反射分布函数

BRDF 描述了从某个方向入射到一个点上的光线的能量会怎么反射,在不同的反射方向上会各分布多少能量(能量一般指功率,即单位时间内的能量)

来自方向 ωiω_i \kern 0.1pt 的辐射强度转化为点 dAdA(某一点)接收到的功率 EE,然后功率 EE 又转化为指向其他方向 ωrω_r \kern 0.1pt 的辐射强度
img

某个点接受 / 发射光线总能量:Irradiance
Differential irradiance incoming:

dE(ωi)=L(ωi)cosθidωid E\left(\omega_{i}\right)=L\left(\omega_{i}\right) \cos \theta_{i} d \omega_{i}

某个点从某个方向接受 / 向某个方向发射光线能量:radiance
Differential radiance exiting:

dLr(ωr)d L_{r}\left(\omega_{r}\right)

BRDF 的几个细节

  • 针对一个输入源
  • 描述不同方向的输出
  • 定义了不同材质

BRDF 表示从每个入射方向反射到每个出射方向的光量 ωrω_r \kern 0.1pt
img

fr(ωiωr)=dLr(ωr)dEi(ωi)=dLr(ωr)Li(ωi)cosθidωi[1sr]f_{r}\left(\omega_{i} \rightarrow \omega_{r}\right)=\frac{\mathrm{d} L_{r}\left(\omega_{r}\right)}{\mathrm{d} E_{i}\left(\omega_{i}\right)}=\frac{\mathrm{d} L_{r}\left(\omega_{r}\right)}{L_{i}\left(\omega_{i}\right) \cos \theta_{i} \mathrm{d} \omega_{i}}\left[\frac{1}{\mathrm{sr}}\right]

# The Reflection Equation 反射方程

img

针对一个输出源(着色点),积分所有方向输入源(光照)的 BRDF,获得最后的输出

Lr(p,ωr)=H2fr(p,ωiωr)Li(p,ωi)cosθidωiL_{r}\left(\mathrm{p}, \omega_{r}\right)=\int_{H^{2}} f_{r}\left(\mathrm{p}, \omega_{i} \rightarrow \omega_{r}\right) L_{i}\left(\mathrm{p}, \omega_{i}\right) \cos \theta_{i} \mathrm{d} \omega_{i}

递归方程

  • 不只有光源才是输入源,其他物体的反射光也有可能是输入源
  • 递归的计算方式,计算量很大

# The Rendering Equation 渲染方程(绘制方程)

在反射方程中添加发射项,使其更具通用性

Lo(p,ωo)=Le(p,ωo)+Ω+Li(p,ωi)fr(p,ωi,ωo)(nωi)dωiL_{o}\left(p, \omega_{o}\right)=L_{e}\left(p, \omega_{o}\right)+\int_{\Omega^{+}} L_{i}\left(p, \omega_{i}\right) f_{r}\left(p, \omega_{i}, \omega_{o}\right)\left(n \cdot \omega_{i}\right) \mathrm{d} \omega_{i}

  • 包括了物体自己会发光的情况,包括了所有光线的传播情况
  • 假设所有方向都指向外侧
  • H2H^2 \kern 0.1ptΩ+\Omega^{+} \kern 0.1pt 都代表半球

单个点光源
img

多个点光源加起来
img

面光源取积分
img

考虑其他物体反射的光线(光源也包括在内),递归
img

第二类弗雷德霍姆积分方程(已通过数值方法广泛研究)及其规范形式

Lr(x,ωr)=Le(x,ωr)+ΩLr(x,ωi)f(x,ωi,ωr)cosθidωiL_{r}\left(x, \omega_{r}\right)=L_{e}\left(x, \omega_{r}\right)+\int_{\Omega} L_{r}\left(x^{\prime},-\omega_{i}\right) f\left(x, \omega_{i}, \omega_{r}\right) \cos \theta_{i} d \omega_{i}

简写为如下形式

I(u)=θ(u)+l(v)K(u,v)dvI(u)=\theta(u)+\int l(v)K(u,v)dv

通过算符的抽象还可极度简化成如下形式:L = E + KL(K:反射算符)其中 L 为未知数

  • 可以离散化为一个简单的矩阵方程或联立线性方程组(L、E 是向量,K 是光传输矩阵)
    img
    img
    img
  • 光栅化的着色过程只有直接光照(间接光照需要间接计算)
  • 全局光照:直接和间接光照的集合
    • 会收敛到一个亮度
    • 在 Lecture16 中会进一步说明

# Probability Review 概率论回顾

  • 随机变量 XX: 可能取很多数值的变量
  • 随机变量的分布函数 Xp(x)X \sim p(x) \kern 0.1pt: probability density function (PDF) 取不同数值的概率
    • 比如,uniform PDF, 骰子
    • 概率 pip_i \kern 0.1pt 的数值非负,和为 1,注意和 p (x) 的概念不一样,是 p (x) 的输出。
  • 期望:从随机分布中反复抽取样本所得到的平均值 E[X]=i=1nxipiE[X]=\sum_{i=1}^{n} x_{i} p_{i} \kern 0.1pt

连续情况下

  • 随机变量的分布函数 Xp(x)X \sim p(x) \kern 0.1pt 是连续的 Probability Distribution Function (PDF)
  • 某一个 x 对应的概率 = p (x) dx(细长条)
  • 概率密度函数的性质 p(x)0p(x) \geq 0 \kern 0.1pt and p(x)dx=1\int p(x) d x = 1 \kern 0.1pt
  • 期望:E[X]=xp(x)dxE[X]=\int x p(x) d x \kern 0.1pt

随机变量的函数

  • 如果某个随机变量 Y 是随机变量 X 的函数:Y=f(X)Y=f(X) \kern 0.1pt
  • 期望的关系:E[Y]=E[f(X)]=f(x)p(x)dxE[Y]=E[f(X)]=\int f(x) p(x) d x \kern 0.1pt

# Lecture16 蒙特卡洛路径追踪

# 蒙特卡洛积分 Monte Carlo Integral

一种近似积分方法:Monte Carlo Integral

  • 有时候定积分很难精确计算(解析式求不出),使用数值方法
  • 黎曼积分:分解成很多个长方形来积分
  • Monte Carlo 积分:随机采样
  • 用任意一个 PDF 去采样,都可以用下面的式子求出积分的近似数值

    f(x)dx=1Ni=1Nf(Xi)p(Xi)Xip(x)\int f(x) \mathrm{d} x=\frac{1}{N} \sum_{i=1}^{N} \frac{f\left(X_{i}\right)}{p\left(X_{i}\right)} \quad X_{i} \sim p(x)

  • N: 采样数
  • 样本越多,结果越准
  • 在 x 上采样的样本就要在 x 上积分

# 路径追踪 Path Tracing

Whitted-Style Ray Tracing 是不正确的

  • 始终进行镜面反射 / 折射
  • 在漫反射表面上停止
  • 这些简化不一定正确
    • 对于光滑材料,光线应该反射到镜面对应的方向附近一圈,而非单镜面反射
    • 漫反射材质之间没有反射:漫反射不应停下,否则少了很多光
    • 缺少渗色:由于漫反射,颜色流到了其他面上

渲染方程式是正确的(部分简化光线的性质),包括了对半球面的积分,还有递归

Lo(p,ωo)=Le(p,ωo)+Ω+Li(p,ωi)fr(p,ωi,ωo)(nωi)dωiL_{o}\left(p, \omega_{o}\right)=L_{e}\left(p, \omega_{o}\right)+\int_{\Omega^{+}} L_{i}\left(p, \omega_{i}\right) f_{r}\left(p, \omega_{i}, \omega_{o}\right)\left(n \cdot \omega_{i}\right) \mathrm{d} \omega_{i}

用数值方法求解该积分:蒙特卡罗方法
img

关于 pdfpdf
这里默认 pdfpdf 在整个面积区域内是均匀分布的常数 A(pdf)dA=1\int_A (pdf) dA = 1 \kern 0.1pt,可以把它从积分里提出来 pdfAdA=1pdf \int_A dA = 1 \kern 0.1pt,因为 AdA=A\int_A dA = A \kern 0.1pt,所以有 pdfA=1pdf \cdot A = 1 \kern 0.1pt,所以 pdf=1Apdf = \dfrac{1}{A} \kern 0.1pt
只有在均匀采样面积时才能得到这个结果,如果 pdfpdf 不是常数,那么只能说 Apdf(x)dA=1\int_A pdf(x) dA = 1 \kern 0.1pt,不能直接推出 pdf(x)=1Apdf(x) = \dfrac{1}{A} \kern 0.1pt

只考虑直接光照

Lo(p,ωo)=Ω+Li(p,ωi)fr(p,ωi,ωo)(nωi)dωi1Ni=1NLi(p,ωi)fr(p,ωi,ωo)(nωi)p(ωi)\begin{aligned} L_{o}\left(p, \omega_{o}\right) &=\int_{\Omega^{+}} L_{i}\left(p, \omega_{i}\right) f_{r}\left(p, \omega_{i}, \omega_{o}\right)\left(n \cdot \omega_{i}\right) \mathrm{d} \omega_{i} \\ & \approx \frac{1}{N} \sum_{i=1}^{N} \frac{L_{i}\left(p, \omega_{i}\right) f_{r}\left(p, \omega_{i}, \omega_{o}\right)\left(n \cdot \omega_{i}\right)}{p\left(\omega_{i}\right)} \end{aligned}

同时考虑间接光照:递归计算
img

递归的问题:光线数量爆炸
解决方式:每次只射出一条光线
用每次只射出一条光线来做蒙特卡洛积分的方法,就叫路径追踪。之所以称之为路径追踪,就是因为它计算的是从摄像机到光源的一条路径
img

只有一条光线的问题:噪声非常大
解决方式:每个像素取多个不同路径计算,最后取平均或加权 -> 射线生成
img

递归的问题:递归停不下来

  • 解决方案 1:限制层数
    • 缺陷:能量损失
  • 解决方案 2:Russian Roulette (RR)
    • 设置概率 PP,设积分为 LoLo,让函数的返回结果为 Lo/PLo / P,判定失败 (1P)(1 - P) 时返回 00
      期望 E=P(Lo/P)+(1P)0=LoE = P * (Lo / P) + (1 - P) * 0 = Lo 结果正好是 LoLo
    • 结果正确

img

RR 的问题:不高效

  • 原因:RR 是均匀采样,但是环境当中光线的来源往往不是均匀的。如果我们对阴影点处的半球进行均匀采样,就会浪费很多光线。
  • 解决方案:采样光源
    • 蒙特卡洛允许任何方式的采样,只要有对应的 x 和 p 就行
    • 对光源积分是个很高效的想法,但是积分的对象和 “在 x 上采样的样本就要在 x 上积分” 的要求不匹配 -> 只需要找到光源对应 ωi\omega_i \kern 0.1pt 的关系就行 -> 改变积分域

img

Lo(x,ωo)=Ω+Li(x,ωi)fr(x,ωi,ωo)cosθdωi=ALi(x,ωi)fr(x,ωi,ωo)cosθcosθxx2dA\begin{aligned} L_{o}\left(x, \omega_{o}\right) &=\int_{\Omega^{+}} L_{i}\left(x, \omega_{i}\right) f_{r}\left(x, \omega_{i}, \omega_{o}\right) \cos \theta \mathrm{d} \omega_{i} \\ &=\int_{A} L_{i}\left(x, \omega_{i}\right) f_{r}\left(x, \omega_{i}, \omega_{o}\right) \frac{\cos \theta \cos \theta^{\prime}}{\left\|x^{\prime}-x\right\|^{2}} \mathrm{d} A \end{aligned}

  • 可以考虑由两部分产生的辐射
    • 直接光照:光源直射,无需 RR
    • 间接光照:间接反射,RR
  • 另外还需检测光源和目标点中间有没有遮挡(在下面的伪代码中没有写这一点)

img

当前只考虑面光源。点光源是一个更复杂的情况,很难做正确,可以考虑将点光源做成很小的面光源

Path Tracing 确实很难:物理、概率、微积分、代码……,但这是现代化图形学的一个根基,几乎 100% 正确,a.k.a. 照片级写实
img

Ray tracing 概念的区分

  • 上一篇讲的 Ray tracing 是 Whitted-style ray tracing
    现代所说的 Ray tracing 是指所有光线传播方法的集合
  • 现代化光传输的一般解决方案
    • (Unidirectional & bidirectional) path tracing
    • Photon mapping
    • Metropolis light transport
    • VCM / UPBP …

课上没讲的:

  • 对半球进行均匀采样?一般来说,如何对任何函数进行采样?
  • 蒙特卡罗积分允许任意概率密度函数(pdf),选择什么样的概率密度函数是最好的?
    • 重要性采样理论 importance sampling
  • 随机数重要吗?
    • 是的。蓝噪声采样、随机采样、低差异序列
  • 可以对半球和光线进行采样,可以将它们合并吗?
    • 多重重要性采样
  • 像素的辐射亮度是穿过该像素的所有路径辐射亮度的平均值
    • 像素重建滤波器
  • 像素的亮度就是像素的颜色吗?
    • 不是。 gamma correction(radiance 到 color 的对应关系), curves (HDR), color space

# Lecture17 Materials and Appearances 材质和外观

# 漫反射、镜面反射、折射材质

Diffuse / Lambertian Material (BRDF) 漫反射材质
img

Lo(ωo)=H2frLi(ωi)cosθidωi=frLiH2cosθidωi=πfrLi\begin{aligned} L_{o}\left(\omega_{o}\right) &=\int_{H^{2}} f_{r} L_{i}\left(\omega_{i}\right) \cos \theta_{i} \mathrm{d} \omega_{i} \\ &=f_{r} L_{i} \int_{H^{2}} \cos \theta_{i} \mathrm{d} \omega_{i} \\ &=\pi f_{r} L_{i} \end{aligned}

fr=ρπf_{r}=\frac{\rho}{\pi}

  • 能量守恒:进出的 irradiance 相同(总量)
  • 漫反射:出的 radiance 均匀 -> fr=cf_r = c \kern 0.1pt (常量)
  • 假设入射光和出射光都是均匀的 -> Li=LoL_i = L_o \kern 0.1pt
  • ρ\rho \kern 0.1pt : albedo (反射率),0 ~ 1(值为 1 时完全不吸收能量)
  • 所以,在 Cook-Torrance BRDF 中计算 diffusediffuse 项时需要除以 π\pi \kern 0.1pt

Glossy material (BRDF)
铜、铝、银等金属
img

Ideal reflective / refractive material (BSDF)
雪、水、皮肤等
img

反射定律
img

Specular Refraction 折射
折射定律(Snell’s Law)
img
img

  • 白光分解成彩虹:折射率不同
  • Caustics (不合适的翻译:焦散,因为只有聚焦才能被看到)
  • 全反射:折射不可能发生的情况下,当 入射介质折射率 > 出射介质折射率 时可能发生
    • Snell’s Window / Circle: 在水下往上看只能看到锥形的一片区域有光
  • BSDF (散射) = BRDF (反射) + BTDF (折射)
    • BSDF (Bidirectional scattering distribution function) 双向散射分布函数

Fresnel Reflection 菲涅耳反射
绝缘体
img
导体
img

  • Fresnel Reflection / Term (菲涅耳项)
    • 描述了光线在不同角度下反射与折射的比例
    • 反射率取决于入射角(以及光的偏振)
    • 与法线方向越接近,越少光被反射
  • 精确计算:需要考虑极化情况
    近似:Schlick’s approximation
    img

    R(θ)=R0+(1R0)(1cosθ)5R0=(n1n2n1+n2)2\begin{aligned} R(\theta) &=R_{0}+\left(1-R_{0}\right)(1-\cos \theta)^{5} \\ R_{0} &=\left(\frac{n_{1}-n_{2}}{n_{1}+n_{2}}\right)^{2} \end{aligned}

# Microfacet Material 微表面材质

基于假设:离得足够远的时候,微小的东西往往看不见,看见的是最后汇聚起来总体的样子

粗糙表面

  • 宏观尺度:平坦而粗糙
  • 微观尺度:凹凸不平且镜面反射

表面的各个组成部分都像镜子一样

  • 称为微面
  • 每个微面都有其自身的法线

Microfacet BRDF 微表面模型

  • 图例:微面法线的分布
    img
  • BRDF 计算:

    f(i,o)=F(i,h)G(i,o,h)D(h)4(n,i)(n,o)f(\mathbf{i}, \mathbf{o})=\frac{\mathbf{F}(\mathbf{i}, \mathbf{h}) \mathbf{G}(\mathbf{i}, \mathbf{o}, \mathbf{h}) \mathbf{D}(\mathbf{h})}{4(\mathbf{n}, \mathbf{i})(\mathbf{n}, \mathbf{o})}

    • F(i,h)\mathbf{F}(\mathbf{i}, \mathbf{h}) \kern 0.1pt: 菲涅尔项,描述了光线在不同角度下反射与折射的比例
    • G(i,o,h)\mathbf{G}(\mathbf{i}, \mathbf{o}, \mathbf{h}) \kern 0.1pt: 几何函数,它描述了微平面之间的相互遮挡。几乎和表面平行的光线方向(掠射角),遮挡损耗很大
    • D(h)\mathbf{D}(\mathbf{h}) \kern 0.1pt: 法线分布函数,它描述了有多少比例的微平面法线正好对准了半矢量
  • 效果十分强大
  • 最先进的 State-of-the-art
  • PBR:Physically Based Rendering / Shading
  • 是统称,有很多不同的模型
  • 缺点:Diffuse 比较少,有时需要手动加
  • 更多解释可以看这篇文章

# Isotropic / Anisotropic Materials (BRDFs) 各向同性 / 各向异性

关键区别:底层表面的方向性
img

反映到 BRDF 上,各向异性的 BRDF 有如下性质

fr(θi,ϕi;θr,ϕr)fr(θi,θr,ϕrϕi)f_{r}\left(\theta_{i}, \phi_{i} ; \theta_{r}, \phi_{r}\right) \neq f_{r}\left(\theta_{i}, \theta_{r}, \phi_{r}-\phi_{i}\right)

  • 方位角不一样时,BRDF 不保持一致,反射取决于方位角
  • 锅底 -> 辐射状高光(来自 VRay 渲染器的一张例图)
  • Nylon(编织), Velvet(天鹅绒,可以人为造成各向异性)

BRDF 的属性

  • 非负 Non-negativity:描述能量分布
  • 线性 Linearity:可加,组合
  • 可逆性 (Reciprocity principle):交换入射和出射,结果一致
  • 能量守恒 Energy conservation:能量要么一致,要么变小(被吸收),收敛
  • 各向同性

    fr(θi,ϕi;θr,ϕr)=fr(θi,θr,ϕrϕi)f_{r}\left(\theta_{i}, \phi_{i} ; \theta_{r}, \phi_{r}\right) = f_{r}\left(\theta_{i}, \theta_{r}, \phi_{r}-\phi_{i}\right)

    从可逆性可得

    fr(θi,θr,ϕrϕi)=fr(θr,θi,ϕiϕr)=fr(θi,θr,ϕrϕi)f_{r}\left(\theta_{i}, \theta_{r}, \phi_{r}-\phi_{i}\right)=f_{r}\left(\theta_{r}, \theta_{i}, \phi_{i}-\phi_{r}\right)=f_{r}\left(\theta_{i}, \theta_{r},\left|\phi_{r}-\phi_{i}\right|\right)

    于是不用考虑方位角的绝对值,便于储存

# Measuring BRDFs

动机

  • 不用费力推模型,自动包含所有存在的散射效应
  • 能够使用真实世界的材质进行精确渲染。可用于产品设计、特效等领域……
  • 实际和推算出来的经常会有很大差距

方法:

  • 基于图像的双向反射分布函数测量
    给定入射出射,参数十分精确,直接测量,枚举
    img
  • 实际存在:UCSD 的 gonio reflectometer 测角反射仪
  • 提高效率
    • 各向同性表面将维度从 4D 降低到 3D
    • 可逆性将测量次数减少一半
    • 只采样一部分,剩余部分插值计算出来(猜测)
    • 巧妙的光学系统……
  • 挑战
    • 掠射角的精确测量。由于菲涅耳效应,这一点很重要
    • 采用足够密集的采样进行测量,以捕捉高频镜面反射
    • 逆反射,空间变化的反射率

# 存储 BRDF

理想的品质

  • 紧凑表示
  • 准确呈现测量数据
  • 对任意方向对进行高效评估
  • 可用于重要性抽样的良好分布

一种方式:表格表示

  • 将样品以均匀间隔的方式储存在 (θi,θr,ϕrϕi)\left(\theta_{i}, \theta_{r},\left|\phi_{r}-\phi_{i}\right|\right) \kern 0.1pt
  • 改进:重新参数化角度以更好地匹配镜面反射率
  • 通常需要将测量值重新采样到表中
  • 极高的存储需求
  • 实例:MERL BRDF Database [Matusik et al. 2004] 90 * 90 * 180 measurements

# Lecture18 Advanced Topics in Rendering 渲染高级主题

# Advanced Light Transport

  • 无偏光传输方法
    • Bidirectional path tracing (BDPT)
    • Metropolis light transport (MLT)
  • 偏光传输方法
    • Photon mapping
    • Vertex connection and merging (VCM)
  • 实时辐射度算法(VPL / 多种光照方法)
    • 间接光表示为很多小光源

有偏蒙特卡罗估计 与 无偏蒙特卡罗估计

  • 无偏
    • 无偏就是对积分值的 “估计” 的 “期望” 等于积分值真实值。也就是在蒙特卡洛过程中,多次采样的 “样本均值” 在采样数量趋于无穷时等于积分值真实值。无偏蒙特卡罗方法不存在任何系统误差。
    • 无论取多少样本,期望永远是对的
  • 有偏:其他情况
    • 一种特殊情况是,当使用无限多个样本时,期望值会收敛到正确值 —— 这是一致的
    • 有偏,但能收敛到无偏

# 无偏光传输方法

# Bidirectional path tracing (BDPT)

  • 追踪来自相机和光源的子路径(半路径)
  • 连接两条子路径的端点 半路径末端互相连接,形成通路
  • 好处:适用于光传输过程在光侧较为复杂的情况
    • 比如,光源第一跳大多是 diffuse
  • 缺点:实施起来很困难,而且速度很慢。能做出来基本能自己写渲染器了

# Metropolis light transport (MLT)

  • 马尔可夫链蒙特卡罗法 (MCMC) 应用
    • 马尔可夫链帮助采样
    • 马尔可夫链:根据当前样本,根据一个概率分布,生成下一个相近的样本
    • 从当前示例跳转到下一个示例,其中包含一些 PDF 文件
  • 可以做到以任意函数为 PDF 生成样本
  • 核心思想:对现有路径进行局部扰动以获得新路径。有一个路径的情况下,可以生成相似的路径
  • 好处
    • 非常擅长局部探索复杂的光路。有了种子,就能找到更多相似的
    • 焦散,间接光源
  • 缺点
    • 收敛速度难以估计。Monte Carlo 可以估计方差,可以量化
    • 不保证每个像素的收敛速度相同
    • 因此,通常会产生 “不理想” 的结果,看上去比较脏,通常不用于渲染动画

# 偏光传输方法

# Photon Mapping

  • 一种有偏的方法和一种两阶段方法
  • 非常擅长处理镜面反射 - 漫反射 - 镜面反射 (SDS) 路径和生成焦散效果

很多种实现方法,这里是其中一种
Photon Mapping — Approach (variations apply)

  • 第一阶段 —— 光子追踪
    • 光源出发,从光源发射光子,使光子四处反射,最终在漫反射表面上记录光子
  • 第二阶段 —— 光子收集(最终收集)
    • 从摄像机发射子路径,使其四处反弹,直到击中漫反射表面
  • 计算 —— 局部密度估计
    • 想法:光子较多的区域应该更亮。
    • 对于每个阴影点,找出最近的 N 个光子(通过树状结构实现算法,N 是固定的)。计算它们覆盖的表面积,然后计算 光子密度 = 光子数量 / 面积
    • 光子数量少:面积大,噪声大
    • 光子数量大:模糊
  • 模糊是因为有偏
    • 局部密度估计 dN /dA != ΔN / ΔA 光子密度估计在数量趋向无限时才与真正光子密度相等,所以虽然有偏,但是一致

有偏和无偏的实用辨别方法

  • 在渲染中 有偏 == 模糊
  • 一致:虽然有偏,但只要样本足够多,最终会收敛到不模糊的结果

# Vertex Connection and Merging (VCM)

  • BDPT 与光子映射的结合
  • 核心思想:如果 BDPT 中的子路径的端点无法连接但可以合并,则不要浪费这些子路径,而是使用光子映射来处理附近 “光子” 的合并。

img

  • 比如,x2x_2 \kern 0.1ptx2x^{*}_{2} \kern 0.1pt 在同一个面上,但是没有重合,按照 BDPT,这种就是浪费
  • 但是 VCM 决定利用这种情况,把其中一半光路转化成光子,进行 Photon Mapping 一样的计算

# 实时辐射度算法 Instant Radiosity (IR)

  • 又称多光方法
  • 核心思想:被照亮的表面可以被视为光源
  • 模拟从光源发出光线,打到的地方相当于二级光源。如果此时 Sample 某个场景点的颜色,那么遍历这些二级光源,叠加计算即可
  • 拍摄多条子路径的光,并假设每条子路径的终点都是一个虚拟点光源(VPL),然后使用这些 VPL 像往常一样渲染场景
  • 优点:速度快,通常在漫反射场景下效果良好
  • 缺点:
    • 当 VPL 靠近阴影点时,会出现尖峰
    • 无法处理光滑材料

工业界:Path Tracing,不高端,但可靠

# Advanced Appearance Modeling

外观 -> 材质 -> 双向反射分布函数

非表面模型

  • 散射介质
  • 毛发 / 皮毛 / 纤维(BCSDF)
  • 颗粒状材料

表面模型

  • 半透明材料 (BSSRDF)
  • 布料
  • 详细材质 (non-statistical BRDF)

程序化生成外观

  • 通过程序生成

# 非表面模型

# 散射介质

  • 散射介质指的是光必须穿透的任何物理体积 —— 如雾、烟、水或半透明材料,并在过程中与粒子相互作用
  • 光在穿过介质的任何一点上,都可能被(部分)吸收和散射
  • 散射:利用相位函数描述参与介质中任意点 x 处光散射的角度分布。规定如何散射。
    img
  • 如何渲染
    • 随机选择一个方向弹跳
    • 随机选择一段直线距离
    • 在每个 “阴影点”,连接到光源

# 头发

关键点:光线和曲线的作用
有两种高光:无色 / 有色高光

Kajiya-Kay Model:简单模型

  • 一根光线,打到圆柱(头发)上,散射出一个圆锥上,同时向四面八方散射,像是 Diffuse + Specular
  • 效果不好,很假
    img
    img

Marschner Model:广泛使用

  • 把头发看作玻璃状圆柱体,有色素,会吸收能量
  • 三种光相互作用类型:R、TT、TRT(R:反射,T:透射)
  • 可能的扩展: TRRT
  • 一部分直接反射 R
  • 一部分穿进头发,再穿出 TT
  • 一部分穿进,内部反射,再穿出 TRT
  • 效果不错
  • 只是单次散射

img
img

# 毛皮外观

不能直接把头发模型用到动物毛发上,两者有差别
img

动物毛发髓质(Medulla)很大,头发忽略了不明显,但是动物毛发忽略之后很明显
Double Cylinder Model:描述了头发和髓质的双层结构

  • R,TT,TRT
  • TTs,TRTs:经过髓质,被散射过的光

img
img
img

其他

  • 这个模型是 闫令琪 发明的
  • 应用:[War for the Planet of the Apes. 2017 movie] (2018 Oscar Nominee for Best Visual Effects)
  • 应用:[The Lion King (HD). 2017 movie] (2019 Oscar Nominee for Best Visual Effects)

# 颗粒状材质

img

避免对所有颗粒进行显式建模的方法:程序定义

目前还没有很好的渲染优化

# 表面模型

# Subsurface Scattering 次表面散射,BSSRDF

Translucent: 不仅仅是半透明,光线在内部还会有折射,比如玉石,水母,牛奶,人耳

物理上:Subsurface Scattering 次表面散射

  • 许多表面的视觉特征是由光线从不同位置射出和射入造成的
  • 违反了 BRDF -> BSSRDF 的一个基本假设

BSSRDF:BRDF 的推广;由于入射到另一点的辐照度差异而导致的某一点的出射辐射度 S(xi,ωi,xo,ωo)S\left(x_{i}, \omega_{i}, x_{o}, \omega_{o}\right) \kern 0.1pt 进来和出去的点不一定一样

渲染方程的推广:对曲面上的所有点和所有方向进行积分。对表面其他地方进入的光线也要考虑,过于复杂

L(xo,ωo)=AH2S(xi,ωi,xo,ωo)Li(xi,ωi)cosθidωidAL\left(x_{o}, \omega_{o}\right)=\int_{A} \int_{H^{2}} S\left(x_{i}, \omega_{i}, x_{o}, \omega_{o}\right) L_{i}\left(x_{i}, \omega_{i}\right) \cos \theta_{i} \mathrm{d} \omega_{i} \mathrm{d} A

用两个光源模拟次表面散射:Dipole Approximation [Jensen et al. 2001]: Approximate light diffusion by introducing two point sources.

# Cloth: Fiber 布料

布:由纤维缠绕而成

  • 每一根纱线是由纤维缠绕而成
  • 每一股毛线是由纱线缠绕而成
  • 规模很大

作为表面渲染

  • 根据编织图案,计算整体性能
  • 使用 BRDF 进行渲染,根据不同的织法,给不同的 BRDF
  • 但是布料并不仅仅是表面,天鹅绒那样的效果无法展现

作为散射介质渲染

  • 单根纤维的特性及其分布 -> 散射参数
  • 空间中分布的体积 -> 细小的格子,对每个格子里布料的性质进行采样,转化成对光线的渲染(像对云的渲染那样)
  • 计算量大

作为实际纤维渲染

  • 显式渲染每一根纤维
  • 计算量大

# Detailed Appearance 详细材质

看起来不太真实,因为太过完美。真实情况下,有很多复杂,不完美的东西

回顾 Microfacet BRDF

  • Surface = Specular microfacets + statistical normals
  • 法线分布 (NDF) 用了正态分布,其实没有那么完美
  • 把法线分布改的复杂一点,就会获得更复杂的结果
  • 法线贴图 200k x 200k,获得很好的效果,但是运算量爆炸(甚至一张图要一个月)
  • 在法线分布复杂的情况下,很难建立 valid 的光线通路(光源 -> 表面 -> 摄像机)

img

解决方案:像素上的双向反射分布函数 (BRDF)

  • 一个像素对应了一块表面,把整块范围内的法线分布整合起来获得(P-NDF),以此简化计算
  • 小范围的 P-NDF 会有很多奇妙的样子

img

应用

  • 精细 / 闪亮材质
  • 海绵波光粼粼的效果

# Recent Trend: Wave Optics 最新趋势:波动光学

之前所有的计算都把光线当作粒子来计算,但光具有波粒二象性,有很多只有在把光当作波的时候才会有的性质就会被忽略。

img

波动光学计算 BRDF:结果与几何光学类似,但不连续(干涉导致),不同波长也不一样

# Procedural Appearance 程序化生成材质

明确地或隐含地,不一定需要真的生成,可以查询
问题:三维模型,三维材质,存储量爆炸

在不考虑纹理的情况下定义细节

  • 动态计算噪声函数
  • 3D 噪声 -> 内部结构是否被切割或损坏
  • 阈值处理(噪声 -> 二值噪声)

复杂的噪声函数可能非常强大。

  • 柏林噪声
    • 生成地形
    • 木头的三维生成
  • ...

Houdini: 程序化生成材质 (Explicitly)

# Lecture19 Cameras, Lenses and Light Fields 相机、镜头和光场

成像 = 合成 + 捕获

  • 合成:光栅 | 光线追踪
  • 捕获:捕捉真实世界来成像
    • 最典型:相机
    • 瞬态成像:研究光在极短时间内的传播
    • 计算摄影:计算成像学

相机的原理

  • 小孔成像
    • 针孔相机 Pinhole Camera
      无虚化
      全部都是清晰的
  • Lens 透镜成像

Shutter 快门:控制光进入相机
Sensor 传感器:曝光期间累积辐照度

为什么不能使用无镜头传感器?

  • 任何一个点都可能收集到不同方向过来的光
  • 传感器记录辐照度

# Field of View (FOV) 视场

img

FOV=2arctan(h2f)\mathrm{FOV}=2 \arctan \left(\frac{h}{2 f}\right)

  • h: 传感器高度
  • f: 焦距,传感器与透镜的距离

通常以 35mm (36 x 24mm) 格式胶片为基准,通过定义焦距的方式来定义 FOV

  • 17mm 焦距对应 104° 广角
  • 50mm 是 “标准” 镜头,视角为 47°
  • 200mm 是远摄镜头,焦距 12°

同样大小的传感器,焦距越大,视场越窄
同样焦距,传感器越大,视场越宽
同样视场,焦距和传感器等比

传感器(Sensor)和胶片(Film)不一定一样

  • 平时两者等价
  • 在渲染器里面,Sensor 收集 irradiance,Film 决定存成什么样的格式

# Exposure 曝光

Exposure

  • H = T x E
  • Exposure = time x irradiance

Exposure time (T)

  • 由快门控制

Irradiance (E)

  • 照射到传感器单位面积上的光功率
  • 由镜头光圈和焦距控制

Aperture size 光圈大小

  • 通过打开 / 关闭光圈来改变光圈值(如果相机有光圈控制功能)
  • 仿生学设计,模拟瞳孔
  • F-Number (F-Stop) 光圈值 用分数表示,其中 F 为分子,光圈值本身为分母。

Shutter speed 快门速度

  • 改变传感器像素积分光的持续时间
  • 越快,开放时间越短,相对越少光

ISO gain 感光度

  • 后期处理
  • 改变传感器值和数字图像值之间的放大倍数(模拟和 / 或数字)
  • 硬件上 调节传感器灵敏度 或者 软件上 调整数字信号
  • 曝光的第三个变量
  • 胶片:用细腻度换取颗粒感
  • 数字时代:以灵敏度换取噪音
    • 在模数转换之前对信号进行乘法运算
    • 线性效应(ISO 200 所需的进光量是 ISO 100 的一半)
  • 光子数量少会有噪声

img

F-Number (F-Stop) 曝光等级 - 光圈大小

  • 数字越小,光圈越大
  • 记为 FN 或 F/N,N 为 F-Number 值
  • 非正式理解:圆形孔径的倒数

Side Effect of Shutter Speed 快门速度过慢

  • 动态模糊:握手、主体移动
  • 快门时间加倍,运动模糊效果也会加倍。
  • 动态模糊并非总是坏事。提示:考虑使用抗锯齿功能

卷帘快门:照片的不同部分在不同时间拍摄

  • 物理快门并非瞬间打开,而是以某种方式 “缓慢 “打开的
  • 会导致高速运动的物体的成像与预想不一致

进光量 ~ F-Stop^2 / Shutter Speed

大光圈会有浅景深的效果,快门时间会导致运动模糊等效果,需要权衡

# Fast and Slow Photography 快速与慢速摄影

High-Speed Photography 每秒极高帧率

  • 快门时间受限,
  • Normal exposure = (extremely fast shutter speed) x (large aperture and/or high ISO)

Long-Exposure Photography 延时摄影

  • 快门时间很长
  • 光圈变小

# Thin Lens Approximation 薄透镜近似

实际镜头设计非常复杂

  • 目前的相机都用透镜组来控制成像
  • 真实的透镜并不那么理想:无法将光线聚于一点 Aberrations
    • 真正的平凸透镜(球面形状)。透镜不会将光线会聚到任何地方的一点。

理想超薄透镜 – 焦点

  • 理想的透镜可将光聚于一点 – 焦点
  • 所有进入透镜的平行光线都会通过其焦点
  • 所有通过焦点的光线,经过透镜后都将平行
  • 焦距可以任意改变(焦距组)

通过透镜组之间的相对位置变化来模拟焦距的改变

高斯成像公式
img

通过这个薄透镜近似可以解释很多问题,例如:解释 Defocus Blur 虚化的原因

# Defocus Blur 散焦模糊

弥散圆(CoC)大小
img

各种距离固定情况下,CoC 与光圈大小成正比

F-Number (F-Stop) 光圈值(又称 F 值)的正式定义:镜头的光圈值定义为焦距除以光圈直径。

常用镜头的光圈值:1.4、2、2.8、4.0、5.6、8、11、16、22、32

光圈值为 2 有时会写成 f/2,这反映了绝对孔径直径 (A) 可以通过焦距 (f) 除以相对孔径 (N) 来计算。

C=Azszizi=fNzsziziC=A \frac{\left|z_{s}-z_{i}\right|}{z_{i}}=\frac{f}{N} \frac{\left|z_{s}-z_{i}\right|}{z_{i}}

更清楚 -> N 要大 -> 光圈要小

# Ray Tracing Ideal Thin Lenses 光线追踪理想薄透镜

(一种可能的)设置

  • 选择传感器尺寸、镜头焦距和光圈尺寸
  • 选择感兴趣的主题深度 zoz_o \kern 0.1pt
  • 利用薄透镜方程计算传感器 ziz_i \kern 0.1pt 的对应深度

渲染

  • x' 透镜中心
  • 对于传感器上的每个像素 x’(实际上是胶片)
  • 在透镜平面上随机抽取点 x''
  • 穿过透镜的光线会击中 x''',因为 x''' 是焦点,考虑虚光线。使用高斯成像公式。
  • 估算光线 x'' -> x''' 上的辐射亮度

img

# Depth of Field 景深

一次成像内,模糊的范围会因光圈大小而变化,而在焦平面肯定不会模糊。

将弥散圆设定为图像平面上允许的最大模糊区域,该区域在最终观看条件下仍能保持清晰。

场景中的深度范围,其中主体对应的 CoC 被认为足够小。当 CoC 小到一定程度,认为是清晰的。
zoz_o 附近的一段距离内都可以看作清晰(CoC 小到一定程度),关键是这段距离有多长。-> 景深

光圈越小,景深范围越大
焦距越大,景深范围越小

img

# Light Field / Lumigraph 光场

两个词指同一东西,属于历史遗留问题,是由两个组几乎同时发现的同样东西

全光函数(Adelson & Bergen):我们所能看到的一切事物的集合

  • 灰度快照:P(θ,ϕ)\boldsymbol{P}(\theta, \phi) \kern 0.1pt 表示光强度
    • 从单一视角来看
    • 同一时刻
    • 在可见光谱波长范围内取平均值 -> 没有具体的颜色
  • 颜色快照:P(θ,ϕ,λ)\boldsymbol{P}(\theta, \phi, \lambda) \kern 0.1pt 表示光强度
    • 从单一视角来看
    • 同一时刻
    • 作为波长的函数。彩色
  • 电影:P(θ,ϕ,λ,t)\boldsymbol{P}(\theta, \phi, \lambda, t) \kern 0.1pt
    • 光强度
    • 从单一视角来看
    • 随着时间的推移
    • 作为波长的函数。彩色
  • 全息电影(Holographic movie)或 全视功能(The Plenoptic Function):P(θ,ϕ,λ,t,VX,VY,VZ)\boldsymbol{P}\left(\theta, \phi, \lambda, t, V_X,V_Y,V_Z\right) \kern 0.1pt
    • 光强度
    • 任何位置看都可以
    • 随着时间的推移
    • 作为波长的函数。彩色
    • 能够重建每个时刻、每个位置、每个波长下的所有可能视图。
    • 它包含了所有人见过的每一张照片、每一部电影,以及所有的一切。它完整地捕捉了我们的视觉现实。

要实现这样一个函数,需要空间中任意一点的全方向光线信息

Ray 光线:

  • P(θ,ϕ,VX,VY,VZ)\boldsymbol{P}\left(\theta, \phi, V_X,V_Y,V_Z\right) \kern 0.1pt
  • 5D = 3D position + 2D direction

Ray Reuse

  • 4D = 2D direction + 2D position(表面为二维)
  • 非散射介质

要记录一个物体向四周展示的样子,只需要记录包围盒上表面各个点往各个方向发射的光线的信息:立方体的表面包含了由于其内部物体而产生的所有辐射信息 -> 光场

光场记录的方式(四维)

  • 2D position + 2D direction
  • 2D position + 2D position:用两个面上两个点来定义光线的方向 -> 2 plane parameterization (u,v) -> (s,t)
  • 固定 (u,v), 所有的 (s,t) 组成一张 image,显示从 (u,v) 点看到的外部世界的样子。
    • 斯坦福相机阵列
  • 固定 (s,t), 所有的 (u,v) 组成一张 image,显示同一个点上从不同方向看过去的样子
    • 积分成像 (苍蝇的眼睛 Lenslets)
    • 从同一个点,将不同方向打过来的光线经过折射记录在不同的位置上
    • 利用微透镜进行空间复用光场捕获:在空间分辨率和角分辨率之间设定固定的权衡。
    • 将单单记录 Irradiance 变成了不同方向的 Radiance

# Light Field Camera 光场相机

Lytro:由 Ren Ng 教授(加州大学伯克利分校)创立

  • 微透镜设计
  • 最重要的功能
    • 计算重聚焦
    • 在拍摄照片后虚拟地改变焦距和光圈大小等
  • 现在每个像素(辐照度)都存储为一个像素块(辐射度)
    • 恢复:一个简单的例子 —— 始终选择每个方块底部的像素
      然后是中间的和顶部的
      本质上就是 “移动摄像机”
  • 计算 / 数字重新聚焦
    • 思路相同:通过视觉改变焦距,相应地选择重新聚焦的光线方向
  • 光场包含一切

缺点

  • 空间分辨率不足(空间信息和方向信息均使用同一胶片)
  • 高成本(微透镜的复杂设计)
  • 计算机图形学讲究权衡取舍。调节更灵活 <-> 分辨率更高

# Lecture20 Color and Perception 颜色与感知

# Physical Basis of Color

光 = 不同波长的电磁辐射(可见光光谱范围内 400~700nm)。不同波长的光具有不同的折射率
Spectrum 光谱:不同波长(频率)的光对应的类型
Spectral Power Distribution (SPD) 谱功率密度:描述一束光在所有波长的分布。线性:可叠加
Color 颜色:是人的一种感知,不是光线的一种根本属性。不同波长的光并不是 “颜色”
人眼的简单介绍:瞳孔 = 光圈,晶状体 = 透镜,视网膜 = 感光元件

视网膜上的感光细胞 Retinal Photoreceptor Cells

  • Rods:视杆细胞,棒状,很多,感知光的强度(而非波长)
  • Cones:视锥细胞,锥形,较少,产生 “颜色” 的感觉
    • 三种视锥细胞类型分别为 S, M, L (分别对应于短波长、中波长和长波长的峰值响应),每种类型具有不同的光谱灵敏度。
    • 不同的人的视锥细胞分布大不一样,三种视锥细胞类型的比例差异很大

# Tristimulus Theory of Color 三刺激值色彩理论

不同视锥细胞的信号强度 = 其对所有波长的光的响应的积分
img

S=rS(λ)s(λ)dλM=rM(λ)s(λ)dλL=rL(λ)s(λ)dλ\begin{aligned} S &=\int r_{S}(\lambda) s(\lambda) d \lambda \\ M &=\int r_{M}(\lambda) s(\lambda) d \lambda \\ L &=\int r_{L}(\lambda) s(\lambda) d \lambda \end{aligned}

任何一束光 -> (S,M,L) -> Color 的对应,人眼只知道 (S,M,L),不知道原来的光线分布 (SPD)

# Metamerism 同色异谱

同色异谱:不同的 SPD -> 同样的 (S,M,L) = 同样的 Color
img

同色异谱是指投射到相同(S、M、L)(3 维)响应的两个不同的光谱(∞维)

  • 对人类而言,这些颜色看起来是一样的。同色异谱现象的存在对于颜色再现 / 匹配至关重要。
  • 不必完全重现真实场景的全部内容
  • 例如:同色异谱仪可以在仅由三种颜色像素组成的显示器上再现真实世界场景的感知颜色(虽然背后的光谱一般完全不一样)

# Color Reproduction / Matching 色彩还原 / 匹配

通过混合的方式

计算机的成像系统是加色系统

  • 给定一组主色(例如 RGB)的光谱分布(S,M,L?)sR(λ),sG(λ),sB(λ)s_{R}(\lambda), s_{G}(\lambda), s_{B}(\lambda) \kern 0.1pt
  • 调整三种主色的强度并相加,得到一种颜色 RsR(λ)+GsG(λ)+BsB(λ)R s_{R}(\lambda)+G s_{G}(\lambda)+B s_{B}(\lambda) \kern 0.1pt
  • 于是这种颜色就可以用 (R,G,B) 这三个标量表示。
  • 于是也可以通过实验确定不同颜色的 (R,G,B) 表示 -> Additive Color Matching Experiment 加色匹配实验
    img

有些颜色怎么混合也混不出来,但是通过给原色加色,就可以混合出来,那么将最后混合的颜色中减去加上的颜色,就是对这种颜色的表示 -> 系数会有负数
img

# CIE RGB Color Matching Experiment 颜色匹配实验

CIE:一个组织
主光 RGB 都是单一波长的光
img
做测试,测量多少强度的三种主光加起来会获得和测试光一样的颜色

颜色匹配函数 color matching functions 描述了三种主光各自多少强度加起来会获得和测试光一样的颜色。
该图绘制了需要将多少 CIE RGB 三原色光混合才能匹配 x 轴上所示波长的单色光。
注意:这些不是响应曲线或光谱
img

现实的光线 = 许多不同强度单一波长光的积分
现实的光线表示的颜色 = 许多不同强度单一波长光的 Color Matching 值的积分 -> (R,G,B)
对于任何光谱,感知到的颜色可以通过以下公式进行匹配:CIE RGB 原色缩放公式
img

# Color Spaces 颜色空间

  • Standard Color Spaces
  • A Universal Color Space: CIE XYZ
  • Perceptually Organized Color Spaces
    • HSV Color Space (Hue-Saturation-Value)
    • CIELAB Space (AKA L * a * b *)

# Standard Color Spaces

Standardized RGB (sRGB)

  • 使特定显示器符合 RGB 标准
  • 其他颜色设备模拟该显示器
  • 如今被广泛采用
  • 色域有限
  • 基于物理的渲染 中有更多介绍

# A Universal Color Space: CIE XYZ

同样定义了 CIE XYZ color matching functions,但是并非实验测得,而是人造的,虚拟的
img
假想的标准原色集 X、Y、Z

  • 具有这些匹配函数的原色不存在
  • Y 代表亮度(与颜色无关的亮度)
  • 匹配函数均为严格正函数
  • 涵盖所有可观察的颜色

将 (X,Y,Z) 归一化获得 (x,y,z)(x + y + z = 1), 然后对 (x,y) 做枚举,获得一张二维图像,表示在 Y(亮度)固定的情况下,不同 X, Z 对应的颜色。
img

  • 由于 x + y + z = 1,我们只需要记录这三个值中的两个
  • 通常选择 x 和 y,得到特定亮度 Y 处的 (x, y) 坐标
  • 弯曲边界:光谱轨迹
    • 对应于单色光(每个点代表单一波长的纯色)
  • 里面的任何颜色纯度都较低,是混合色
  • 白色位于图的中心点 (1/3, 1/3)

色域:由一组原色产生的色度集合
img

  • 不同的色彩空间代表不同的颜色范围
  • 所以色域不同,也就是在说,它们在色度图上覆盖的区域不同

# Perceptually Organized Color Spaces

# HSV Color Space (Hue-Saturation-Value)

轴线对应于色彩的艺术特征,广泛应用于拾色器

Hue (色相)

  • “是什么颜色”
  • 比色关联:主波长 / 色品角
  • 艺术家相关术语:颜色家族或颜料名称,比如红、黄、蓝、绿
  • 色相是未混合过的色彩

Tone (色调)

  • “整体偏什么感觉”
  • 比色关联:明度 / 亮度,也可能包含冷暖倾向
  • 艺术家相关术语:颜色中加入白、黑或灰后形成的调子;也指画面整体调性,比如冷色调、暖色调、灰色调
  • 色调是混合后的色彩

Saturation (饱和度)

  • “色彩缤纷”
  • 比色关联:纯度
  • 艺术家相关术语:彩色颜料管中的颜料比例

Lightness (or value) (亮度)

  • 光照总量
  • 比色相关性:亮度
  • 艺术家的对应关系:色调较浅,阴影较深

# CIELAB Space (AKA Lab*)

一种常用的色彩空间,力求实现感知上的均匀性

  • L* is lightness (brightness)
  • a* and b* are color-opponent pairs
  • a* is red-green 正方向:红色,负方向:绿色
  • b* is blue-yellow

CIELAB 色彩空间维度有良好的神经学基础。
基于互补色理论(Opponent Color Theory):大脑似乎很早就开始使用三个轴来编码颜色:白色 — 黑色,红色 — 绿色,黄色 — 蓝色。黑白轴代表明度;其他轴决定色调和饱和度。

一个例子:你可以有浅绿色、深绿色、黄绿色或蓝绿色,但你不可能有红绿色(这根本说不通)。因此,红色是绿色的对立面。另一项证据:残像

人眼是奇怪的

  • 视觉暂留
  • 视错觉
  • 颜色的相对性

# HDR

这部分课上没讲

HDR 是 High Dynamic Range,高动态范围。图像或渲染系统能表示更宽的亮度范围,从很暗的阴影到非常亮的高光都能保留下来

普通 LDR/SDR 图像通常把颜色限制在 [0, 1] 或 8-bit 的 0~255 里,超过范围的亮部会被直接截断,比如太阳、火焰、灯光高光会变成一片死白
HDR 在图形学里通常允许颜色值 大于 1,例如灯光高光可以是 3.0、10.0,甚至更高,这样后处理时还能知道 “这里真的很亮”

在游戏渲染管线里,HDR 常见流程是:先把场景渲染到 HDR Render Texture,然后做 Bloom、曝光、色调映射、调色等后处理,最后输出到 SDR 或 HDR 显示器

场景渲染
HDR 颜色缓冲区,例如 FP16
Bloom / Exposure / Color Grading
Tone Mapping
显示到屏幕

Tone Mapping,色调映射。它很重要,因为屏幕能显示的亮度范围有限,所以需要把 HDR 的大范围亮度压缩到屏幕能显示的范围内
比如一个像素原本亮度是 8.0,不能直接显示到普通屏幕上,所以 Tone Mapping 会把它压缩到接近白色但仍保留层次的结果
常见的 Tone Mapping 算法有 Reinhard、Filmic、ACES,其中 ACES 在游戏和影视风格渲染里很常见

HDR 的核心是 保留亮度信息,让高光、Bloom、曝光变化、真实光照更自然。例如没有 HDR 时,亮度 1.5、5.0、20.0 都可能被夹到 1.0,Bloom 就分不清哪个地方更亮

# 减色系统

典型:CMYK: A Subtractive Color Space

墨水越混越黑

  • Cyan, Magenta, Yellow, and Key
  • 靛蓝、品红、黄色、黑色

# Lecture21 Animation 动画

  • 动画是一种信息传递的工具,美学经常比技术重要
  • 动画是模型的延伸(连续性),将场景模型表示为时间的函数
  • 输出:按顺序观看时,一系列图像会产生运动感
    • 电影:24FPS
    • 视频:30FPS、29.994FPS
    • VR:90FPS (不晕的基础要求)

# History

最早:狩猎鹿的动画 (Shahr-e Sukhteh, Iran 3200 BCE)
圆盘旋转:(Phenakistoscope, 1831)
第一部 Film:Edward Muybridge, “Sallie Gardner” (1878)
First Hand-Drawn Feature-Length (>40 mins) Animation:Disney, “Snow White and the Seven Dwarfs” (1937)
First Digital-Computer-Generated Animation:Ivan Sutherland, “Sketchpad” (1963) – Light pen, vector display
Early Computer Animation:Ed Catmull & Frederick Parke, “Computer Animated Faces” (1972)
Digital Dinosaurs!:Jurassic Park (1993)
First CG Feature-Length Film:Pixar, “Toy Story” (1995) (光栅化)
Computer Animation - 10 years ago:Sony Pictures Animation, “Cloudy With a Chance of Meatballs” (2009)
Computer Animation - last year:Walt Disney Animation Studios, “Frozen 2” (2019)

# Keyframe animation 关键帧动画

  • 动画师(例如首席动画师)创建关键帧
  • 辅助工具(人或计算机)创建中间帧(“补间动画”),渐变帧

关键的技术难点 - Interpolation 插值

  • 线性插值通常不够好
  • 回溯样条曲线以实现平滑 / 可控插值

B 样条……

# Physical Simulation 物理模拟

模拟、仿真:推导、实现公式,模拟出物体应该怎么变化

例子:布料模拟、流体模拟

# 质点弹簧系统 Mass Spring System: Example of Modeling a Dynamic System

例如:质点弹簧绳、头发、质点弹簧网

  • 简单的理想化弹簧
    • 没有初始长度
    • 随着拉力线性增长 / 缩短,线性系数是 弹簧系数:刚度
    • 力将点拉向一起
    • 强度与位移成正比(胡克定律)
    • 问题:长度会倾向于 0
  • 非零长度弹簧

    fab=ksbaba(bal)\boldsymbol{f}_{a \rightarrow b}=k_{s} \frac{\boldsymbol{b}-\boldsymbol{a}}{\|\boldsymbol{b}-\boldsymbol{a}\|}(\|\boldsymbol{b}-\boldsymbol{a}\|-l)

    • 初始长度(Rest length)不为零
    • 问题:持续振荡

导数的点表示法:

xx˙=vx¨=a\begin{aligned} &\boldsymbol{x} \\ &\dot{\boldsymbol{x}}=\boldsymbol{v} \\ &\ddot{\boldsymbol{x}}=\boldsymbol{a} \end{aligned}

能量损失简介

  • 简单运动阻尼

    f=kdb˙\boldsymbol{f}=-k_{d} \dot{\boldsymbol{b}}

  • kdk_d \kern 0.1pt 是阻尼系数
  • 表现得像粘性阻力
  • 减缓速度方向上的运动
  • 问题:减缓所有运动
    • 想要让生锈的弹簧的振动速度减慢,但同时也希望它能更慢地落到地面:跟全局速度挂钩
    • 无法表示弹簧内部的损耗

弹簧内部阻尼
img

  • 粘性阻力仅由弹簧长度的变化引起
    • 通过点乘将相对速度分解到 ab 方向上,乘以系数后再乘到 ab 方向上
    • 不会减慢弹簧系统的群体运动(例如,群体的全局平移或旋转)
  • 注:这只是阻尼的一种特定类型。只是一种阻尼的近似

# Structures from Springs

  • 床单
  • 积木
  • 其他
    • 比如说,一块布的进化

Step 1: 床单

  • 这种结构无法抵抗剪切力。切变会露馅
  • 这种结构无法抵抗面外弯曲……

img

Step 2: 加强筋

  • 这种结构能够抵抗剪切,但具有各向异性倾向
  • 这种结构也无法抵抗面外弯曲……

img

Step 3: 加强筋 plus

  • 该结构将抵抗剪切。方向性偏差较小。
  • 这种结构也无法抵抗面外弯曲……

img

Step 4: 加强筋 max (skip connection)

  • 该结构将抵抗剪切。方向性偏差较小。
  • 这种结构能够抵抗面外弯曲(红色弹簧的强度应该要弱得多)

img

# FEM (Finite Element Method) Instead of Springs

有限元法(FEM)代替弹簧

有限元方法

  • 车辆碰撞

力传导扩散适合用有限元方法建模做

# 动画系统之 Particle Systems 粒子系统

粒子系统

  • 将动力系统建模为大量粒子的集合
  • 每个粒子的运动都由一组物理力(或非物理力)决定
  • 每个粒子有自己的属性

图形和游戏中的常用技术

  • 易于理解和实施
  • 可扩展性:粒子数量越少速度越快,粒子数量越多复杂度越高。

挑战

  • 可能需要许多粒子(例如液体)
  • 可能需要加速结构(例如,用于寻找相互作用的最近粒子)

动画中的每一帧

  • (如有必要)清除无效粒子
  • 计算每个粒子所受的力
  • 更新每个粒子的位置和速度
  • (如果需要)创建新粒子
  • 渲染粒子

定义个体和群体之间的关系

# Particle System Forces 粒子系统力

吸引力和排斥力

  • 引力、电磁力……
  • 弹簧、推进系统……

阻尼力

  • 摩擦力
  • 空气阻力
  • 粘度
  • ……

碰撞

  • 墙壁、容器、固定物体……
  • 动态对象、角色身体部位……

星系模拟、Particle-Based Fluids

示例:模拟集群行为的常微分方程

  • 定义鸟儿之间交互的规则:个体对群体的观察
  • 将每只鸟视为质点,并使其受到非常简单的力作用
  • 邻里中心的吸引力
  • 来自邻居的排斥
  • 与邻居的平均轨迹对齐 以数字方式模拟大粒子系统的演化 涌现的复杂行为(也见于鱼、蜜蜂等)

例如:分子动力学

# Kinematics 运动学

运动学:正向和反向

# Forward Kinematics 正向运动学

明确骨骼之间的运动关系 -> 计算出各个部位的位置

关节骨骼

  • 拓扑结构(哪些部分与哪些部分相连)
  • 关节的几何关系
  • 树状结构(无环)

关节类型

  • 销钉(1D 旋转)
  • 球(二维旋转)
  • 移动关节(变换)

img

优点

  • 直接控制很方便
  • 实施起来很简单

缺点

  • 动画可能与物理定律不符。
  • 对艺术家来说很耗时

# Inverse Kinematics 逆运动学

限制各个部位(通常只有终端)的位置、限制骨骼的运动方式 -> 计算骨骼的运动
方便控制形体整体形状
解特别复杂,并且解可能不唯一,也可能无解

img

解法:随机化算法(优化方法,梯度下降)
一般 N 连杆逆运动学问题的数值解

  • 选择初始配置
  • 定义误差指标(例如,目标位置与当前位置之间距离的平方)
  • 计算误差梯度作为配置的函数
  • 应用梯度下降法(或牛顿法,或其他优化程序)

例子:Style-Based IK

# Rigging 骨骼绑定

骨骼绑定是一套对角色进行更高级别控制的技术,可以更快速、更直观地修改姿势、变形、表情等

重要提示

  • 如同操控木偶的线
  • 捕捉所有重要的角色变化
  • 因角色而异

制造成本高昂

  • 人工操作 定控制点,拉控制点(应该怎么定、应该怎么拉 -> 动画师)
  • 需要艺术和技术方面的培训

# Blend Shapes 控制点间的位置插值计算

不使用骨架,而是直接在曲面之间进行插值
例如,对一系列面部表情进行建模:最简单的方案:取顶点位置的线性组合,使用样条曲线来控制权重随时间的变化

# Motion Capture 动作捕捉

真人控制点反映到虚拟角色中去,需要建立真实和虚拟的联系

采用数据驱动方法创建动画序列

  • 记录真实世界的表现(例如,某人执行某项活动)
  • 从收集的数据中提取姿态随时间变化的函数

优势

  • 能够快速捕获大量真实数据
  • 现实主义可以很高

弱点

  • 复杂且昂贵
  • 拍摄的动画可能无法满足艺术需求,需要进行修改。例如某些不可能实现的动作

捕捉条件限制

不同的捕捉方法:

  • 光学定位(更多内容请参见后续幻灯片)
    • 在被测物体上标记位置
    • 通过多摄像头三角测量定位
    • 8 个以上摄像头,240 Hz 刷新率,遮挡问题较为棘手
  • 磁力定位:通过感知磁场推断位置 / 方向。需连接线缆。
  • 机械定位:直接测量关节角度。限制运动。

面部动画的挑战

  • 恐怖谷
    • 在机器人学和图形学领域
    • 当人工智能角色的外观接近人类的真实程度时,我们的情绪反应会逐渐变得负面,直到其表情达到足够令人信服的真实水平

面部动作捕捉

举例:阿凡达

# 动画的制作流程 The Production Pipeline

img

# Lecture22 Animation Cont 动画

# Single Particle Simulation

已有变量:每个粒子的 v (t0) 和 x (t0)
目标是 x (t1),之后将其推广到大量粒子。

首先,假设粒子的运动由速度矢量场决定,该速度矢量场是位置和时间的函数
速度场:v (x,t)
img

Ordinary Differential Equation (ODE) 常微分方程
计算速度场内粒子的位置需要计算一阶常微分方程:

dxdt=x˙=v(x,t)\frac{d x}{d t}=\dot{x}=v(x, t)

解一阶常微分方程:
连续:积分
离散:Euler’s Method 欧拉方法(显式欧拉法,前向、显式)

  • 始终用前一帧的状态来更新后一帧

    xt+Δt=xt+Δtx˙tx˙t+Δt=x˙t+Δtx¨t\begin{array}{l} \boldsymbol{x}^{t+\Delta t}=\boldsymbol{x}^{t}+\Delta t \dot{\boldsymbol{x}}^{t} \\ \dot{\boldsymbol{x}}^{t+\Delta t}=\dot{\boldsymbol{x}}^{t}+\Delta t \ddot{\boldsymbol{x}}^{t} \end{array}

  • 简单迭代法
  • 常用
  • 非常不准确
    • 数值积分过程中误差会累积
    • 欧拉积分法尤其糟糕
  • 不稳定
    • 离正确结果越来越远

# Instability and improvements 不稳定与改进

采用有限差分数值积分法求解会遇到两个问题

Errors 误差 不是特别大的问题

  • 每个时间步的误差都会累积。随着模拟的进行,精度会降低。
  • 在图形应用程序中,准确性可能并非至关重要

Instability 不稳定性 很要命

  • 误差会不断累积,即使底层系统本身没有问题,也会导致模拟结果出现偏差。收敛很重要
  • 稳定性不足是仿真中的一个根本性问题,不容忽视

# 如何确定 / 量化稳定性

  • 使用局部截断误差(每一步)/ 总累积误差(总体)
  • 绝对值并不重要,但相对于步长的顺序很重要。研究误差和步长的关系(几次方?)

一些对抗不稳定性的方法

  • Midpoint method / Modified Euler
  • Adaptive step size
  • Implicit methods (backward 隐式、后向)
  • Runge-Kutta Families
  • Position-based / Verlet integration

# Midpoint method / Modified Euler 中点法 / 修正欧拉法

起点和终点的平均速度
img

xt+Δt=xt+Δt2(x˙t+x˙t+Δt)x˙t+Δt=x˙t+Δtx¨txt+Δt=xt+Δtx˙t+(Δt)22x¨t\begin{aligned} &\boldsymbol{x}^{t+\Delta t}=\boldsymbol{x}^{t}+\frac{\Delta t}{2}\left(\dot{\boldsymbol{x}}^{t}+\dot{\boldsymbol{x}}^{t+\Delta t}\right) \\ &\dot{\boldsymbol{x}}^{t+\Delta t}=\dot{\boldsymbol{x}}^{t}+\Delta t \ddot{\boldsymbol{x}}^{t} \\ &\boldsymbol{x}^{t+\Delta t}=\boldsymbol{x}^{t}+\Delta t \dot{\boldsymbol{x}}^{t}+\frac{(\Delta t)^{2}}{2} \ddot{\boldsymbol{x}}^{t} \end{aligned}

多了一个二次项

# Adaptive step size

  • 递归地比较一步和两个半步,直到误差在可接受范围内
  • 重复此过程直至误差低于阈值
    • 计算欧拉步长为 T 的 x_T
    • 计算 x_T/2,两个欧拉步,步长 T/2
    • 计算误差 || x T – x T/2 ||
    • 如果误差大于阈值,则减小步长并重试
  • 基于误差估计选择步长的方法
  • 非常实用的技术
  • 但可能需要采取非常小的步长

img

# Implicit methods (backward 隐式、后向)

使用下一个时间步的速度(困难)

xt+Δt=xt+Δtx˙t+Δtx˙t+Δt=x˙t+Δtx¨t+Δt\begin{array}{l} \boldsymbol{x}^{t+\Delta t}=\boldsymbol{x}^{t}+\Delta t \dot{\boldsymbol{x}}^{t+\Delta t} \\ \dot{\boldsymbol{x}}^{t+\Delta t}=\dot{\boldsymbol{x}}^{t}+\Delta t \ddot{\boldsymbol{x}}^{t+\Delta t} \end{array}

  • 是一个方程组,有三个未知数,只能假设一个已知(猜)
  • 使用求根算法,例如牛顿法
  • 稳定性更好
  • 隐式欧拉法的阶数为 1
    • 局部截断误差:O (h^2)
    • 全局截断误差:O (h)(h 为步长,即 ∆t)
  • O (h) 的理解
    • 如果我们将 h 减半,我们预期误差也会减半
    • 阶数越高越好,减小步长的情况下降低更快

# Runge-Kutta Families

一系列求解常微分方程的高级方法,尤其擅长处理非线性问题

它的四阶版本应用最为广泛,又称 RK4
img

更多:Numerical Analysis 对图形学有用(其他的:信号处理)

# Position-based / Verlet integration 基于位置 / Verlet 集成

约束时间步后粒子的位置和速度
假设弹簧无限大

思想

  • 经过改进的欧拉前向步法后,约束粒子位置以防止发散、不稳定的行为
  • 利用约束位置计算速度
  • 这两种方法都会耗散能量,使之稳定

优点 / 缺点

  • 快速并且简单
  • 并非基于物理原理,而是耗散能量(错误)

# Rigid body simulation

不会形变

简单情况

  • 类似于模拟粒子
  • 再考虑一下其他属性。拓展

img

# Fluid simulation

# A Simple Position-Based Method 基于位置的方法

模拟只需要输出物体的位置,其他的就是渲染的问题了

核心思想

  • 假设水是由微小的刚体球体组成
  • 假设水不可压缩(即密度恒定)
  • 因此,只要密度在某个地方发生变化,就应该通过改变粒子的位置来校正它
  • 需要知道密度相对于每个粒子位置的梯度
  • 梯度下降法更新

这是非物理方法

# 流体模拟中两种不同的思路:Eulerian vs. Lagrangian

Lagrangian:质点法,以每个元素为单位模拟
Eulerian:网格法,以空间为单位分割模拟

# Material Point Method (MPM)

混合式,结合了欧拉和拉格朗日观点

  • 拉格朗日:考虑携带材料属性的粒子
  • 欧拉方法:使用网格进行数值积分
  • 交互:粒子将属性传递给网格,网格进行更新,然后插值回粒子