我实际上是在实现一个C ++光线跟踪器,而且我遇到了一个关于光线跟踪的经典问题。当放置高垂直FOV时,形状会越靠近边缘就会产生更大的失真。
我知道为什么会发生这种扭曲,但我不知道如何解决它(当然,减少FOV是一种选择,但我认为我的代码中有一些变化)。我一直在浏览不同的计算论坛,但没有找到解决方法。
这是一个截图来说明我的问题。
我认为问题在于,我投射光线的视平面实际上并不平坦,但我不知道如何解决这个问题。如果您有任何解决方法,我可以接受建议。
我是一个右撇子导向系统。 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);
答案 0 :(得分:3)
您的预测没有任何问题。它产生的应该是它应该产生的东西。
让我们考虑下图来了解所有数量如何相互作用:
我们有摄像机位置,视野(作为角度)和图像平面。图像平面是您将3D场景投影到的平面。从本质上讲,这代表了您的屏幕。当您在屏幕上查看渲染时,您的眼睛将用作相机。它可以看到投影的图像,如果它位于正确的位置,它将看到实际的3D场景在那里会看到什么(忽略像景深等效果)。
显然,您无法修改屏幕(您可以更改窗口大小,但让我们坚持使用恒定大小的图像平面)。然后,相机的位置和视野之间存在直接关系。随着视野的增加,相机越来越靠近图像平面。像这样:
因此,如果您在代码中增加视野,则需要将眼睛移近屏幕以获得正确的感知。你可以尝试用你的图像。移动你的眼睛非常靠近屏幕(我说的是3厘米)。如果你现在看外面的球体,它们实际上看起来像真正的球。
总之,视野应与观察设置的几何形状大致匹配。对于给定的屏幕尺寸和平均观看距离,可以很容易地计算出来。如果您的查看设置与您在代码中的假设不符,则3D感知将会崩溃。