Given the up and focal vector of the perspective camera, the position of the camera and the vertical and horizontal opening angle of the FOV. How can I calculate a ray for given screen space coordinates (x, y) where x, y are between -1 and 1 (inclusive). I tried this:

1) Calculate the vectors sx, sy that span the image plane

sy = -norm(up)

sx = norm(cross(focal, sy))

2) Calculate the focal length f

f = 1 * sin(90 - vertical) / sin(vertical)

3) Create the ray

dir = (center + x * sx + y * sy + f * forward) - center

r(t) = center + t * norm(dir)

But the resulting image does not turn out like the reference image. Someone know what I am doing wrong?

  • $\begingroup$ sin most likely accepts radians. Also you can cancel out the +center-center: dir = x * sx + y * sy + f * forward. I am unsure why you calculate the focal length like this either. $\endgroup$
    – lightxbulb
    Oct 27, 2019 at 21:58
  • $\begingroup$ Oh yes in my code i have pi/2 not 90, but what do you mean with the focal length? $\endgroup$
    – Yamahari
    Oct 27, 2019 at 22:16

1 Answer 1


Let the horizontal FOV be given as theta (in radians), and the vertical FOV be given as phi (in radians). The we know that:

$$\tan\frac{\theta}{2}=\frac{w}{f}, \tan\frac{\phi}{2}=\frac{h}{f}$$

Let us pick $f = 1$, then $w = \tan\frac{\theta}{2}, h = \tan\frac{\phi}{2}$. Now your ray generation direction generation formula looks like:

$$\pmb{d} = x w\pmb{u} + yh\pmb{v} + \pmb{w}$$

Where $\pmb{u},\pmb{v}, \pmb{w}$ are your sx,sy, forward vectors. Essentially, I found the extent of the smallest/largest x and y respectively ($1w = w, -1w=-w$, etc.). You can premultiply $\pmb{u}, \pmb{v}$ with $w, h$ respectively, if you don't want to perform the multiplication per ray.

  • $\begingroup$ hm I am still having trouble recreating the last reference image provided for this task. this is how I am doing my ray now, but that doesnt seem to work for the last image ( probably missing something ): sx=norm(cross(forward, up)) * tan(horizontal/2), sy=norm(cross(forward, sx)) * tan(vertical/2) ( up may not be orthogonal to forward ), r(t)=origin + t * norm(x*sx + y*sy + forward). Am I missing something? $\endgroup$
    – Yamahari
    Oct 30, 2019 at 14:53
  • $\begingroup$ @Yamahari Looks correct. Maybe your fov us given in half angles? Then remove the /2. Also is forward normalized? $\endgroup$
    – lightxbulb
    Oct 30, 2019 at 16:35
  • $\begingroup$ i doubt the angle is only half, for the last image the given vertical/horizontal angles are pi * 0.9. Yes the forward vector is normalized $\endgroup$
    – Yamahari
    Oct 30, 2019 at 17:14
  • $\begingroup$ @Yamahari Then all should be fine, there is probably a different reason you do not get the reference. $\endgroup$
    – lightxbulb
    Oct 30, 2019 at 17:24
  • $\begingroup$ oh man I just found out what happened, I was too stupid to use c++ correctly xD thx $\endgroup$
    – Yamahari
    Oct 30, 2019 at 17:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.