예제 #1
0
        //Check the material of the hit object and if the transparency is 0, return black.
        //Return calculated refracted value is it is transparent
        public Color RefractedColor(Computations c, int remaining = 1)
        {
            if (Utility.FE(c.rayObject.material.Transparency, 0) || remaining == 0)
            {
                return(Color.black);
            }

            //Check for infinite internal reflection
            double nRatio = c.n1 / c.n2;
            double cosI   = Vector.Dot(c.eye, c.normal);
            double sin2T  = nRatio * nRatio * (1 - (cosI * cosI));

            if (sin2T > 1)
            {
                return(Color.black);
            }

            double cosT = Math.Sqrt(1.0 - sin2T);

            Vector direction = c.normal * (nRatio * cosI - cosT) - c.eye * nRatio;

            Ray refractRay = new Ray(c.underPoint, direction);

            Color refractedColor = ColorAt(refractRay, remaining - 1) *
                                   c.rayObject.material.Transparency;

            //Replace later with code for refraction calculations
            return(refractedColor);
        }
예제 #2
0
        public Color ReflectedColor(Computations c, int remaining = 1)
        {
            if (remaining == 0 || Utility.FE(c.rayObject.material.Reflective, 0.0))
            {
                return(Color.black);
            }

            Ray reflectionRay = new Ray(c.overPoint, c.reflectVector);

            return(ColorAt(reflectionRay, remaining - 1) * c.rayObject.material.Reflective);
        }
예제 #3
0
        public Color ColorAt(Ray ray, int remaining = 1)
        {
            List <Intersection> hits = this.Intersections(ray);

            if (hits.Count == 0)
            {
                return(Color.black);
            }
            Intersection hit        = this.Hit(hits);
            Computations c          = Computations.Prepare(hit, ray, hits);
            Color        finalColor = Scene.current.ShadeHit(c, remaining);

            return(finalColor);
        }
예제 #4
0
        public double Schlick(Computations c)
        {
            double cos = Vector.Dot(c.eye, c.normal);

            if (c.n1 > c.n2)
            {
                double n     = c.n1 / c.n2;
                double sin2T = (n * n) * (1.0 - (cos * cos));
                if (sin2T > 1.0)
                {
                    return(1.0);
                }

                double cosT = Math.Sqrt(1.0 - sin2T);

                cos = cosT;
            }

            double r0 = Math.Pow((c.n1 - c.n2) / (c.n1 + c.n2), 2);

            return(r0 + (1 - r0) * Math.Pow((1 - cos), 5));
        }
예제 #5
0
        public Color ShadeHit(Computations c, int remaining = 1)
        {
            if (c == null)
            {
                return(Color.black);
            }

            Color surfaceColor = new Color(0, 0, 0);

            for (int i = 0; i < lights.Count; i++)
            {
                //Is this light in shadow?
                if (c.rayObject.canReceiveShadows)
                {
                    bool isShadow = IsShadowed(c.overPoint, lights[i]);
                    surfaceColor += c.rayObject.Lighting(c.point,
                                                         lights[i],
                                                         c.eye,
                                                         c.normal,
                                                         isShadow);
                }
            }

            Color reflected = this.ReflectedColor(c, remaining);

            Color refracted = this.RefractedColor(c, remaining);

            if (c.rayObject.material.Reflective > 0 &&
                c.rayObject.material.Transparency > 0)
            {
                double reflectance = this.Schlick(c);
                return(surfaceColor + reflected * reflectance +
                       refracted * (1.0 - reflectance));
            }

            return(surfaceColor + reflected + refracted);
        }
예제 #6
0
        public static Computations Prepare(Intersection i, Ray ray, List <Intersection> xs)
        {
            if (i == null)
            {
                return(null);
            }

            Point temp = ray.Position(i.t);

            Computations c = new Computations();

            c.rayObject = i.rayObject;
            c.t         = i.t;
            c.point     = temp;
            c.eye       = -ray.direction.Normalize();
            c.normal    = i.rayObject.GetNormal(temp, i).Normalize();
            c.n1        = RefractiveIndex.Vacuum;
            c.n2        = RefractiveIndex.Vacuum;

            if (c.normal.Dot(c.eye) < 0)
            {
                c.inside = true;
                c.normal = -c.normal;
            }
            else
            {
                c.inside = false;
            }

            //Transparency Intersections algorithm
            if (xs != null)
            {
                List <RayObject> container = new List <RayObject>();
                for (int x = 0; x < xs.Count; x++)
                {
                    if (i == xs[x])
                    {
                        if (container.Count == 0)
                        {
                            c.n1 = RefractiveIndex.Vacuum;
                        }
                        else
                        {
                            c.n1 = container.Last <RayObject>().material.RefracIndex;
                        }
                    }

                    if (container.Contains(xs[x].rayObject))
                    {
                        container.Remove(xs[x].rayObject);
                    }
                    else
                    {
                        container.Add(xs[x].rayObject);
                    }

                    if (i == xs[x])
                    {
                        if (container.Count == 0)
                        {
                            c.n2 = RefractiveIndex.Vacuum;
                        }
                        else
                        {
                            c.n2 = container.Last <RayObject>().material.RefracIndex;
                        }
                        break;
                    }
                }
            }

            c.reflectVector = Vector.Reflect(ray.direction, c.normal);

            c.overPoint  = c.point + (c.normal * Constants.epsilon);
            c.underPoint = c.point - (c.normal * Constants.epsilon);
            return(c);
        }