private double TestRay(Ray ray, Scene scene)
        {
            ISect isect = MinIntersection(ray, scene);

            if (ISect.IsNull(isect))
            {
                return(0);
            }
            return(isect.Dist);
        }
        private Color TraceRay(Ray ray, Scene scene, int depth)
        {
            ISect isect = MinIntersection(ray, scene);

            if (ISect.IsNull(isect))
            {
                return(Color.Background);
            }
            return(Shade(isect, scene, depth));
        }
        private Color Shade(ISect isect, Scene scene, int depth)
        {
            Vector d          = isect.Ray.Dir;
            Vector pos        = Vector.Plus(Vector.Times(isect.Dist, isect.Ray.Dir), isect.Ray.Start);
            Vector normal     = isect.Thing.Normal(pos);
            Vector reflectDir = Vector.Minus(d, Vector.Times(2 * Vector.Dot(normal, d), normal));
            Color  ret        = Color.DefaultColor;

            ret = Color.Plus(ret, GetNaturalColor(isect.Thing, pos, normal, reflectDir, scene));
            if (depth >= MaxDepth)
            {
                return(Color.Plus(ret, new Color(.5, .5, .5)));
            }
            return(Color.Plus(ret, GetReflectionColor(isect.Thing, Vector.Plus(pos, Vector.Times(.001, reflectDir)), normal, reflectDir, scene, depth)));
        }
        private ISect MinIntersection(Ray ray, Scene scene)
        {
            ISect min = ISect.Null;

            foreach (SceneObject obj in scene.Things)
            {
                ISect isect = obj.Intersect(ray);
                if (!ISect.IsNull(isect))
                {
                    if (ISect.IsNull(min) || min.Dist > isect.Dist)
                    {
                        min = isect;
                    }
                }
            }
            return(min);
        }