If you are doing some ray tracing assignments, I have some lazy tricks for making your pictures look better with very little code. Note these may be slow, but that's what overnight runs are for.
Hollow glass primitive. This is to get thin glass balls like Turner Whitted's famous image.
Make a sphere with radius R centered at C. Make another at C with radius -0.9R (or -0.95 or whatever). The sphere intersection code depends only on R^2 so the negative radius wont matter. The surface normal is:
N = hitPoint - C /radius
The negative radius will make an inward facing normal so the refraction code works out.
Soft shadows from point sources.
If you have a point source at position P, instead of sending a shadow ray toward P, send one to a random point within radius R of P. To do this just use a rejection method by picking random points in a cube of radius R:
x = drand48();
y = drand48();
z = drand48();
} while (x*x + y*y + z*z > 1) // now (x,y,z) is random in unit sphere
newrandomlightpoint = P + R*vec3(x,y,z)
Fuzzy (glossy) reflections
You have a hitpoint P and a reflected ray direction V. The "end" of the ray is Q = P + V. Now find a random point within a sphere centered at Q (see soft shadows). Now the new reflection ray is V' = Q - P. Make it a unit vector if your code requires it.
Depth of field (defocus blur)
Randomly perturb the eye point within a sphere centered at the eye point. This will work better with some ways people implement cameras than other equally good ways.
Directionally varying ambient
Instead of a constant, use Color1*(max(0,dot(N, V1)) + Color2*(max(0,dot(N, V2))
Making V1 "up" and sky (background) color and V2 "down" and ground color will look pretty good.
Directionally varying background
If you miss everything, and are too lazy for an environment map (I am!), use something that varies. For example (0.2, 0.2, 1.0) + (1.0-fabs(v.z))*(0.6,0.6,0.0). Fool with that.