2011-05-10 49 views
10

我正在寫一個光線跟蹤器(主要是爲了好玩),雖然我已經寫了一個過去,並花了大量的時間搜索,沒有教程似乎闡明瞭如何在透視投影中計算眼睛光線,而不使用矩陣。Raytracer - 計算的眼睛光線

我相信我最後一次做的是通過使用類Quaternion(可能)低效旋轉相機方向矢量的眼矢量x/y度。這是用C++編寫的,我正在用C#做這個,儘管這並不重要。

僞代碼(假設V * Q =變換操作)

yDiv = fovy/height 
xDiv = fovx/width 

for x = 0 to width 
    for y = 0 to height 

     xAng = (x/2 - width) * xDiv 
     yAng = (y/2 - height) * yDiv 
     Q1 = up vector, xAng 
     Q2 = camera right vector, yAng 
     Q3 = mult(Q1, Q2) 

     pixelRay = transform(Q3, camera direction) 
     raytrace pixelRay 

    next 
next 

我認爲與此實際的問題是,它模擬球形屏幕表面,而不是平坦的屏幕表面。

請注意,雖然我知道如何以及爲什麼要使用交叉產品,點積,矩陣等,但我真正的3D數學問題解決技能並不是很棒。

所以給出:

  • 攝像機位置,方向和上矢量
  • 視場
  • 屏幕像素和/或子採樣劃分

什麼是實際的方法爲光線跟蹤器的x/y像素座標產生一個眼睛光線?

爲了澄清:我正是我想要計算的,我只是不太想拿出3D數學來計算它,並且我發現沒有光線跟蹤代碼似乎有我需要的代碼計算單個像素的眼睛光線。

enter image description here

回答

13

enter image description here

INPUT: camera_position_vec, direction_vec, up_vec, screen_distance 

right_vec = direction_vec x up_vec 
for y from 0 to 1600: 
    for x from 0 to 2560: 
     # location of point in 3d space on screen rectangle 
     P_3d = camera_position_vec + screen_distance*direction_vec 
       + (y-800)*-up_vec 
       + (x-1280)*right_vec 

     ray = Ray(camera_position_vec, P_3d) 
     yield "the eye-ray for `P_2d` is `ray`" 

x指叉積

編輯: 答案假設direction_vec是標準化的,因爲它應該是。 right_vec在圖片中(看起來應該在左邊),但right_vec不是必需的,如果包含,應始終與-(up_vec x direction_vec)處於相同的方向。此外,圖片暗示x座標隨着一個向右而增加,y座標隨着向下而增加。這些標誌已經稍微改變以反映這一點。縮放可以通過將公式中的x和y項相乘或更有效地乘以矢量並使用scaled_up_vecscaled_right_vec來執行。然而,變焦是等同的(因爲光圈無關緊要,這是一個完美的針孔攝像頭),以改變視場(FoV),這是一個比任意「變焦」更好的處理量。有關如何實現FoV的信息,請參閱下面的註釋。

+0

謝謝。對不起,我應該在這個問題上讓自己更清楚。我的腦海裏實際上已經有了這種實現。如果用一個視場角來計算屏幕距離,那麼如果x是-0.5到0.5,縱橫比不能承受? – 2011-05-10 02:08:28

+2

考慮當你改變'screen_distance'(焦距)時會發生什麼。隨着您移近它,圖像變得更加寬廣。因此,我們假設我們希望以度爲單位的視角「FoV」。如果考慮右邊中間的最大y值,它將形成一個三角形,意味着tan(FoV/2)= 800/screen_distance'。因此,如果我們設置'FoV'而不是'screen_distance',我們將'screen_distance'設置爲'800/tan(FoV/2)'。當然,人們不會使用像2560和1600這樣的固定值,但是你去了。 – ninjagecko 2011-05-10 02:14:48