近平面焦平面成像平面
GLSL-PathTracer
1 | float scale = tan(camera.fov * 0.5); |
刚开始看这段代码的时候,没有想清楚代码里预设的内容,也即成像平面的距离是1;这里面注意两个地方,成像平面(的距离,z方向的位移)上的点来确定光线的方向,以及对焦距离确定对焦点。
Near Plane(近平面) 是裁剪用的,距离相机很近(比如 0.01),比它更近的物体不渲染。在光栅化管线中有意义,在 path tracing 中通常不需要。
Image Plane(成像平面) 是代码中构造 rayDir
的那个虚拟平面,距离相机为 1(因为 camera.forward
是单位向量,d.x 和 d.y
是在这个平面上的偏移)。它的作用是把像素坐标转换为光线方向,跟最终画面的”对焦”无关。
focalDist(对焦距离)
是摄影概念,表示相机到”焦平面”的距离。焦平面上的物体是完全清晰的,偏离焦平面越远的物体越模糊(景深效果)。这个值一般比较大,比如
5.0、10.0,取决于你想对焦到场景中多远的位置,是针对于场景中的距离的概念。focalPoint计算这句,是在相机空间下计算的,其参与finalRayDir的计算为什么没有带上camera.position,因为一加一减,就不需要了。
smallpt
1 | int main(int argc, char *argv[]){ |
光线计算
1 | Vec d = cx*(((sx+.5+dx)/2+x)/w-.5) + cy*(((sy+.5+dy)/2+y)/h-.5) + cam.d; |
像素的 2×2 子像素结构: 每个像素被分成 2×2 的子像素(sx∈{0,1},sy∈{0,1})。对于子像素内的某一个采样点,它在像素内部的位置可以这样理解:
以 x 方向为例,(sx + 0.5 + dx) / 2
计算的是采样点在当前像素内的相对偏移(范围大致 [0, 1])。其中
sx + 0.5 是子像素的中心位置(sx=0 时为 0.5,sx=1 时为
1.5),dx 是 tent filter 产生的随机抖动(范围 [-1,
1]),除以 2 是因为一个像素被分成了 2 个子像素。所以当 sx=0
时,采样中心在像素内偏移 0.25 处;sx=1 时在 0.75
处,两个子像素的采样区域合理地覆盖了整个像素。
映射到归一化屏幕坐标: 加上像素坐标 x
后除以图像宽度 w,再减去
0.5,就得到了一个以图像中心为原点、范围约 [-0.5, 0.5] 的归一化坐标。y
方向同理。
合成方向向量: cx 和 cy
是相机的”右”和”上”方向基向量,它们的长度编码了视场角(FOV)。cx = Vec(w * 0.5135 / h, 0, 0)
保证了宽高比正确,cy 的长度为
0.5135,对应垂直方向的半视场角约为 ((0.5135/2) °)。将归一化坐标分别乘以
cx 和 cy,再加上相机的朝向
cam.d,就得到了这条采样光线的(未归一化的)方向向量
d。
本质上这就是一个针孔相机模型:cam.d
指向图像中心,cx 和 cy
控制偏离中心的程度。
其中,cam.d = Vec(0,-0.042612,-1),x分离是0;Vec cx=Vec(w*.5135/h, 0, 0),cx的y、z分量也分别为0。cam.d和cx是正交的。相机到成像平面的距离是1,cam.d是归一化后的向量,Vec d的计算中,x/y方向上的偏移后直接加的cam.d,其实是省略了cam.d * length。从光线的方向d的计算中,可得cy的跨度是0.5135,因此\(\tan\frac{fov}{2} =
\frac{0.5135}{2}\)。
光照计算
1 | r = r + radiance(Ray(cam.o + d*140, d.norm()), 0, Xi) * (1./samps); |
光线起点前推 (cam.o + d * 140):
相机实际位置在 ((50, 52, 295.6)),位于 Cornell Box
的外面(场景大致在 (z )
范围内)。如果光线从相机原点出发,需要先穿过盒子的开口才能进入场景内部。通过沿方向
d 前推 140 个单位,光线起点被移到了大约 (z )
的位置,也就是直接从盒子内部开始,避免了不必要的求交计算。代码注释
"Camera rays are pushed forward to start in interior"
说的就是这个意思。
采样平均 (* (1./samps)):
每个子像素内取 samps 个采样,每个采样的辐射贡献乘以 (1/)
后累加到 r 中,实现蒙特卡洛积分的均值估计。外层还有
c[i] = c[i] + Vec(clamp(r.x),clamp(r.y),clamp(r.z))*.25,即四个子像素各贡献
1/4。