예제 #1
0
        public Tuple ReflectedColor(Precomputation comp, int remaining)
        {
            if (comp.Object.Material.Reflective == 0 || remaining <= 0)
            {
                return(new Tuple(0, 0, 0, 0));
            }
            Ray   reflectRay = new Ray(comp.OverPoint, comp.ReflectVector);
            Tuple colour     = ColourAt(this, reflectRay, remaining - 1);

            return(colour * comp.Object.Material.Reflective);
        }
예제 #2
0
        public static Tuple ColourAt(World world, Ray ray, int remaining)
        {
            Intersection[] worldIntersections = IntersectWorld(world, ray);
            Intersection   hit = Intersect.Hit(worldIntersections);

            if (hit != null)
            {
                Precomputation comps = Intersect.PrepareComputations(hit, ray);
                return(ShadeHit(world, comps, remaining));
            }
            else
            {
                return(new Tuple(0, 0, 0, 0));
            }
        }
예제 #3
0
        public static Tuple ShadeHit(World world, Precomputation comps, int remaining)
        {
            bool     shadowed       = IsShadowed(world, comps.OverPoint);
            Tuple    Colour         = Material.Lighting(comps.Object.Material, comps.Object, world.SceneLight, comps.OverPoint, comps.EyeVector, comps.NormalVector, shadowed);
            Tuple    reflectedColor = world.ReflectedColor(comps, remaining);
            Tuple    refractedColor = RefractedColor(world, comps, remaining);
            Material m = comps.Object.Material;

            if (m.Reflective > 0f && m.Transparency > 0f)
            {
                float reflectance = Schlick(comps);
                return(Colour + reflectedColor * reflectance + refractedColor * (1 - reflectance));
            }
            else
            {
                return(Colour + reflectedColor + refractedColor);
            }
        }
예제 #4
0
        public static float Schlick(Precomputation comp)
        {
            float cos = comp.EyeVector.Dot(comp.NormalVector);

            if (comp.n1 > comp.n2)
            {
                float ratio  = comp.n1 / comp.n2;
                float sin2_t = ratio * ratio * (1.0f - (cos * cos));
                if (sin2_t > 1.0)
                {
                    return(1.0f);
                }
                float cos_t = MathF.Sqrt(1.0f - sin2_t);
                cos = cos_t;
            }
            float r0 = ((comp.n1 - comp.n2) / (comp.n1 + comp.n2)) * ((comp.n1 - comp.n2) / (comp.n1 + comp.n2));

            return(r0 + (1 - r0) * MathF.Pow((1 - cos), 5));
        }
예제 #5
0
        public static Tuple  RefractedColor(World world, Precomputation comp, int remaining)
        {
            if (comp.Object.Material.Transparency == 0 || remaining == 0)
            {
                return(new Tuple(0, 0, 0));
            }

            float n_ratio = comp.n1 / comp.n2;
            float cos_i   = comp.EyeVector.Dot(comp.NormalVector);
            float sin2_t  = (n_ratio * n_ratio) * (1 - (cos_i * cos_i));

            if (sin2_t > 1)
            {
                return(new Tuple(0, 0, 0));
            }

            float cos_t       = MathF.Sqrt(1.0f - sin2_t);
            Tuple direction   = comp.NormalVector * (n_ratio * cos_i - cos_t) - comp.EyeVector * n_ratio;
            Ray   refract_ray = new Ray(comp.UnderPoint, direction);

            return(ColourAt(world, refract_ray, remaining - 1) * comp.Object.Material.Transparency);
        }
        public static Precomputation PrepareComputations(Intersection i, Ray ray, Intersection[] optionalXS = null)
        {
            if (optionalXS == null)
            {
                optionalXS    = new Intersection[1];
                optionalXS[0] = i;
            }

            List <Shape>   containers = new List <Shape>();
            Precomputation comp       = new Precomputation();

            for (int index = 0; index < optionalXS.Length; index++)
            {
                if (optionalXS[index] == i)
                {
                    if (containers.Count == 0)
                    {
                        comp.n1 = 1.0f;
                    }
                    else
                    {
                        comp.n1 = containers[containers.Count - 1].Material.Refractive_index;
                    }
                }

                if (containers.Contains(optionalXS[index].Object))
                {
                    containers.Remove(optionalXS[index].Object);
                }
                else
                {
                    containers.Add(optionalXS[index].Object);
                }

                if (optionalXS[index] == i)
                {
                    if (containers.Count == 0)
                    {
                        comp.n2 = 1.0f;
                    }
                    else
                    {
                        comp.n2 = containers[containers.Count - 1].Material.Refractive_index;
                    }

                    break;
                }
            }



            //Precomputation comp = new Precomputation();
            comp.T_Value       = i.T_Value;
            comp.T_Value_Tuple = i.T_Value_Tuple;
            comp.Object        = i.Object;
            comp.Point         = ray.Position(comp.T_Value_Tuple);
            comp.EyeVector     = -ray.Direction;


            comp.NormalVector = Shape.NormalAt(comp.Object, comp.Point);
            if (comp.NormalVector.Dot(comp.EyeVector) < 0)
            {
                comp.Inside       = true;
                comp.NormalVector = -comp.NormalVector;
            }
            else
            {
                comp.Inside = false;
            }
            comp.OverPoint     = comp.Point + (comp.NormalVector * Arithmetic.EPSILON);
            comp.UnderPoint    = comp.Point - (comp.NormalVector * Arithmetic.EPSILON);
            comp.ReflectVector = Tuple.Reflect(ray.Direction, comp.NormalVector);

            return(comp);
        }