Assume a fixed viewing position, the camera position O = (0,0,0) in the scene. The camera looks forward Z+ with Y+ up and X+ to the right.
Assume a frame with dimensions V_w and V_h perpendicular to Z+ at a distance d from the camera’s forward, centered with respect to Z and with sides parallel to X and Y. Basically it’s a rectangle right in front of the camera, we call it a viewport.
We’re going to draw onto the canvas whatever we see through the viewport. For simplicity, we set V_w = V_h = d = 1. This gives us a Field of View of about 53deg.
The raytracing algorithm looks like this:
To figure out which square on the viewport (V_x, V_y) corresponds to pixel C_x, c_y:
We put the viewport along the same orientation as the canvas, with the center matching the canvas. So we just need to change scale to convert from canvas coordinates to scene coordinates.
V_x = C_x * (V_w / C_w) V_y = C_y * (V_h / C_h)
(We do it because the viewport might be bigger or smaller than the canvas)
The viewport is 2D but inside a 3D space. We put it at a distance d from the camera so
V_z = d
To color a pixel, we can shoot a ray out from the camera O_x, O_y, O_z into the viewport V_x, V_y, V_z and keep going until we hit an object, then use the color of that object for the pixel. So the ray becomes
P = O + t(V - O) where t is any real number.
The direction of the ray D = V - O so
$P=O+t\vec{D}$
So to build a simple scene we can use spheres.
For a sphere of center C and radius r, the points on the surface are P and so
distance(P, C) = r
$|P-C|=r$
$\sqrt{(P-C)\cdot(P-C)} = r$
$(P-C)\cdot(P-C) = r^2$
Solving for a ray-sphere intersection gives us a quadratic equation where
$\vec{CO} = O-C$
$a=\vec{D}\cdot\vec{D}$
$b=2((\vec{CO})\cdot{d})$
$c=\vec{CO}\cdot\vec{CO}-r^2$
so that ${t_1,t_2} = \frac{-b \pm\sqrt{b^2 - 4ac}}{2a}$
No solution = no intersection (neg discrim), 1 solution = tangential (0 discrim), 2 solutions = in front out back (pos discrim).
Once we know t, we can plug it back into the ray equation to get the intersection point(s).
So now, for every pixel on the canvas just compute the intersection between the ray and every sphere in the scene, and keep the intersection closest to the camera, then paint the pixel on the canvas with the color of that sphere.