我正在阅读计算机图形学的基础知识,并试图建立自己的光线跟踪器。这本书说:"构造相机框架的最常见方法是从视点,即e,即视角方向,即−w,以及上向量,该向量用于构造在由视角方向和上方向定义的平面中具有v和w的基"
但后来我遇到了如何在光线跟踪器中移动相机?这意味着我们需要通过与相机方向(w)进行叉积来校正(斜率?)的向上矢量。为什么?
我用lookAt(0,0,0)和up(0,1,0)调用我的相机设置
// a camera can be constructed using a position, direction and an up vector
Camera::Camera(Vector position, Vector lookAt, Vector up) {
this->position = position;
this->lookAt = lookAt;
// the difference between camera position and where we want
// to look at is the direction of the camera
Vector direction = lookAt.diff(position);
// camera frame
w = direction.normalize();
v = up.cross(w).normalize(); // right vector
// which is the correct up?
u = up.normalize();
printf("%.2f %.2f %.2fn", u.getX(), u.getY(), u.getZ()); // prints 0 1 0
u = v.cross(w).normalize(); // the up vector
printf("%.2f %.2f %.2fn", u.getX(), u.getY(), u.getZ()); // prints 0.31 -0.86 -0.41
}
最终需要的是一对向量,它们形成图像平面的正交基。其中一个将指向相对于相机方向的右侧。另一个是相对于摄影机的方向指向上。
如果向上矢量是一般的"天空就是这样",如果你的相机不是水平的,那么向上矢量和相机向上矢量会略有不同。向上矢量是关于所需方向的提示,但它并不完全是正确的矢量。在这种情况下,你可以将右向量与方向向量相交,这将给你一个位于图像平面中的向量,垂直于右向量。这就是你想要的。
如果向上矢量是一般的"天空就是这样",并且如果你的相机是级别,那么向上矢量和camera_up矢量将完全相同。额外的叉积是不必要的,但如果您希望代码足够通用以处理第一种情况,那么它也没有害处。
也许一些ASCII艺术可以帮助澄清。。。
^ * look-at point
| "up" "camera up"
|
| image plane
"camera down"
向上矢量是直线向上的。观察点比相机高,所以相机必须向后倾斜一点。在图中,我们看到了图像平面的边缘。"右"向量在那个平面上,并在图中指出。方向向量(您的代码称之为w
)垂直于图像,并直接指向观察点。
相机上方向矢量(代码中的u
)必须位于图像平面中,所以我们不能只使用"上"。它必须垂直于"右"向量。最简单的方法是将这两个向量交叉。
由于我们根据原始向上向量生成了"右"向量,这就给了我们方向。