Raytracer - 计算眼睛光线

Nic*_*ord 10 3d raytracing

我正在写一个光线追踪器(主要是为了好玩),虽然我过去写了一个,花了相当多的时间搜索,没有任何教程似乎揭示了透视投影中计算眼睛光线的方式,不使用矩阵.

我相信我最后一次这样做是因为(可能)x/y使用Quaternion类别从摄像机方向矢量无效地旋转眼睛矢量度.这是在C++中,我在C#中做这个,虽然这不是那么重要.

伪代码(假设V*Q =变换操作)

yDiv = fovy / height
xDiv = fovx / width

for x = 0 to width
    for y = 0 to height

        xAng = (x / 2 - width) * xDiv
        yAng = (y / 2 - height) * yDiv
        Q1 = up vector, xAng
        Q2 = camera right vector, yAng
        Q3 = mult(Q1, Q2)

        pixelRay = transform(Q3, camera direction)
        raytrace pixelRay

    next
next
Run Code Online (Sandbox Code Playgroud)

我认为这个问题的实际问题在于它模拟的是球形屏幕表面,而不是平面屏幕.

请注意,虽然我知道如何以及为什么使用交叉产品,点积,矩阵等,但我实际的3D数学问题解决技巧并不是很棒.

所以给出:

  • 相机位置,方向和向上矢量
  • 视野
  • 屏幕像素和/或子采样分区

为光线跟踪器生成x/y像素坐标的眼睛光线的实际方法是什么?

澄清一下:我正是我想要计算的,我只是不善于提出计算它的3D数学,并且我找不到光线跟踪器代码似乎有我需要的代码来计算眼睛光线个别像素.

在此输入图像描述

nin*_*cko 13

在此输入图像描述

INPUT: camera_position_vec, direction_vec, up_vec, screen_distance

right_vec = direction_vec x up_vec
for y from 0 to 1600:
    for x from 0 to 2560:
        # location of point in 3d space on screen rectangle
        P_3d = camera_position_vec + screen_distance*direction_vec
               + (y-800)*-up_vec
               + (x-1280)*right_vec

        ray = Ray(camera_position_vec, P_3d)
        yield "the eye-ray for `P_2d` is `ray`"
Run Code Online (Sandbox Code Playgroud)

x 是指交叉产品

编辑:答案假设direction_vec是规范化的,应该是.right_vec在图片中(似乎左边应该是),但是right_vec没有必要,如果包括在内,应该始终与方向相同-(up_vec x direction_vec).此外,图片暗示x-coord随着一个向右而增加,并且y-coord随着一个向下而增加.这些迹象略有改变以反映这一点.可以通过将等式中的x和y项相乘来执行缩放,或者更有效地,将矢量相乘并使用scaled_up_vec和来执行缩放scaled_right_vec.然而,变焦是等效的(因为光圈无关紧要;这是一个完美的针孔相机)来改变视野(FoV),这是一个比任意"变焦"更好的处理量.有关如何实施FoV的信息,请参阅下面的评论.

  • 考虑一下当你改变`screen_distance`(焦距)时会发生什么.随着您越来越近,图像变得更加广角.因此,假设我们希望以度为单位观察"FoV".如果考虑右边中间的最大y值,它将形成一个三角形,暗示`tan(FoV/2)= 800/screen_distance`.因此,如果我们设置`FoV`而不是`screen_distance`,我们将`screen_distance`设置为'800/tan(FoV/2)`.当然,人们不会使用固定值,如2560和1600,但你去了. (2认同)