/// Computes the diffuse and specular components of the Phong
        /// reflection model.
        /// @Note Avoids code duplication in ComputePointLight and
        /// ComputeDirectionalLight.
        private Color ComputeDiffuseSpecular(
            Light l, Object3D obj, V3 p, V2 uv, V3 incidentVec
        )
        {
            V3 normalVec = obj.Normal(p, uv);

            V3 reflectedVec = incidentVec.ReflectedVector(normalVec);
            reflectedVec.Normalize();

            V3 viewingVec = CameraPos - p;
            viewingVec.Normalize();

            Color diffuseIllu = ComputeDiffuse(
                l, incidentVec, normalVec, obj, uv
            );
            Color specularIllu = ComputeSpecular(
                l, reflectedVec, normalVec, obj, uv
            );

            return diffuseIllu + specularIllu;
        }
        /// Recursivly raytrace to get the color resulting from the refracted
        /// light component for the specified collisionPoint.
        private Color RefractionColor(
            V3 incidentVec, V3 collisionPoint, V2 collisionUV,
            Object3D collidedObj, int depth
        )
        {
            if (!collidedObj.Material.IsTransparent()) { return Color.Black; }

            V3 normal = collidedObj.Normal(collisionPoint, collisionUV);

            Ray refractionRay = new Ray(
                origin: collisionPoint,
                direction: incidentVec.RefractedVector(
                    normalVec: normal,
                    n1: Scene.RefractiveIndex,
                    n2: collidedObj.Material.RefractiveIndex
                ),
                originObject: null
            );

            Color refractionColor = Raytrace(refractionRay, depth - 1);
            if (refractionColor == null) { return Color.Black; }

            return collidedObj.Material.Transparency * refractionColor;
        }
        /// Recursivly raytrace to get the color resulting from the reflected
        /// light component for the specified collisionPoint.
        private Color ReflectionColor(
            V3 incidentVec, V3 collisionPoint, V2 collisionUV,
            Object3D collidedObj, int depth
        )
        {
            if (!collidedObj.Material.IsReflective()) { return Color.Black; }

            V3 normal = collidedObj.Normal(collisionPoint, collisionUV);
            Ray reflectionRay = new Ray(
                origin:       collisionPoint,
                direction:    incidentVec.ReflectedVector(normal),
                originObject: collidedObj
            );

            Color reflectionColor = Raytrace(reflectionRay, depth - 1);
            if (reflectionColor == null) { return Color.Black; }

            return collidedObj.Material.Reflection * reflectionColor;
        }