2017-10-19 156 views
0

我有一個由右,上,前向和位置矢量組成的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)); 

我有幾個問題:

  1. 我如何才能找到焦點我的光線追蹤攝像機的長度?
  2. 我的圖像平面在哪裏?
  3. 爲什麼cameraForward需要乘以這個1/tanf(m_verticalFovAngleRadian)

回答

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; 

這些公式計算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處的半圖像平面的大小。只需繪製一個三角形來驗證。請注意,此代碼只能生成方形圖像平面。如果你想允許長方形,你需要考慮邊長的比例。