games101 – 4 – Ray Tracing
- 2022 年 1 月 7 日
- 筆記
- programming-and-computer-graphics, 计算机图形学 - 渲染
games101 – 4 – Ray Tracing
- games101 – 4 – Ray Tracing
- 为什么需要Ray Tracing
- Recursive (Whitted-Style) Ray Tracing
- Ray-Surface Intersection
- Bounding Volumes
- Spatial Partitions
- Bounding Volume Hierarchy (BVH)
- Radiometry
- Bidirectional Reflectance Distribution Function (BRDF)
- 反射方程
- 渲染方程
- Understanding the rendering equation
- Probability Review
- Monte Carlo Integration
- Path Tracing
- Materials and Appearances
- 没有覆盖到的内容
对应的Lecture 13 ~ 17
为什么需要Ray Tracing
光栅化无法处理全局效果
- 软阴影;
- 光反弹次数超过一次的情况,如glossy reflection,indirection illumination;
- 光栅化的很快,但是质量比较低;
- raytracing,很准确,但是很慢;
Recursive (Whitted-Style) Ray Tracing
An improved Illumination model for shaded display” T. Whitted, CACM 1980
Ray-Surface Intersection
射线的定义:\(r(t) = o + td, 0 \le t \lt \infty\),一个起始点,和方向构成了一个射线。
对于射线和方程隐式表示的表面,可以通过求解方程式得到交点。更常见的场景是射线和三角网格模型进行求交计算。对于射线和三角形求交计算,可以先和平面进行求交,然后再判断交点是不是位于三角形内部。
(23条消息) Möller-Trumbore算法-射线三角形相交算法_zhanxi1992的专栏-CSDN博客
O – P_0 = (P_1 – P_0)b_1 + (P_2 – P_0)b_2 – tD \\
S = E_1b_1 + E_2b_2 -tD
\]
矩阵的形式表示如下:
-D & E_1 & E_2
\end{bmatrix}
\begin{bmatrix}
t \\
b_1 \\
b_2
\end{bmatrix} = S
\]
然后利用克莱姆法则(\(Ax = c=>x_i = detA_i/detA\))求解,
如果遍历三角网格中的所有三角形,对每个三角形进行相交计算,并找到最近的交点,整个过程是非常耗时的。需要的开销为#pixels x #triangles (x #bounces)
.
Bounding Volumes
可以利用包围盒,进行加速。针对复杂物体,构建出包围盒,然后如果射线不和包围盒相交,那么射线就不和包围盒内部的物体相交,如果相交,然后再进行内部物体的相交测试,而包围盒相交监测速度非常快。常见的包围盒有:包围球,轴对⻬包围盒,非轴对齐包围盒。更常用的是使用轴对齐包围盒,因为针对它的相交计算很简单。
在计算直线和Axis-Aligned Box相交的时候(此处允许t<0),分别针对每个维度,计算出\(t_{min}\)和\(t_{max}\),那么\(t_{enter}\)等于各个维度\(t_{min}\)的最大值,\(t_{exit}\)等于各个维度\(t_{max}\)的最小值。如果\(t_{enter} < t_{exit}\),那么相交。
但是ray并不是一条直线需要对负值的情况进行额外判断:
- 如果\(t_{exit} < 0\),那么不相交;
- 如果\(t_{exit} \ge 0\)并且\(t_{enter} < 0\),那么射线的原点位于box内部,相交;
- 那么ray和AABB相交,当且仅当\(t_{enter} < t_{exit}\ \&\& \ t_{exit} \ge 0\)
Spatial Partitions
- Uniform Spatial Partitions (Grids) 适用于很多对象均匀的分布在空间中的场景。
更常用的是不均匀空间划分。
常见的分法如下:
K-D Tree – OI Wiki (oi-wiki.org)
Bounding Volume Hierarchy (BVH)
构建一个BVHs,需要进行如下操作:
- 找到包围盒;
- 将包围盒中的对象分成两个部分(细分的时候需要选择维度最大的方向进行划分,这里通常选择当前node轴长最大的轴,切分的位置通常位于中间);
- 重新计算子集的包围盒;
- 达到某种条件后中断,通常是node中的对象少于一定数量;
- 将对象存储到各个节点中;
BVH的数据结构主要分为两类:内部节点和叶子节点。内部节点包括:包围盒,子节点;叶子节点包括:包围盒,对象集合;
BVH树的遍历:
Intersect(Ray ray, BVH node) {
if (ray misses node.bbox) return;
if (node is a leaf node)
test intersection with all objects;
return closest intersection;
hit1 = Intersect(ray, node.child1);
hit2 = Intersect(ray, node.child2);
return the closer of hit1, hit2;
}
Radiometry
radiant energy: the energy of electromagnetic radiation. \(Q\ [J=Joule]\); 能量整体
radiant flux: the energy emitted, reflected, transmitted or received, per unit time. \(\Phi = dQ/dt\),单位是[W=Watt],或者是[lm = lumen]。单位时间的能量;
另外几个关键概念,示意图如下:
Radiant intensity: the power per unit solid angle emitted by a point light source. \(I(\omega) = d\Phi/d\omega\),单位是[W/sr],或者是[lm/sr = candela]。单位时间单位立体角的能量;立体角的概念,微分,积分,如下:
Irradiance:the power per (perpendicular projected) unit area incident on a surface point.\(E(x) = d\Phi(x)/dA\)。单位面积单位时间的能量(面积为垂直于光线方向);面积理解的示意图如下:
Radiance: the power emitted, reflected, transmitted or received by a surface, per unit solid angle, per projected unit area. 示意图及公式如下:
irradiance和radiance概念对比,irradiance表示的是单位面积接收到的所有能量,radiance表示,从某一个单位立体角看过去的单位面积上接收的能量。
Bidirectional Reflectance Distribution Function (BRDF)
BRDF: 用来表示从每个方向过来的光线,有多少会贡献到每个outgoing方向。represents how much light is reflected into each outgoing direction \(\omega_r\) from each incoming direction. 对应的公式如下:
上面的公式中为什么需要对Lr做微分,对Ei做微分呢?具体解释可以参见:关于BRDF公式理解的笔记_fatever的博客-CSDN博客,摘录关键内容如下:
反射方程
表示的不同方向的irradiance对出射方向上的贡献的积分。
渲染方程
在反射方程的基础上再加上emission项,得到渲染方程。
Understanding the rendering equation
图中,当一个光源的时候,用间接反射光取代了入射光。
Probability Review
随机变量的概率密度函数:\(P(a\le x\lt b) = \int_a^b p(x) dx\)。p(x)即为概率密度函数。从负无穷到正无穷的图形对应的面积为1。对应的期望为\(E(X) = \int xp(x)dx\).
Monte Carlo Integration
蒙特卡罗方法(Monte Carlo Method)概述——概念、起源、思路、应用、特点、计算程序、计算举例和文献资料(21k) (sohu.com)
如果需要求解定积分,\(\int_a^bf(x) dx\),首先需要知道x的概率分布,那么可以转换成求解积分,\(\int_a^bf(x)/p(x)\cdot p(x) dx\),那么用蒙特卡洛进行期望估计,得到:
Path Tracing
Whitted-Style Ray Tracing的条件是:总是执行镜面反射和折射;碰到漫反射表面停止。这种近似对于一些场景会存在问题:1)对于glossy reflection表面;2)在diffuse材质,不会有反射;
之前给出的rendering equation是正确的,那么如何求解呢?
A Simple Monte Carlo Solution
问题:假设我们需要渲染下面场景中一个点(仅考虑直接光照):
那么可以得到如下的反射方程:
\]
要求解这样的积分,我们利用蒙特卡洛积分,构建“f(x)”,为:\(L_i(p,\omega_i)f_r(p,\omega_i, \omega_o)(n\cdot\omega_i)\),并且先假设\(\omega_i\)的概率密度函数为\(p(\omega_i)=1/(2\pi)\),半球上均匀分布,那么可以得到:
如果在光线追踪的时候,一条光线hit到了物体,而没有hit到light,需要怎么处理呢?那么首先需要计算hit到物体的位置,贡献的光是多少。如下:
shade(p, wo)
Randomly choose N directions wi~pdf
Lo = 0.0
For each wi
Trace a ray r(p, wi)
If ray r hit the light
Lo += (1/N) * L_i * f_r * cosine / pdf(wi)
Else If ray r hit an object at q
Lo += (1/N) * shade(q, -wi) * f_r * cosine / pdf(wi)
Return Lo
这样就ok了么,并不然。上述的处理方式还存在什么问题呢?
问题1:光线次数随着碰撞次数的增多而指数增长
问题1:光线次数随着碰撞次数的增多而指数增长。如下图所示:
为了避免光线数量的暴增。随机只选择一条光线进行处理。如下:
shade(p, wo)
Randomly choose 1 directions wi~pdf
Lo = 0.0
Trace a ray r(p, wi)
If ray r hit the light
Lo += L_i * f_r * cosine / pdf(wi)
Else If ray r hit an object at q
Lo += shade(q, -wi) * f_r * cosine / pdf(wi)
Return Lo
这种方式的话,如果一个像素上只有一条光线穿过,那么得到的结果噪声会很大,因此需要多条射线穿过一个像素位置,然后对结果进行平均。这样针对一个像素位置的伪代码如下:
ray_generation(camPos, pixel)
Uniformly choose N sample positions within the pixel
pixel_radiance = 0
For each sample in the pixel
Shoot a ray r(camPos, cam_to_sample)
If ray hit the screen at p
pixel_radiance += 1 / N * shade(p, sample_to_cam)
Return pixel_radiance
问题2:此时shade函数如何终止
问题2:此时shade函数中还存在一个问题,就是函数进行无限循环。解决方案是提供轮盘赌的方式(Russian Roulette)。假设我们手动设置一个概率值,P,在发射一条光线的时候,给出一个随机值,如果范围在P~1,那么返回:0,否则返回:Lo/P。这样得到的Lo的期望为:E = P * (Lo/P) + (1-P)*0 = Lo。将这部分内容加到shader伪代码中如下:
shade(p, wo)
Manully specify a probability P_RR
Randomly select ksi in a uniform dist. in [0, 1]
If (ksi > P_RR) return 0.0
Randomly choose ONE direction wi-pdf(w)
Trace a ray r(p, wi)
If ray r hit the light
Return L_i * f_r * cosine / pdf(wi) / P_RR
Else If ray r hit an object at q
Return shade(q,-wi) * f_r * cosine / pdf(wi) / P_RR
问题3:如何提高采样效率
上述的实现并不是很高效,如下图所示:
如果光源面积比较大,那么发射较少数量的光线,就可以碰撞到光源,如果光源面积比较小,那么需要发生很多的光线才行。这样如果我们在半球表面进行均匀采样,那么会有大量的光线是wasted的。那么怎么解决呢?
可以将采样分为两部分,1)针对光源进行采样,2)针对非直接光照场景进行采样;
从渲染方程得知,接收到的光照信息,是针对立体角进行积分的,那么怎么转换到,通过光源面积进行积分呢?从立体角的定义得到:
\]
那么渲染方程可以重写为:
此时shade伪代码可以写为:
shade(p, wo)
# Contribute from the light source
Uniformly sample the light at x' (pdf_light = 1/A)
# test blocked
Shoot a ray from p to x'
If the ray is not blocked in the middle
L_dir = L_i * f_r * costheta * costheta' / |x' - p|^2 / pdf_light
# Contribute from other reflectors
L_indir = 0.0
Test Russian Roulette with probability P_RR
Uniformly sample the hemisphere toward Wi (pdf_hemi = 1/2pi)
Trace a ray r(p, wi)
If ray hit a non-emitting object at q
L_indir = shade(q, -wi) * f_r * costheta / pdf_hemi / P_RR
Materials and Appearances
Materials == BRDF。BRDF用来表示从每个方向过来的光线,有多少会贡献到每个outgoing方向。
Snell’s Law
传输方向从i到t,那么如果\(\eta_i/\eta_t > 1\)可能发生完全内反射(即,没有折射的现象)。
Fresnel Reflection
用来解释:视线垂直于表面时,反射较弱,而当视线非垂直表面时,夹角越小,反射越明显,这一种现象。
Fresnel Reflection – 菲涅尔反射 – Tekkaman – 博客园 (cnblogs.com)
准确解和近似解分别如下:
微表面
微表面,针对每一个元素都可以视为mirror。
没有覆盖到的内容
- uniformly sampling the hemisphere; How?
- Monte carlo integration allows arbitrary pdfs. What’s the best choice?
- Do random numbers matter ? Yes! (low discrepancy sequences)
- I can sample the hemisphere and the light. Can I combine them? Yes! (multiple imp. sampling)
- The radiance of a pixel is the average of radiance on all paths passing through it. Why? (pixel reconstruction filter)
- Is the radiance of a pixel the color of a pixel? No. (gamma correction, curves, color space)
- deeper path tracing.