示例#1
0
        /// <summary>
        /// Traces a ray and calculates the color using the methods implemented in raytracer implementations.
        /// </summary>
        /// <param name="ray">The ray that will be traced through the scene.</param>
        /// <param name="recursionDepth">The current recursion depth. Optional, but should never be given at the first call.</param>
        /// <returns>Returns the color that results when tracing the ray.</returns>
        protected Color Trace(Ray ray, int recursionDepth = 0)
        {
            if (recursionDepth > Settings.RecursionDepth)
            {
                return(Color.Black);
            }

            // Intersect ray with scene objects and save to closestHit
            if (!CurrentScene.Intersect(ray, out HitData closestHit))
            {
                return(calculateNoHitColor(ray));
            }

            Color color = Color.Black;

            color += calculateDefaultColor(ray, closestHit);

            // Check for each light if it is blocked by scene objects and calculate color contribution
            CurrentScene.LightList.ForEach((ILight light) =>
            {
                //Offset start position the prevent casting of a shadow on itself.
                Vector3 shadowRayDirection = light.Position - closestHit.Position;
                shadowRayDirection.Normalize();
                Vector3 offsettedStartPosition = closestHit.Position + Settings.SecondaryRayOffset * shadowRayDirection;

                bool isOccluded = CurrentScene.Intersect(offsettedStartPosition, light.Position, out HitData shadowRayHit, true);
                color          += calculateColorPerLight(ray, closestHit, light, isOccluded);
            });

            // Handle reflective materials
            if (closestHit.Material.Reflective(closestHit.TextureCoords) > 0.001f)
            {
                Vector3 reflectionDirection = ray.Direction.Reflect(closestHit.Normal);
                Ray     reflectionRay       = new Ray(closestHit.Position + Settings.SecondaryRayOffset * reflectionDirection, reflectionDirection);
                color += closestHit.Material.Reflective(closestHit.TextureCoords) * Trace(reflectionRay, recursionDepth + 1);
            }

            return(color);
        }