我正在阅读计算机图形学的基础知识并尝试设置我自己的光线跟踪器。这本书说"最常见的构建相机框架的方法是从视角,即视图方向,即-w,以及向上矢量,用于构建具有v和w在由视图方向和向上方向定义的平面中"
然后我遇到了How to move a camera using in a ray-tracer?,它说我们需要通过执行与摄像机方向(w)的交叉积来校正(斜率?)的向上矢量。那是为什么?
我用lookAt(0,0,0)和向上(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 %.2f\n", u.getX(), u.getY(), u.getZ()); // prints 0 1 0
u = v.cross(w).normalize(); // the up vector
printf("%.2f %.2f %.2f\n", u.getX(), u.getY(), u.getZ()); // prints 0.31 -0.86 -0.41
}
答案 0 :(得分:2)
最终你需要的是一对矢量,它们形成了图像平面的标准正交基础。其中一个将指向相对于相机方向的右侧。另一个是相对于相机的方向指向。
如果向上矢量是一般的“天空就是这样”,如果你的相机不是水平的,那么向上矢量和相机向上矢量会略有不同。向上矢量是您想要的方向的提示,但它不是正确的向量。在这种情况下,您可以使用方向向量跨越右向量,这将为您提供位于图像平面中并垂直于右向量的向量。这就是你想要的。
如果向上矢量是一般的“天空是这样的”,并且如果你的相机是级别,则向上矢量和camera_up矢量将完全相同。额外的交叉产品是不必要的,但如果您希望代码足够通用以处理第一种情况,那么它就没有任何害处。
也许某些ASCII艺术可以帮助澄清......
^ * look-at point
| "up" "camera up"
| \
| image plane \
\
"camera down"
向上矢量直线上升。观察点高于相机,因此相机必须向后倾斜一点。在图中,我们看到了图像平面的边缘。 “右”矢量位于该平面中并从图中指出。方向向量(您的代码称为w
)垂直于图像并直接指向观察点。
相机向上矢量(代码中的u
)必须位于图像平面中,因此我们不能只使用“向上”。它必须垂直于“右”向量。最简单的方法是跨越这两个向量。
由于我们根据原始向上矢量生成了“右”向量,因此可以为我们提供方向。