I am to write a raytracer, however I already seem to hit my first big problem. For whatever reason, my sphere (which - since I only begin - I simply color white when a ray hits) is rendered as an oval.

Furthermore, it seems that the distortion is getting worse, the farther I am moving the sphere's center away from x = 0 and y = 0

Here's the intersection and main-loop code:

double const Sphere::getIntersection(Ray const& ray) const
{
  double t;
  double A = 1;
  double B = 2*( ray.dir[0]*(ray.origin[0] - center_[0]) + ray.dir[1] * (ray.origin[1] - center_[1]) + ray.dir[2] * (ray.origin[2] - center_[2]));
  double C = pow(ray.origin[0]-center_[0], 2) + pow(ray.origin[1]-center_[1], 2) + pow(ray.origin[2] - center_[2], 2) - radius_pow2_;
  double discr = B*B - 4*C;

  if(discr > 0)
  {
    t = (-B - sqrt(discr))/2;
    if(t <= 0)
    {
      t = (-B + sqrt(discr))/2;
    }
  }
  else t = 0;

  return t;
}

Sphere blub = Sphere(math3d::point(300., 300., -500.), 200.);
Ray mu = Ray();
// for all pixels of window
for (std::size_t y = 0; y < window.height(); ++y) {
  for (std::size_t x = 0; x < window.width(); ++x) {
    Pixel p(x, y);
    mu = Ray(math3d::point(0., 0., 0.), math3d::vector(float(x), float(y), -300.));

    if (blub.getIntersection(mu) == 0. ) {
      p.color = Color(0.0, 0.0, 0.0);
    } else {
      p.color = Color(1., 1., 1.);
    }
  }
}

Sphere with center at 300,300,-500 Sphere with center at 0,0,-500

What I also do not understand is why my "oval" isn't centered on the picture. I have a window of 600 x 600 pixels, so putting the sphere's center at 300 x 300 should afaik put the sphere in the center of the window as well.


my specific solution

(Thanks to Thomas for pushing me to the right direction!)

As Thomas rightly said, my questions where two distinct problems. Considering projecting the sphere in the center, I did as he suggested and changed the origin and projections of the rays.

To get the perspective right, I did not realize I already had to calculate the focal length from the dimensions.

focal_length = sqrt(width^2 + height^2) / ( 2*tan( 45/2 ) )

The result:

Sphere with center at 200,300,-focal_length

有帮助吗?

解决方案

This is normal for linear perspective projections, and exacerbated by wide camera angles; see http://en.wikipedia.org/wiki/Perspective_projection_distortion. Most games use something like 90 degrees in the horizontal direction, 45 on either side. But by casting rays up across 600 pixels in the x direction but 300 in the z direction, yours is significantly wider, 126 degrees to be precise.


The reason why your sphere doesn't appear centered is that you're casting rays from the bottom left corner of the screen:

mu = Ray(math3d::point(0.,0.,0.),math3d::vector(float(x),float(y),-300.));

That should be something like:

mu = Ray(math3d::point(width/2,height/2,0.),math3d::vector(float(x-width/2),float(y-height/2),-300.));
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top