C++ 如何在光线跟踪器中移动摄影机?

C++ 如何在光线跟踪器中移动摄影机?,c++,camera,transformation,raytracing,C++,Camera,Transformation,Raytracing,我目前正在研究光线追踪技术,我认为我做得相当好;但是,我还没有谈到相机 到目前为止,我使用了一个平面片段作为视图平面,它位于(-width/2,height/2200)和(width/2,-height/2200)[200只是一个固定的z数,可以更改] 除此之外,我主要在e(0,0,1000)上使用相机,并使用透视投影 我将光线从点e发送到像素,并在计算像素颜色后将其打印到图像的对应像素 这是我创建的一个图像。希望您可以通过查看图像猜出眼睛和视图平面的位置 我的问题从这里开始。是时候移动我的相机

我目前正在研究光线追踪技术,我认为我做得相当好;但是,我还没有谈到相机

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

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

我将光线从点
e
发送到像素,并在计算像素颜色后将其打印到图像的对应像素

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

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


我认为这种方法需要知道视图平面上像素的三维坐标。我不确定这是正确的方法。那么,您有什么建议?

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

对于光线跟踪,这是不必要的,因为通常从二维空间中的已知像素坐标开始

给定眼睛位置、屏幕中心的3空间点以及“向上”和“向右”矢量,计算从眼睛位置经过指定像素的3D“光线”非常容易


我之前在

上发布了一些来自我自己的光线跟踪器的示例代码,有多种方法可以做到这一点。我是这样做的:

  • 选择一个点来表示相机位置(
    相机位置
  • 选择一个矢量,该矢量指示相机正在查看的方向(
    camera\u direction
    )。(如果您知道相机正在查看的点,可以通过从该点减去
    相机位置
    来计算该方向向量。)您可能希望规格化(
    相机方向
    ),在这种情况下,它也是图像平面的法向量
  • 选择另一个从摄影机的角度(大约“向上”)的标准化向量(
    camera\u up
  • camera\u right=交叉(camera\u方向,camera\u向上)
  • camera\u up=Cross(camera\u right,camera\u direction)
    (这会纠正选择“up”时的任何坡度。)
  • 将图像平面的“中心”显示在
    camera\u位置+camera\u方向
    。上方向向量和右方向向量位于图像平面中

    您可以选择与屏幕相对应的图像平面的矩形部分。该矩形截面的宽度或高度与摄影机方向长度的比率决定了视野。要放大,可以增加摄影机的方向或减小宽度和高度。执行相反的操作以缩小

    因此,给定一个像素位置
    (i,j)
    ,您需要该像素在图像平面上的
    (x,y,z)
    。您可以从中减去
    摄影机位置
    以获得光线向量(然后需要对其进行归一化)


    这是为了说明问题,因此未对其进行优化。

    请看我在视野计算中迷失了方向。请您详细说明一下这些代码行:dir.add_scaled(右,m_tanf*m_aspect*x);方向加成比例(向上,m_tanf*y);dir.normalise()
    v.add_scaled(d,n)
    只做
    v+=(d*n)
    其中
    d
    是一个向量,
    n
    是比例因子。这两条线计算视图平面中与像素相交的点,该点位于
    (x,y)
    ,其中
    x
    y
    -1..1
    范围内。这对我来说不太合适,但我想我明白了。在“Vector3 image_point=i*camera_right+j*camera_up+camera_position+camera_direction”中,您是指标准化的_i和标准化的_j吗?是的,我是指使用标准化的i和j(在回答中已更正)。请注意,
    ray\u direction
    在将其添加到
    image\u point
    后立即减去
    camera\u position
    ,因此您可以简单地忽略它,但我觉得这模糊了逻辑。我不知道你在说什么扭曲。在广角视图中,对象确实会在帧边缘附近发生扭曲(例如,球体看起来是长方形的)。@RdIP:如果您将像素视为一个小1x1正方形,则希望光线穿过它的中间,而不是角。@binaryBigInt:如果您有相机的位置和指向的方向,您没有足够的信息来了解相机的方向。如果将摄影机指向某人的脸,可以沿其外观的轴转动摄影机,使该脸在图像中处于侧面或倒置状态。所以我们选择一个
    摄像机向上
    向量来消除这种模糊性。由此,我们可以导出
    camera\u right
    ,它与
    camera\u up
    一起定义胶片或图像传感器在世界空间中的平面。@RdIP:正如我所说,有多种方法。对我来说,FOV不是很直观,所以我更喜欢根据焦距和相机型号来考虑。这一切归结为相同的转换。
    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);
    }