0
votes

I have made a ray tracing algorithm using C++ , from scratch and implemented a sphere as an object for testing. However, I get perfect 2D cross section of a sphere only when the FOV is near to 90 degrees and the aspect ratio is 1.0 . Any further deviation from these parameters causes the sphere to be distorted.

Aspect Ratio: 0.75, FOV: 89 deg Aspect Ratio: 0.75, FOV: 89 deg

Aspect Ratio: 1.0, FOV: 89 deg Aspect Ratio: 1.0, FOV: 89 deg

Aspect Ratio: 1.33, FOV: 89 Aspect Ratio: 1.33, FOV: 89

I don't see a point of writing the code but this is how my main file looks like:

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() function looks like this:

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

}
    }

As can be seen, there are certain function calls within the rayTrace function which creates and intersects the rays with the object, sphere in my case and accordingly colors the pixel.

But the problem of distorted image still persists.

1

1 Answers

2
votes

You need to scale either x or y by aspect ratio. I.e. for constant vertical FoV:

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

...or for constant horizontal FoV:

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

I assume camera has aspect ratio stored in it. Otherwise you'll have to pass it too.