光线跟踪器:高视场失真

时间:2018-03-12 13:54:00

标签: c++ geometry raytracing

我实际上是在实现一个C ++光线跟踪器,而且我遇到了一个关于光线跟踪的经典问题。当放置高垂直FOV时,形状会越靠近边缘就会产生更大的失真。

我知道为什么会发生这种扭曲,但我不知道如何解决它(当然,减少FOV是一种选择,但我认为我的代码中有一些变化)。我一直在浏览不同的计算论坛,但没有找到解决方法。

这是一个截图来说明我的问题。

Distortion on edges with spheres

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

我是一个右撇子导向系统。 Camera系统矢量,Direction矢量和Light矢量被标准化。

如果您需要一些代码来检查某些内容,我会将其与您提出的部分进行回答。

光线生成代码:

        // 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);

1 个答案:

答案 0 :(得分:3)

您的预测没有任何问题。它产生的应该是它应该产生的东西。

让我们考虑下图来了解所有数量如何相互作用:

Field of View

我们有摄像机位置,视野(作为角度)和图像平面。图像平面是您将3D场景投影到的平面。从本质上讲,这代表了您的屏幕。当您在屏幕上查看渲染时,您的眼睛将用作相机。它可以看到投影的图像,如果它位于正确的位置,它将看到实际的3D场景在那里会看到什么(忽略像景深等效果)。

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

Field of View

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

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