6

我目前正在研究光线追踪技术,我认为我做得很好;但是,我还没有涵盖相机。

(-width/2, height/2, 200)到目前为止,我使用了一个平面片段作为视图平面,它位于(width/2, -height/2, 200)[200 只是 z 的固定数量,可以更改] 之间。

除此之外,我主要使用相机e(0, 0, 1000),并使用透视投影。

我将光线从点发送e到像素,并在计算像素颜色后将其打印到图像的相应像素。在此处输入图像描述

这是我创建的图像。希望您可以通过查看图像来猜测眼睛和视图平面的位置。

我的问题从这里开始。是时候移动我的相机了,但我不知道如何将 2D 视图平面坐标映射到规范坐标。有没有一个转换矩阵?

我认为的方法需要知道视图平面上像素的 3D 坐标。我不确定这是使用正确的方法。所以你有什么建议?

4

2 回答 2

18

有多种方法可以做到这一点。这就是我所做的:

  1. 选择一个点来表示相机位置 ( camera_position)。
  2. 选择一个向量来指示相机正在看的方向 ( camera_direction)。(如果您知道相机正在查看的点,则可以通过camera_position从该点减去该点来计算该方向向量。)您可能想要归一化 ( camera_direction),在这种情况下,它也是图像平面的法线向量。
  3. 选择另一个从相机的角度(大约)“向上”的归一化向量(camera_up)。
  4. camera_right = Cross(camera_direction, camera_up)
  5. camera_up = Cross(camera_right, camera_direction)(这可以纠正选择“向上”的任何错误。)

在 处可视化图像平面的“中心” camera_position + camera_direction。上和右向量位于图像平面中。

您可以选择图像平面的矩形部分以对应您的屏幕。这个矩形部分的宽度或高度与 camera_direction 的长度之比决定了视野。要放大,您可以增加 camera_direction 或减少宽度和高度。做相反的事情来缩小。

所以给定一个像素位置(i, j),你想要(x, y, z)图像平面上的那个像素。从中您可以减去camera_position以获得光线矢量(然后需要对其进行归一化)。

Ray ComputeCameraRay(int i, int j) {
  const float width = 512.0;  // pixels across
  const float height = 512.0;  // pixels high
  double normalized_i = (i / width) - 0.5;
  double normalized_j = (j / height) - 0.5;
  Vector3 image_point = normalized_i * camera_right +
                        normalized_j * camera_up +
                        camera_position + camera_direction;
  Vector3 ray_direction = image_point - camera_position;
  return Ray(camera_position, ray_direction);
}

这只是说明性的,因此未进行优化。

于 2012-10-25T23:20:43.903 回答
4

对于光栅化渲染器,您往往需要一个转换矩阵,因为这是您直接从 3D 坐标映射到屏幕 2D 坐标的方式。

对于光线追踪,这不是必需的,因为您通常2D 空间中的已知像素坐标开始。

给定眼睛位置、屏幕中心的 3 空间中的一个点以及“上”和“右”的向量,很容易计算从眼睛位置穿过指定位置的 3D“射线”像素。

我之前在https://stackoverflow.com/a/12892966/6782上发布了一些来自我自己的光线追踪器的示例代码

于 2012-10-25T22:32:27.043 回答