距此光线追踪公式的焦距和像平面距离是多少

时间:2017-10-19 12:09:49

标签: graphics camera computer-vision geometry perspectivecamera

我有一个4x4相机矩阵,由向右,向上,向前和位置向量组成。 我使用我在教程中找到的以下代码对场景进行光线追踪,但并不完全理解它:

for (int i = 0; i < m_imageSize.width; ++i)
{
    for (int j = 0; j < m_imageSize.height; ++j)
    {
        u = (i + .5f) / (float)(m_imageSize.width - 1) - .5f;
        v = (m_imageSize.height - 1 - j + .5f) / (float)(m_imageSize.height - 1) - .5f;

        Ray ray(cameraPosition, normalize(u*cameraRight + v*cameraUp + 1 / tanf(m_verticalFovAngleRadian) *cameraForward));

我有几个问题:

  1. 如何找到我的光线摄像机的焦距?
  2. 我的图像平面在哪里?
  3. 为什么cameraForward需要与此1/tanf(m_verticalFovAngleRadian)相乘?

1 个答案:

答案 0 :(得分:1)

焦距是镜头系统的特性。然而,该代码使用的相机型号是针孔相机,根本不使用镜头。所以,严格来说,相机并没有真正的焦距。相应的光学特性反而表示为视场(摄像机可以观察的角度;通常是垂直角度)。您可以使用以下公式计算具有等效视野的相机的焦距(请参阅Wikipedia):

FOV = 2 * arctan (x / 2f)
FOV  diagonal field of view 
x    diagonal of film; by convention 24x36 mm -> x=43.266 mm
f    focal length

没有独特的图像平面。垂直于视图方向的任何平面都可以看作图像平面。事实上,投影图像的尺寸不同。

关于你的上一个问题,让我们仔细看看代码:

u = (i + .5f) / (float)(m_imageSize.width - 1) - .5f;
v = (m_imageSize.height - 1 - j + .5f) / (float)(m_imageSize.height - 1) - .5f;

这些公式计算每个像素的-0.5和0.5之间的u / v坐标,假设整个图像适合-0.5和0.5之间的框。

u*cameraRight + v*cameraUp 

...只是将光线的x / y坐标放在像素上。

... + 1 / tanf(m_verticalFovAngleRadian) *cameraForward

...定义光线的深度分量,最终定义您正在使用的图像平面的深度。基本上,这使得光线更陡峭或更浅。假设您有一个非常小的视野,那么1/tan(fov)是一个非常大的数字。因此,图像平面距离很远,这恰好产生了这个小视场(当你已经设置了x / y分量时,保持图像平面的大小不变)。另一方面,如果视场很大,则图像平面移近。请注意,这种图像平面的概念只是概念性的。正如我所说,所有其他图像平面同样有效,并会产生相同的图像。指定光线的另一种方式(也许是更直观的方式)将是

u * tanf(m_verticalFovAngleRadian) * cameraRight 
+ v * tanf(m_verticalFovAngleRadian) * cameraUp 
+ 1 * cameraForward));

如您所见,这是完全相同的光线(仅缩放)。这里的想法是将概念图像平面设置为深度1并缩放x / y分量以适应图像平面的大小。 tan(fov)fov是半视野)正好是深度为1的半图像平面的大小。只需绘制一个三角形来验证。请注意,此代码只能生成方形图像平面。如果要允许矩形,则需要考虑边长的比率。