In a traditional camera, the photons from the scene travel through the lens of the camera, then hit the sensor at the focal length. A consequence of the lens is that the image is upside down and backwards.
In ray tracing, we can optimize this by imagining the focal plane is in front of the camera. You can think that the photons from the scene travel towards the camera hole, and resolve on the image plane.
Another optimization in ray tracing to to trace rays from the camera into the scene, rather than tracing them from light sources and hoping they hit the camera. Therefore, the first rays we shoot out are the ones that go from the eye through each pixel on the virtual screen.
In order to create the ray, we need to know the distances a and b in world units. Therefore, we need to convert pixel units into world units. To do this we need a define a camera. Let's define an example camera as follows:
$$origin = \begin{bmatrix} 0 & 0 & 0 \end{bmatrix}$$
$$coordinateSystem = \begin{bmatrix} 1 & 0 & 0\\ 0 & 1 & 0\\ 0 & 0 & 1 \end{bmatrix}$$
$$fov_{x} = 90^{\circ}$$
$$fov_{y} = \frac{fov_{x}}{aspectRatio}$$
$$focalDist = 1$$
The field of view, or fov is an indirect way of specifying the ratio of pixel units to view units. Specifically, it is the viewing angle that is seen by the camera.
The higher the angle, the more of the scene is seen. But remember, changing the fov does not change the size of the screen, it merely squishes more or less of the scene into the same number of pixels.
Let's look at the triangle formed by fovx and the x-axis:
We can use the definition of tangent to calculate the screenWidth in view units
$$\tan \left (\theta \right) = \frac{opposite}{adjacent}$$
$$screenWidth_{view}= 2 \: \cdot \: focalDist \: \cdot \: \tan \left (\frac{fov_{x}}{2} \right)$$
Using that, we can calculate the view units of the pixel.
$$x_{homogenous}= 2 \: \cdot \: \frac{x}{width} \: - \: 1$$
$$x_{view} = focalDist \: \cdot \: x_{homogenous} \: \cdot \: \tan \left (\frac{fov_{x}}{2} \right)$$
The last thing to do to get the ray is to transform from view space to world space. This boils down to a simple matrix transform. We negate yview because pixel coordinates go from the top left of the screen to the bottom right, but homogeneous coordinates go from (-1, -1) at the bottom left to (1, 1) at the top right.
$$ray_{world}= \begin{bmatrix} x_{view} & -y_{view} & d\end{bmatrix}\begin{bmatrix} & & \\ & cameraCoordinateSystem & \\ & & \end{bmatrix}$$
You can see an implementation of this here (In the code, I assume the focalDist is 1, so it cancels out)