10

我正在写一个光线追踪器(主要是为了好玩),虽然我过去写过一个,并且花了相当多的时间搜索,但似乎没有教程能阐明在透视投影中计算眼睛光线的方法,不使用矩阵。

我相信我最后一次这样做是(可能)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

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

请注意,虽然我知道如何以及为什么要使用叉积、点积、矩阵等,但我实际的 3D 数学问题解决能力并不出色。

所以给出:

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

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

澄清一下:我正是我想要计算的,我只是不擅长提出 3D 数学来计算它,而且我发现没有光线追踪器代码似乎有我需要计算眼睛光线的代码单个像素。

在此处输入图像描述

4

1 回答 1

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`"

x表示叉积

编辑:答案假设direction_vec是标准化的,因为它应该是。right_vec在图片中(看起来应该在左边),但right_vec不是必需的,如果包括在内,应该始终与-(up_vec x direction_vec). 此外,图片暗示 x 坐标随着向右而增加,而 y 坐标随着向下而增加。标志已经稍微改变以反映这一点。缩放可以通过将方程中的 x 和 y 项相乘来执行,或者更有效地,将向量相乘并使用scaled_up_vecscaled_right_vec. 然而,变焦等效于改变视场(FoV)(因为光圈无关紧要;这是一个完美的针孔相机),这比任意“变焦”要好得多。有关如何实施 FoV 的信息,请参阅下面的评论。

于 2011-05-10T02:00:36.317 回答