什么是这个光线追踪公式的焦距和像面距离
我有一个由右,上,前向和位置矢量组成的4x4相机矩阵。 RAYTRACE我用下面的代码,我在一个教程中的情景,但真的不完全理解它:什么是这个光线追踪公式的焦距和像面距离
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));
我有几个问题:
- 我如何才能找到焦点我的光线追踪摄像机的长度?
- 我的图像平面在哪里?
- 为什么
cameraForward
需要乘以这个1/tanf(m_verticalFovAngleRadian)
?
焦距是透镜系统的一个特性。然而,该代码使用的相机型号是针孔相机,根本不使用镜头。所以,严格来说,相机并没有真正的焦距。相应的光学性质被表示为视场(相机可以观察的角度;通常是垂直的角度)。你可以计算出具有视用下面的公式等价场相机的焦距(见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;
这些公式计算U/V -0.5到0.5之间的协调对每个像素,假设整个图像中的箱子适合在-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处的半图像平面的大小。只需绘制一个三角形来验证。请注意,此代码只能生成方形图像平面。如果你想允许长方形,你需要考虑边长的比例。