当长宽比不为 1 时,光线追踪会导致图像扭曲

问题描述 投票:0回答:2

我使用 C++ 从头开始制作了光线追踪算法,并实现了一个球体作为测试对象。然而,只有当 FOV 接近 90 度且纵横比为 1.0 时,我才能获得完美的球体二维横截面。任何进一步偏离这些参数都会导致球体扭曲。

纵横比:0.75,FOV:89 度 Aspect Ratio: 0.75, FOV: 89 deg

纵横比:1.0,FOV:89 度 Aspect Ratio: 1.0, FOV: 89 deg

长宽比:1.33,FOV:89 Aspect Ratio: 1.33, FOV: 89

我没有看到编写代码的意义,但这就是我的主文件的样子:

int main(int argc, char** argv)
{


  size_t width = 480;
  size_t height = 360;
  //Image newImg(width, height);

  Vector3D cameraOrigin(-5.0, 1.0, 0.0);
  Vector3D imgLoc(0.0, 1.0, 0.0);
  Vector3D upGuide(0.0, 1.0, 0.0);
  double fov = 89.0;
  double aspectRatio = (double)width/(double)height;
  std::cout << "aspect ratio : " << aspectRatio << "\n";

  PerspectiveCamera camera(cameraOrigin,
                           imgLoc,  
                           upGuide, fov,
                           aspectRatio);

  Sphere sphere(Vector3D(0.0, 0.0, 0.0), 0.5);

  png::image< png::rgb_pixel > image(width, height);

  //call to ray trace function
  rayTrace(&camera, &sphere, image);     
    return 0;

rayTrace() 函数如下所示:

void rayTrace(Camera *camera, Shape *shape, png::image< png::rgb_pixel > &image)
{
    // Do nothing
    for (size_t x = 0; x < image.get_width(); x++)
    {
        for (size_t y = 0; y < image.get_height(); y++)
        {
            Vector3D screenCoord( ((2.0*x/image.get_width())-1.0), ((2.0*y/image.get_height()) - 1.0), 0.0);
            Ray ray = camera->makeRay(screenCoord);

            Intersection intersection(ray);

            if (shape->intersect(intersection))
            {

                image[y][x] = png::rgb_pixel(23,69,46);
            }
            else
            {

                image[y][x] = png::rgb_pixel(255,255,255);
            }
        }
    }

     image.write("sphere.png");

}
    }

可以看出,rayTrace 函数中存在某些函数调用,它们创建光线并使光线与对象(在我的例子中为球体)相交,并相应地为像素着色。

但是图像扭曲的问题仍然存在。

c++ raytracing
2个回答
3
投票

您需要按纵横比缩放 x 或 y。 IE。对于恒定的垂直 FoV:

Vector3D screenCoord( ((2.0*x/image.get_width())-1.0) / camera->aspectRatio, ((2.0*y/image.get_height()) - 1.0), 0.0);

...或恒定水平 FoV:

Vector3D screenCoord( ((2.0*x/image.get_width())-1.0), ((2.0*y/image.get_height()) - 1.0) * camera->aspectRatio , 0.0);

我假设相机中存储了长宽比。否则你也必须通过它。


0
投票

当纵横比不是 1.0 时,我在光线追踪器中遇到了同样的图像扭曲问题。经过调查,我意识到问题与水平视野 (FOV) 的计算方式有关。

问题:

出现失真的原因是我错误地通过将垂直FOV乘以纵横比来计算水平FOV。这种方法是有缺陷的,因为角度和纵横比之间的关系不是线性的。相反,这是一种非线性关系,需要以不同的方式解决。

解决方案:

为了纠正这个问题,我调整了计算如下:

1。计算图像平面距离: 首先,我使用垂直 FOV 计算图像平面与相机原点的距离:

let baseDistance = (imageHeight / 2.0) / (verticalFOVRadians / 2.0).tan();

这里,baseDistance 是从相机到图像平面的距离,由垂直 FOV 和图像高度得出。

2。计算水平 FOV: 然后,我使用上面计算的距离计算水平 FOV:

let horizontalFOVRadians = 2.0 * ((imageWidth / 2.0) / baseDistance).atan();

此方法通过查找与给定计算距离的图像平面宽度相对应的角度来计算水平 FOV。

说明:

baseDistance 计算找到从相机到图像平面的距离,使得垂直 FOV 适合图像的高度。 使用此距离,通过考虑图像平面的宽度来计算水平 FOV。 此方法可确保正确考虑宽高比和视场,从而实现准确的渲染而不失真。

希望这有助于澄清问题,并为面临类似问题的其他人提供有用的解决方案!

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.