예제 #1
0
        internal Color ShadeHit(IntersectionState state, int maxRecursion = MaxRecursion)
        {
            Color surfaceColor = Colors.Black;

            foreach (Light light in Lights)
            {
                bool isShadowed = IsShadowed(state.OverPoint, light);

                Color surfaceColorFromLight = state.Shape.Material.CalculateLighting(
                    state.Shape,
                    light,
                    state.OverPoint,
                    state.Eye,
                    state.Normal,
                    isShadowed);

                surfaceColor += surfaceColorFromLight;
            }

            Color reflectedColor = ReflectedColor(state, maxRecursion);
            Color refractedColor = RefractedColor(state, maxRecursion);

            Material material = state.Shape.Material;

            if (material.Reflective > 0 && material.Transparency > 0)
            {
                double reflectance = state.Schlick();
                return(surfaceColor + (reflectedColor * reflectance) + (refractedColor * (1 - reflectance)));
            }

            return(surfaceColor + reflectedColor + refractedColor);
        }
예제 #2
0
        public Color ReflectedColor(IntersectionState state, int maxRecursion = MaxRecursion)
        {
            if (maxRecursion <= 0 || state.Shape.Material.Reflective == 0)
            {
                return(Colors.Black);
            }

            var   reflectedRay   = new Ray(state.OverPoint, state.Reflection);
            Color color          = ColorAt(reflectedRay, maxRecursion - 1);
            Color reflectedColor = color * state.Shape.Material.Reflective;

            return(reflectedColor);
        }
예제 #3
0
        /// <summary>
        /// Finds the color of the first shape that is hit for the given ray.
        /// </summary>
        /// <param name="ray">The ray to use for hit testing.</param>
        /// <param name="maxRecursion">The maximum number of additional rays to use for reflection.</param>
        /// <returns>
        /// The color for the part of the shape that the ray hits, or <see cref="Colors.Black"/> if no shape is hit.
        /// </returns>
        public Color ColorAt(Ray ray, int maxRecursion = MaxRecursion)
        {
            IntersectionList intersections = Intersect(ray);
            Intersection?    hit           = intersections.Hit;

            if (hit == null)
            {
                return(Colors.Black);
            }

            var   state = IntersectionState.Create(hit, ray, intersections);
            Color color = ShadeHit(state, maxRecursion);

            return(color);
        }
예제 #4
0
        public Color RefractedColor(IntersectionState state, int maxRecursion = MaxRecursion)
        {
            if (maxRecursion <= 0 || state.Shape.Material.Transparency == 0)
            {
                return(Colors.Black);
            }

            // Find the ratio of the first index of refraction to the second. This is inverted from the definition of
            // Snell's Law, which is sin(theta_i) / sin(theta_t) = n2 / n1.
            double nRatio = state.N1 / state.N2;

            // cos(theta_i) is the same as the dot product of the two vectors.
            double cosI = state.Eye.Dot(state.Normal);

            // Find sin(theta_t)^2 via trigonometric identity.
            double sin2T = nRatio * nRatio * (1 - (cosI * cosI));

            // Total internal reflection - there is no refraction.
            if (sin2T > 1)
            {
                return(Colors.Black);
            }

            // Find cos(theta_t) via trigonometric identity.
            double cosT = Math.Sqrt(1.0 - sin2T);

            // Compute the direction of the refracted ray.
            Vector direction = (state.Normal * ((nRatio * cosI) - cosT)) - (state.Eye * nRatio);

            // Create the refracted ray.
            var refractedRay = new Ray(state.UnderPoint, direction);

            // Find the color of the refracted ray, making sure to multiply by the transparency value to account for any opacity.
            Color color = ColorAt(refractedRay, maxRecursion - 1) * state.Shape.Material.Transparency;

            return(color);
        }