PBR读书笔记二:Basic Shapes
在整个图形学领域,空间中的物体都是由基本的Shape构成的,比如基本的几何形体:Sphere、Box;或者能够达成更加复杂表现的Mesh等。这一章主要讲述了几种不同的形体的定义和相关计算。
形体基类
PBRT
使用Shape
类来为所有形体创建了一个基类,reverseOrientation
用来决定图形的法线是否翻转(用来确定图形的内、外)。
对于每个形体有如下的基础函数和解释:
1 | virtual Bounds3f ObjectBound() const = 0; |
aabb bounding box,用于加速相交求解。
1 | virtual bool Intersect(const Ray &ray, Float *tHit, |
光线和物体的相交(实际),保证: - 光线未达到终点 - 返回的相交点最近
intersectP
方法用于忽略一些返回值。
1 | virtual Float Area() const = 0; |
物体的面积,用于计算面积光源。
由于物体不保证封闭,并且光线追踪算法的特殊性,pbrt没有采用背面剔除算法。
1 | virtual Interaction Sample(const Point2f &u) const = 0; |
剩下的就是和光照有关的重要性采样(Sample)、概率分布函数(pdf)的内容,不作为重点赘述。
光线与包围盒的相交
对于一个定义\(\vec r = o + t\vec d\)的光线,假设其与平面\(ax+by+cz+d = 0\)相交,可有解为\(t = \frac{-\vec d-((a,b,c)\cdot o)}{((a,b,c)\cdot \vec d)}\),而对于由\(x\)决定的平面,则可以进一步地简写为:\(t_0=\frac{x_0-o_x}{d_x}\)。
则相应地,我们的代码如下:
1 | Float invRayDir = 1 / ray.d[i]; |
自然,这两个Near和Far的变量的顺序并不一定正确,于是需要根据两个变量的大小交换,这里需要考虑到浮点数出现0/0导致的NaN
问题,这里利用一条性质:
NaN
浮点数和任何其他浮点数进行比较的返回必定是false
于是更新t0和t1的代码需要仔细一些额外处理(t0、t1是最终返回的值):
1 | t0 = tNear > t0 ? tNear : t0; |
(虽然我觉得用stl的std::max
和std::min
会好一些
PBR读书笔记二:Basic Shapes