本文未经允许禁止转载 B站:https://space.bilibili.com/455965619 作者: Heskey0 / 赫斯基皇
三.lambertian材质的半球采样
因为lambertian 材质涉及到的知识比较多,所以单独用一章进行讲解 在本章中,我会讲解漫反射的一部分知识:
1.cosine hemisphere sampling
2.计算lambertian材质的漫反射法线方向和pdf
我们要实现对球面的uniform sampling ,可以先在圆盘中采样
- 在一个正方形中采样
- 将点转换到一个圆,并且用极坐标表示
- 将圆上的点映射到半球
(1) concentric sample
我们先对正方形进行均匀采样
x = ti.random() * 2.0 - 1.0
y = ti.random() * 2.0 - 1.0
在上述代码中,x和y均为 -1 ~ 1 ,这样采样到的点是连续的。
然后,我们使用concentric sample 的方式将(x,y) 从笛卡尔坐标系中的正方形映射到极坐标系中的圆 即:(x,y) => (r,θ)
我们具体代码的实现:
if x != 0 or y != 0:
if abs(x) > abs(y):
r = x
theta = np.pi / 4 * (y / x)
else:
r = y
theta = np.pi / 4 * (2 - x / y)
那么,为何不直接使用高中学的 坐标变换公式
即:
{
r
=
x
2
+
y
2
θ
=
a
r
c
t
a
n
(
y
x
)
\begin{cases} r=\sqrt{x^2+y^2}\\ \theta=arctan(\frac{y}{x}) \end{cases}
{r=x2+y2
?θ=arctan(xy?)?
注意: 我们的目的是uniform sampling ,而平方,开方,
a
r
c
t
a
n
(
)
arctan()
arctan() 破坏了(x,y) 的线性关系。 (
θ
=
π
4
?
b
a
\theta=\frac{\pi}{4}*\frac{b}{a}
θ=4π??ab?虽然使用了除法,但当a不变时,
θ
\theta
θ依然是连续的)
(2) Malley’s method
然后,我们需要将点(r,φ) (即上面的(r,θ) )从极坐标系映射到球坐标系 即: (r,φ) => (θ,φ)
原理有些复杂,我们先看代码:
u = ti.Vector([1.0, 0.0, 0.0])
if abs(normal[1]) < 1 - eps:
u = normal.cross(ti.Vector([0.0, 1.0, 0.0]))
v = normal.cross(u)
xy = r*ti.cos(phi)*u + r*ti.sin(phi)*v
zlen = ti.sqrt(max(0.0, 1.0 - xy.dot(xy)))
return xy + zlen * normal
我们先看u 和v 的作用
- 不需要关心normal和vector.up的关系,vector.up的引入是为了 辅助建立起坐标系
(u,v,normal) - 从计算中可以看出:
u,v 垂直, 长度均为sin(phi) , 均 在微平面上 - 由 normal为中心轴 , u和v为水平轴 建立笛卡尔坐标系
这里插一句:要表示一个法线(x,y,z) 的方向,我们只需要两个数据:(x,y) 。因为,我们可以通过
z
=
1
?
x
2
?
y
2
z=\sqrt{1-x^2-y^2}
z=1?x2?y2
? 计算出z的值。
代码中的xy 其实就是在(u,v) 平面中的一个向量,我们根据
z
=
1
?
x
2
?
y
2
z=\sqrt{1-x^2-y^2}
z=1?x2?y2
? 求出z 的长度值。注意:我们的运算不是在(x,y,z) 坐标系中进行的,而是在(u,v,normal) 坐标系中。所以,我们的求出的z 长度值还要乘以normal 向量。
返回值为漫反射材质表面的法线(u )
最后,根据此法线(u ),可以求出pdf 的值
pdf = max(0.0001, normal.dot(u) / np.pi)
normal 为垂直于材质表面的法线,u 为计算出漫反射的法线 注意:normal 和u 均为单位向量,上面代码等价于:
p
d
f
=
cos
?
(
?
)
π
{pdf}=\frac{\cos(\phi)}{\pi}
pdf=πcos(?)? [
?
\phi
?为u与normal的夹角]
|