Raytracer:高 FOV 失真

Raytracer : High FOV distortion

我实际上正在实现一个 C++ 光线追踪器,我正面临一个关于光线追踪的经典问题。当放置高垂直 FOV 时,形状越靠近边缘变形越大。

我知道为什么会出现这种失真,但我不知道如何解决它(当然,减少 FOV 是一种选择,但我认为我的代码中有一些地方需要更改)。我一直在浏览不同的计算论坛,但没有找到任何解决方法。

这是说明我的问题的屏幕截图。

我认为问题在于我投射光线的视平面实际上并不平坦,但我不知道如何解决这个问题。如果您有任何解决问题的技巧,我愿意接受建议。

我使用的是右手系统。 相机系统向量、方向向量和光向量被归一化。

如果你需要一些代码来检查某些东西,我会把它放在你问的部分的答案中。

光线生成代码:

        // PixelScreenX = (pixelx + 0.5) / imageWidth
        // PixelCameraX = (2 ∗ PixelScreenx − 1) ∗
        //      ImageAspectRatio ∗ tan(fov / 2)
        float x = (2 * (i + 0.5f) / (float)options.width - 1) *
                options.imageAspectRatio * options.scale;

        // PixelScreeny = (pixely + 0.5) / imageHeight
        // PixelCameraY = (1 − 2 ∗ PixelScreeny) ∗ tan(fov / 2)
        float y = (1 - 2 * (j + 0.5f) / (float)options.height) * options.scale;

        Vec3f dir;
        options.cameraToWorld.multDirMatrix(Vec3f(x, y, -1), dir);
        dir.normalize();
        newColor = _renderer->castRay(options.orig, dir, objects, options);

你的投影没有问题。它产生的正是它应该产生的。

让我们考虑下图,看看所有数量是如何相互作用的:

我们有相机位置、视野(角度)和图像平面。图像平面是您将 3D 场景投影到的平面。本质上,这代表您的屏幕。当您在屏幕上查看渲染时,您的眼睛充当相机。它会看到投影图像,如果它位于正确的位置,它会准确看到实际 3D 场景存在时会看到的内容(忽略景深等效果)

显然,您无法修改屏幕(您可以更改 window 大小,但让我们坚持使用 constant-size 图像平面)。然后,相机的位置和视野之间存在直接关系。随着视野的增加,相机越来越靠近图像平面。像这样:

因此,如果您在代码中增加视野,则需要将眼睛移近屏幕以获得正确的感知。您实际上可以尝试使用您的图像。将眼睛移近屏幕(我说的是 3 厘米)。如果你现在再看外面的球体,它们实际上又像真球了。

总而言之,视野应与观看设置的几何形状大致匹配。对于给定的屏幕尺寸和平均观看距离,这可以很容易地计算出来。如果您的观看设置与您在代码中的假设不符,3D 感知将会崩溃。