本系列的最后一本,同样会涉及到大量的东西,本博客只记录个人所得。这一章有部分个人理解的东西,如有不正确之处,感谢指正,另外我如果发现了那些地方有错误也会及时修正。
原文地址:https://github.com/RayTracing/raytracing.github.io/
蒙特卡洛方法
蒙特卡洛方法是一种解决问题思路,对同意实验进行大量重复实验,使结果逼近一个值,不过不一定正确,这是一个估计方法。
例如,在正方形中画一个圆,在正方形中找一个点,求这个点在圆中的概率,假设我们做1000次实验,那概率就是
点
在
圆
中
的
概
率
=
点
在
圆
中
的
次
数
/
1000
点在圆中的概率=点在圆中的次数/1000
点在圆中的概率=点在圆中的次数/1000 在点是完全随机的情况下,这个问题可以转化为两者面积之比
p
i
∗
R
2
/
(
2
R
)
2
=
p
i
/
4
pi*R^2/(2R)^2=pi/4
pi∗R2/(2R)2=pi/4
点
在
圆
中
的
概
率
=
点
在
圆
中
的
次
数
/
1000
=
p
i
/
4
点在圆中的概率=点在圆中的次数/1000=pi/4
点在圆中的概率=点在圆中的次数/1000=pi/4用这个方式可以快速逼近pi的值,一开始向pi值逼近的速度很快,但随着实验数量的提升,逼近速度会变慢,这是蒙特卡洛方法存在的问题(Law of Diminishing Returns)
这里提到了,分层解决Law of Diminishing Returns的方法,双循环把整个图形分割,但是这种方法维度越高效果越差。
蒙特卡洛积分
蒙特卡洛积分经常用在不方便求解的积分,例如下图,我们要求出函数f(x)在a点和b点之间的定积分(实际上这个曲线是可以表示的,我们假装它很难求)。我们可以把线段分成无数个小段的Δx然后用累加的方式求出。当Δx->0时
∫
a
b
f
(
x
)
d
x
=
∑
i
=
1
n
f
(
ε
i
)
Δ
x
i
\int_a^bf(x){\rm d}x= \sum_{i=1}^n f(ε_i)Δx_i
∫abf(x)dx=i=1∑nf(εi)Δxi
假设我们可以知道Δx与ab之间x的总长度
x
a
x_a
xa,那Δx占总值的比例为p(x)
p
(
x
)
=
S
Δ
x
S
x
a
p(x)=\frac{S_Δx}{Sx_a}
p(x)=SxaSΔx其中
S
Δ
x
S_Δx
SΔx是离散范围内要求出的x的值,也就是
S
Δ
x
=
f
(
ε
i
)
Δ
x
i
S_Δx= f(ε_i)Δx_i
SΔx=f(εi)Δxi
S
x
a
=
∫
a
b
f
(
x
)
d
x
Sx_a=\int_a^bf(x){\rm d}x
Sxa=∫abf(x)dx 得到
∫
a
b
f
(
x
)
d
x
=
S
Δ
x
p
(
x
)
\int_a^bf(x){\rm d}x=\frac{S_Δx}{p(x)}
∫abf(x)dx=p(x)SΔx 这里的p(x)就是概率密度函数,通常表示为pdf(x)。在实际问题中我们通常要进行多次采样,就像上述的蒙特卡洛的概念一样,多次采样然后求平均,将
S
Δ
x
S_Δx
SΔx表示为
f
(
x
k
)
f(x_k)
f(xk)即得到公式:
F
n
(
x
)
=
1
n
∑
k
=
1
n
f
(
x
k
)
p
d
f
(
x
k
)
F_n(x)= \frac{1}{n}\sum_{k=1}^n \frac{f(x_k)}{pdf(x_k)}
Fn(x)=n1k=1∑npdf(xk)f(xk)
其中F(x)是积分的值,n是样本的数量。
蒙特卡洛积分在球面应用
在球面上采样,将之前随机在圆内的向量单位化就得到了球面上的随机向量,先要将球面上一点相对于整个球面的比例算出来,使用立体角计算,整个球面的立体角为4π,那 p d f ( x ) = 1 4 π pdf(x)=\frac{1}{4π} pdf(x)=4π1,
光线散射
在之前的定义中我们假设光线被散射的概率是A,那被吸收的概率就是1-A,这个A是由定义的材质决定的。但光线进行反射的时候,会有一个方向上的概率分布,将其定义为pdf即为s(direction),那现在每一个点的颜色是由散射概率,散射pdf和着色函数共同决定的
C
o
l
o
r
=
∫
A
∗
s
(
d
i
r
e
c
t
i
o
n
)
∗
c
o
l
o
r
(
d
i
r
e
c
t
i
o
n
)
Color=\int A*s(direction)*color(direction)
Color=∫A∗s(direction)∗color(direction) 运用蒙特卡洛的思想,添加一个随机生成方向的pdf
C
o
l
o
r
=
A
∗
s
(
d
i
r
e
c
t
i
o
n
)
∗
c
o
l
o
r
(
d
i
r
e
c
t
i
o
n
)
/
p
(
d
i
r
e
c
t
i
o
n
)
Color=A*s(direction)*color(direction) /p(direction)
Color=A∗s(direction)∗color(direction)/p(direction)
在Lambertian中其实已经隐式的使用过这个方法了:假设Lambertian表面的s()与p()都是一个余弦函数,θ为法线平面与反射光线的夹角,当cosθ<0的时候,半球的积分为π,由单位角
d
A
=
s
i
n
(
θ
)
d
θ
d
φ
dA=sin(θ)dθdφ
dA=sin(θ)dθdφ得出
半
球
面
积
=
∫
0
2
π
∫
0
π
2
c
o
s
(
θ
)
s
i
n
(
θ
)
d
θ
d
φ
半球面积=\int_0^{2π}\int_0^{\frac{π}{2}}cos(θ)sin(θ)dθdφ
半球面积=∫02π∫02πcos(θ)sin(θ)dθdφ
所以s(diretion)和p(direction)的值都与cos(θ)/π成正比。可以从上面颜色的公式看到两者相除得到一个常数,就简化成了现在Lambertian的公式。
重要性采样
我们所看到的景象都是从相机出发的射线与物体相交构造的,所以想让灯光更集中一点,只能改变灯光的采样,让它散射时更集中一点。假设我们发送的一束朝向光源的光线的pdf为pLight(direction)再一个和s有关的pdf函数,我们叫它为pSurface(direction)。我们可以把两者进行线性组合,得到一个综合的pdf:
p
(
d
i
r
e
c
t
i
o
n
)
=
0.5
∗
p
L
i
g
h
t
(
d
i
r
e
c
t
i
o
n
)
+
0.5
∗
p
S
u
r
f
a
c
e
(
d
i
r
e
c
t
i
o
n
)
p(direction)=0.5*pLight(direction)+0.5*pSurface(direction)
p(direction)=0.5∗pLight(direction)+0.5∗pSurface(direction)
只要pdf的权重是正的,并且加起来等于1,任意pdf函数组合形成的pdf只要满足这两点都是合理的。
要弄清楚如何使s(direction)*color(direction)大的pdf更大,也就是找到合适的pdf,创造更真实的颜色比例效果。
对于漫反射表面,我们猜测它更偏重color因子。 大多数渲染器将镜面设计成一种特殊情况,只是隐含地使用s / p 进行计算,所以,我们目前也是这样。
三维方向随机向量生成
如何生成随机方向,假定z轴为表面法线,规定θ为法线张开的角度,此时只关注z轴,其他相关的来量都为均匀分布。假设一个在圆上的方向pdf,
p
(
d
i
r
e
c
t
i
o
n
)
=
f
(
θ
)
p(direction)=f(θ)
p(direction)=f(θ),在一维中θ和φ的pdf分别是:
a
(
φ
)
=
1
2
π
a(φ)=\frac{1}{2π}
a(φ)=2π1
b
(
θ
)
=
2
∗
π
∗
f
(
θ
)
s
i
n
(
θ
)
b(θ)=2*π*f(θ)sin(θ)
b(θ)=2∗π∗f(θ)sin(θ)
两个随即生成的均匀变量r1和r2
r
1
=
∫
0
φ
1
2
π
=
φ
2
π
r_1=\int_0^φ \frac{1}{2π}=\frac{φ}{2π}
r1=∫0φ2π1=2πφ
ϕ
=
2
π
∗
r
1
ϕ=2π*r_1
ϕ=2π∗r1
r
2
=
∫
0
θ
2
π
f
(
t
)
s
i
n
(
t
)
r_2=\int_0^θ2πf(t)sin(t)
r2=∫0θ2πf(t)sin(t)
尝试找到一个f(),当在球面上均匀密度采样,整个球面为4π,
p
(
d
i
r
e
c
t
i
o
n
)
=
1
4
π
p(direction)=\frac{1}{4π}
p(direction)=4π1
r
2
=
−
c
o
s
(
θ
)
2
−
−
c
o
s
(
0
)
2
=
1
−
c
o
s
(
θ
)
2
r_2=\frac{-cos(θ)}{2}-\frac{-cos(0)}{2}=\frac{1-cos(θ)}{2}
r2=2−cos(θ)−2−cos(0)=21−cos(θ)
c
o
s
(
θ
)
=
1
−
2
r
2
cos(θ)=1-2r_2
cos(θ)=1−2r2
然后用球坐标转换方程,生成向量
x
=
c
o
s
(
φ
)
∗
s
i
n
(
θ
)
x=cos(φ)*sin(θ)
x=cos(φ)∗sin(θ)
y
=
s
i
n
(
φ
)
∗
s
i
n
(
θ
)
y=sin(φ)*sin(θ)
y=sin(φ)∗sin(θ)
z
=
c
o
s
(
θ
)
z=cos(θ)
z=cos(θ)然后把
(
r
1
,
r
2
)
(r_1,r_2)
(r1,r2)代入方程
x
=
c
o
s
(
2
π
r
1
)
∗
2
r
2
(
1
−
r
2
)
x=cos(2πr_1)*2\sqrt {r_2(1-r_2)}
x=cos(2πr1)∗2r2(1−r2)
y
=
s
i
n
(
2
π
r
1
)
∗
2
r
2
(
1
−
r
2
)
y=sin(2πr_1)*2\sqrt {r_2(1-r_2)}
y=sin(2πr1)∗2r2(1−r2)
z
=
1
−
2
r
2
z=1-2r_2
z=1−2r2
然后我们再用我们之前假设的Lambertian的表面散射pdf,
p
(
d
i
r
e
c
t
i
o
n
)
=
c
o
s
θ
π
p(direction)=\frac{cosθ}{π}
p(direction)=πcosθ试试。依旧是:
b
(
θ
)
=
2
∗
π
∗
c
o
s
θ
π
s
i
n
(
θ
)
b(θ)=2*π*\frac{cosθ}{π}sin(θ)
b(θ)=2∗π∗πcosθsin(θ)
r
2
=
∫
0
θ
2
π
c
o
s
t
π
s
i
n
(
t
)
=
1
−
c
o
s
2
(
θ
)
r_2=\int_0^θ2π\frac{cost}{π}sin(t)=1-cos^2(θ)
r2=∫0θ2ππcostsin(t)=1−cos2(θ)
c
o
s
(
θ
)
=
1
−
r
2
cos(θ)=\sqrt{1-r_2}
cos(θ)=1−r2代入坐标系转换方程:
x
=
c
o
s
(
φ
)
∗
s
i
n
(
θ
)
=
c
o
s
(
2
π
r
1
)
r
2
x=cos(φ)*sin(θ)=cos(2πr_1)\sqrt{r_2}
x=cos(φ)∗sin(θ)=cos(2πr1)r2
y
=
s
i
n
(
φ
)
∗
s
i
n
(
θ
)
=
s
i
n
(
2
π
r
1
)
r
2
y=sin(φ)*sin(θ)=sin(2πr_1)\sqrt{r_2}
y=sin(φ)∗sin(θ)=sin(2πr1)r2
z
=
c
o
s
(
θ
)
=
1
−
r
2
z=cos(θ)=\sqrt{1-r_2}
z=cos(θ)=1−r2
标准正交基
上述生成的随机的方向是基于z轴为法线的特殊情况,接下来要用标准正交基来推广到真实法线。其实就是一个空间变换,可以用矩阵,但在这里直接用乘法,用法线和向上的up向量做叉乘的到t,再用t和n叉乘得到s,用任意点的(x,y,z)分别乘上s,t,n即可完成坐标的转换。
直接光照采样
我们是从摄像机出发发出射线求交,现在要让发往光源方向的射线变多。 d A dA dA表示光源表面积极的一小部分,假设采样到这一小部分的面积的概率是 P q ( q ) ∗ d A P_q(q)*dA Pq(q)∗dA对于单位球而言, d w dw dw为对应 d A dA dA的单位球表面面积的一小部分,假设采样到这一小部分的概率为 p ( d i r e c t i o n ) ∗ d w p(direction)*dw p(direction)∗dw d w = d A ∗ c o s ( a l p h a ) d i s t a n c e ( p , q ) 2 dw=\frac{dA*cos(alpha)}{distance(p,q)^2} dw=distance(p,q)2dA∗cos(alpha)采样到两者的概率相等: d A ∗ c o s ( a l p h a ) d i s t a n c e ( p , q ) 2 ∗ p ( d i r e c t i o n ) = P q ( q ) ∗ d A = d A A \frac{dA*cos(alpha)}{distance(p,q)^2}*p(direction)=P_q(q)*dA=\frac{dA}{A} distance(p,q)2dA∗cos(alpha)∗p(direction)=Pq(q)∗dA=AdA p ( d i r e c t i o n ) = d i s t a n c e ( p , q ) 2 d A ∗ c o s ( a l p h a ) p(direction)=\frac{distance(p,q)^2}{dA*cos(alpha)} p(direction)=dA∗cos(alpha)distance(p,q)2就有了我们要求的pdf。
总结
基本的算法以及思想基本阐述了一遍,这一章的pdf可以通过很多不同的数学方法取得,也可以进行pdf的混合,最终的目的是为了让光线的发射以及反射都更加偏向光源,怎么样配比,用什么公式效果更好需要慢慢调试。
这3本书很薄但基本把ray tracing的东西讲完了,当然很多年过去了,现在很多方法可以做的更好,但光线追踪的核心思想基本就是这些了。