2015-11-03 80 views
0

我正在研究一些非常简单的射线追踪器。相机(简单射线脚轮)的长宽比计算错误

现在我正在试图使透视相机正常工作。

我使用这样的循环来渲染场景(只有两个,硬编码的球体 - I投射光线从它的中心的每个像素,不AA施加):

Camera * camera = new PerspectiveCamera({ 0.0f, 0.0f, 0.0f }/*pos*/, 
{ 0.0f, 0.0f, 1.0f }/*direction*/, { 0.0f, 1.0f, 0.0f }/*up*/, 
buffer->getSize() /*projectionPlaneSize*/); 
Sphere * sphere1 = new Sphere({ 300.0f, 50.0f, 1000.0f }, 100.0f); //center, radius 
Sphere * sphere2 = new Sphere({ 100.0f, 50.0f, 1000.0f }, 50.0f); 

for(int i = 0; i < buffer->getSize().getX(); i++) { 
    for(int j = 0; j < buffer->getSize().getY(); j++) { 
//for each pixel of buffer (image) 
     double centerX = i + 0.5; 
     double centerY = j + 0.5; 

     Geometries::Ray ray = camera->generateRay(centerX, centerY); 
     Collision * collision = ray.testCollision(sphere1, sphere2); 
     if(collision){ 
      //output red 
     }else{ 
      //output blue 
     } 
    } 
} 

Camera::generateRay(float x, float y)是:

Camera::generateRay(float x, float y) { 
    //position = camera position, direction = camera direction etc. 
    Point2D xy = fromImageToPlaneSpace({ x, y }); 
    Vector3D imagePoint = right * xy.getX() + up * xy.getY() + position + direction; 
    Vector3D rayDirection = imagePoint - position; 
    rayDirection.normalizeIt(); 
    return Geometries::Ray(position, rayDirection); 
} 

Point2D fromImageToPlaneSpace(Point2D uv) { 
    float width = projectionPlaneSize.getX(); 
    float height = projectionPlaneSize.getY(); 
    float x = ((2 * uv.getX() - width)/width) * tan(fovX); 
    float y = ((2 * uv.getY() - height)/height) * tan(fovY); 
    return Point2D(x, y); 
} 

的视场:

double fovX = 3.14159265359/4.0; 
double fovY = projectionPlaneSize.getY()/projectionPlaneSize.getX() * fovX; 

我得到好成绩宽度:高度方面(例如400×400): enter image description here

但是我得到错误,例如: 800x400: enter image description here

甚至略差是更大的宽高比(如1200x400): enter image description here

我做什么不对或步没我省略

它可能是一个精度问题,而不是fromImageToPlaneSpace(...)

回答

0

警告:我在一家视频公司工作了5年,但我有点生疏。

注意:写完之后,我意识到像素纵横比可能不是你的问题,因为屏幕纵横比也出现错误,所以你可以略过一点。

但是,在视频中我们担心有两个不同的视频源:standard definition4:3一个屏幕长宽比和高清晰度与16:9一个屏幕宽高比。

但是,还有另一个变量/参数:像素长宽比。在标准清晰度中,像素是正方形,而hidef像素是矩形(反之亦然 - 我不记得了)。

假设您的当前计算对于屏幕比例是正确的,则您可能必须考虑像素宽高比不同,无论是来自相机源还是您正在使用的显示器。

两个屏幕宽高比和像素纵横比可被存储在的.mp4,.JPEG等

我下载了1200x400 JPEG。我用它的ImageMagick改变像素纵横比:

convert orig.jpg -resize 125x100%\! new.jpg 

这是说改变像素纵横比(125%增加的宽度和离开的高度相同)。\!意味着像素 vs 屏幕比率。 125是因为我记得矩形像素为8x10。无论如何,你需要增加水平宽度10/8这是1.25或125%

不用说,这给了我圆圈,而不是椭圆。

其实,我可以通过调整屏幕高宽比来获得相同的效果。

因此,在您的计算中,您引入了该因素的失真。你在哪里应用缩放?函数调用如何不同?

你在哪里设置屏幕尺寸/比例?我不认为这是显示的(例如,我没有看到任何地方像1200或400任何地方)。

如果我不得不冒险猜测,则必须考虑fromImageToPlaneSpace中的宽高比。宽度/高度需要预分频,或者x =和/或y =行需要缩放因子。 AFAICT,你目前只能用于方形几何。为了测试,使用1200x400的情况下,乘以x 125%[一个kludge],我敢打赌你会得到一些东西。

0

从图像看,您似乎错误地定义了从像素坐标到世界坐标的映射,并在Y轴上引入了一些拉伸。

略读代码,它看起来像是从帧缓冲区的维度定义摄像机的视角。因此,如果您具有非1:1宽高比的帧缓冲区,则您的摄像机的视角不是1:1。您需要将相机的视角视锥模型与最终帧缓冲区的图像空间维分开。

换句话说,帧缓冲区是我们正在查看的相机投影的平面部分。相机定义了世界的3D空间如何投射到相机平面上。

关于3D图形的任何基本书籍都将讨论查看和投影。