Пример #1
0
        private void HandleRefraction(Computations comps, IntersectionCollection xs)
        {
            var containers = new List<Shape>();
            
            foreach (var intersection in xs.Intersections)
            {
                if (intersection.T == T)
                    comps.n1 = containers.Any()
                        ? containers.Last().Material.RefractiveIndex
                        : 1.0;

                if (containers.Contains(intersection.Object))
                    containers.Remove(intersection.Object);
                else
                    containers.Add(intersection.Object);

                if (intersection.T == T)
                {
                    comps.n2 = containers.Any()
                        ? containers.Last().Material.RefractiveIndex
                        : 1.0;
                    break;
                }
            }
        }
Пример #2
0
        internal Color RefractedColor(Computations comps, int remaining)
        {
            if (remaining == 0)
            {
                return(Color.Black);
            }

            if (comps.Object.Material.Transparency == 0)
            {
                return(Color.Black);
            }

            // Snell's law
            var nRatio             = comps.n1 / comps.n2;
            var cosTheta_i         = comps.EyeVector.Dot(comps.NormalVector);
            var sinTheta_t_squared = Math.Pow(nRatio, 2) * (1 - Math.Pow(cosTheta_i, 2));

            if (sinTheta_t_squared > 1)
            {
                return(Color.Black);
            }

            var cosTheta_t            = Math.Sqrt(1 - sinTheta_t_squared);
            var refractedRayDirection =
                comps.NormalVector * (nRatio * cosTheta_i - cosTheta_t) -
                comps.EyeVector * nRatio;
            var refractedRay = new Ray(comps.UnderPoint, refractedRayDirection);
            // Find the color of the refracted ray, making sure to multiply
            // by the transparency value to account for any opacity
            var color = ColorAt(refractedRay, --remaining) * comps.Object.Material.Transparency;

            return(color);
        }
Пример #3
0
        internal Color ReflectedColor(Computations comps, int remaining = 1)
        {
            if (remaining < 1)
            {
                return(Color.Black);
            }

            if (comps.Object.Material.Reflective == 0.0)
            {
                return(Color.Black);
            }

            var reflectRay = new Ray(comps.OverPoint, comps.ReflectV);
            var color      = ColorAt(reflectRay, --remaining);

            return(color * comps.Object.Material.Reflective);
        }
Пример #4
0
        internal Color ShadeHit(Computations comps, int remaining = 1)
        {
            var isShadowed = IsShadowed(comps.OverPoint);
            var surface    = comps.Object.Material.Lighting(comps.Object, LightSource, comps.OverPoint, comps.EyeVector, comps.NormalVector, isShadowed);
            var reflected  = ReflectedColor(comps, remaining);
            var refracted  = RefractedColor(comps, remaining);

            var material = comps.Object.Material;

            if (material.Reflective > 0 && material.Transparency > 0)
            {
                var reflectance = comps.Schlick();
                return(surface +
                       reflected * reflectance +
                       refracted * (1 - reflectance));
            }

            return(surface + reflected + refracted);
        }
Пример #5
0
        public Computations PrepareComputations(Ray ray, IntersectionCollection xs = null)
        {
            var c = new Computations();
            c.T = T;
            c.Object = Object;
            c.Point = ray.Position(T);
            c.EyeVector = -ray.Direction;            
            c.NormalVector = Object.NormalAt(c.Point, this);

            if (c.NormalVector.Dot(c.EyeVector) < 0)
            {
                c.Inside = true;
                c.NormalVector = -c.NormalVector;
            }

            c.OverPoint = c.Point + c.NormalVector * C.Epsilon;
            c.UnderPoint = c.Point - c.NormalVector * C.Epsilon;
            c.ReflectV = ray.Direction.Reflect(c.NormalVector);

            xs = xs ?? new IntersectionCollection();
            HandleRefraction(c, xs);

            return c;
        }