在光线追踪器的相机设置中设置向上矢量

Setting the up vector in the camera setup in a ray tracer

我正在阅读计算机图形学基础知识并尝试设置我自己的光线追踪器。书上说 "The most common way to construct the camera frame is from the viewpoint, which becomes e, the view direction, which is−w, and the up vector, which is used to construct a basis that has v and w in the plane defined by the view direction and the up direction"

但后来我遇到了 How to move a camera using in a ray-tracer?,它说我们需要通过与相机方向 (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 %.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
}

你最终需要的是一对构成图像平面正交基的向量。其中之一将指向相对于相机方向的右侧。另一个将相对于相机的方向指向上方。

如果向上矢量是一般的"the sky is that way,"并且如果您的相机不水平,则向上矢量和相机向上矢量会略有不同。向上向量是关于您想要的方向的提示,但它并不是完全正确的向量。在这种情况下,您可以将右矢量与方向矢量交叉,这将为您提供一个位于图像平面内并垂直于右矢量的矢量。这就是你想要的。

如果向上矢量是一般的"the sky is that way,"并且如果你的相机水平,那么向上矢量和camera_up矢量将恰好是相同的。额外的叉积是不必要的,但如果您希望代码足够通用以处理第一种情况,它也没有坏处。

也许一些 ASCII 艺术可以帮助澄清...

^                                        * look-at point
| "up"        "camera up"
|                  \ 
|       image plane \
                     \
                 "camera down"

向上矢量是直线向上的。观察点高于相机,因此相机必须向后倾斜一点。在图中,我们看到图像平面的边缘。 "right" 向量位于该平面内并指向图中。方向矢量(您的代码称为 w)垂直于图像并直接指向观察点。

相机向上矢量(代码中的 u)必须位于图像平面内,因此我们不能只使用 "up"。并且它必须垂直于 "right" 向量。最简单的方法是交叉这两个向量。

由于我们根据原始向上向量生成了 "right" 向量,这给了我们方向。