Shadows happen when there’s a light whose rays cannot reach an object because there’s another object in the way.
So basically we want to check for a point P whether or not there’s an object between P and the light. If so, don’t add the illumination from that light here.
Since we know P and L, we can have a ray P + tL from the point P to the light source. We can check if that ray intersects other objects. For point lights, we want to set t_max to 1 so that the ray stops at the light.
Mirrors perfectly reflect light rays across their surface normal. If we trace a ray and hit a mirror, then we color it with the color of the reflected ray, by tracing another ray through the reflection. Use a recursion limit where r=0 means no reflections and r=2 means we see reflections of the reflections of objects. r=3 is usually as deep as is worth going. Also introduce a ‘reflectiveness’ property on objects. A high reflectiveness means most of the color is from the reflection, a low reflectiveness means most of the color is from the object.
For a ray D towards P, the direction of the reflected ray is -D with respect to the surface normal N.