我要写一个光线跟踪器,但是我似乎已经遇到了我的第一个大问题。无论出于何种原因,我的球体(因为我只是开始 - 我只是在射线击中时变成白色)呈现为椭圆形。
此外,似乎失真越来越严重,我将球体的中心移离x = 0 and y = 0
这是交集和主循环代码:
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.);
}
}
}
我也不明白为什么我的“椭圆形”不在图片的中心。我有一个600 x 600像素的窗口,所以将球体的中心放在300 x 300处也应该将球体放在窗口的中心。
我的具体解决方案
(感谢Thomas推动我走向正确的方向!)
正如托马斯正确地说的那样,我的问题在于两个截然不同的问题。考虑到将球体投射到中心,我按照他的建议做了,并改变了光线的原点和投影。为了获得正确的观点,我没有意识到我已经必须从维度计算focal length。
focal_length = sqrt(width^2 + height^2) / ( 2*tan( 45/2 ) )
结果:
答案 0 :(得分:4)
这对于线性透视投影来说是正常的,并且由于宽的摄像机角度而加剧;见http://en.wikipedia.org/wiki/Perspective_projection_distortion。大多数游戏在水平方向上使用90度,在任一侧使用45度。但是,通过在x方向上投射600个像素但在z方向上投射300个像素,你的光线要宽得多,精确到126度。
你的球体没有出现居中的原因是你正在从屏幕的左下角投射光线:
mu = Ray(math3d::point(0.,0.,0.),math3d::vector(float(x),float(y),-300.));
那应该是这样的:
mu = Ray(math3d::point(width/2,height/2,0.),math3d::vector(float(x-width/2),float(y-height/2),-300.));