【问题标题】:Raytracer - Computing Eye RaysRaytracer - 计算眼睛光线
【发布时间】:2011-08-22 02:16:04
【问题描述】:

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

我相信我最后一次这样做是(可能)使用Quaternion 类从相机方向向量中低效地旋转眼睛向量x/y 度数。这是用 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 数学来计算它,而且我发现似乎没有光线追踪器代码我需要计算单个像素的眼睛光线的代码。

【问题讨论】:

    标签: 3d raytracing


    【解决方案1】:

    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 的信息,请在下方查看我的评论。

    【讨论】:

    • 谢谢。对不起,我应该在这个问题上让自己更清楚。实际上,我的脑海中已经有了这种实现。如果 x 为 -0.5 到 0.5,纵横比无法承受,如何计算具有视场角的屏幕距离?
    • 考虑当你改变screen_distance(焦距)时会发生什么。随着您将其越来越近,图像变得越来越广角。因此,假设我们需要以度为单位的视野FoV。如果考虑右边缘中间的最大 y 值,它将形成一个三角形,暗示tan(FoV/2) = 800/screen_distance。因此,如果我们设置FoV 而不是screen_distance,我们将screen_distance 设置为800/tan(FoV/2)。当然,我们不会使用 2560 和 1600 之类的固定值,但你就可以了。
    猜你喜欢
    • 1970-01-01
    • 2019-02-27
    • 1970-01-01
    • 2014-12-21
    • 2012-03-14
    • 1970-01-01
    • 2011-05-26
    • 2012-09-21
    • 2012-03-20
    相关资源
    最近更新 更多