public Colour CalculateLighting(Intersection intersection, Ray ray, int recursionDepth)
        {
            const int maxRecursionDepth = 10; //todo
            if (recursionDepth > maxRecursionDepth || !ray.IsColourSignificant)
            {
                return new Colour(0,0,0);
            }

            throw new NotImplementedException();
        }
Beispiel #2
0
        /// <summary>
        /// Determines whether a given ray intersects with any scene objects (other than excludedObject)
        /// </summary>
        /// <param name="ray">The ray to test</param>
        /// <param name="scene">The scene to test</param>
        /// <param name="excludedObject">An object that is not tested for intersections</param>
        /// <param name="intersection">If the intersection test succeeds, contains the closest intersection</param>
        /// <returns>A value indicating whether or not any scene object intersected with the ray</returns>
        private bool TryCalculateIntersection(Ray ray, Scene scene, DrawableSceneObject excludedObject, out Intersection intersection)
        {
            var closestDistance = float.PositiveInfinity;
            var closestIntersection = new Intersection();
            foreach (var sceneObject in scene.DrawableObjects)
            {
                Intersection i;
                if (sceneObject != excludedObject && sceneObject.TryCalculateIntersection(ray, out i))
                {
                    if (i.Distance < closestDistance)
                    {

                        closestDistance = i.Distance;
                        closestIntersection = i;
                    }
                }
            }

            if (closestDistance == float.PositiveInfinity)
            {
                intersection = new Intersection();
                return false;
            }
            else
            {
                intersection = closestIntersection;
                return true;
            }
        }
Beispiel #3
0
        /// <summary>
        /// Recursive algorithm base
        /// </summary>
        /// <param name="intersection">The intersection the recursive step started from</param>
        /// <param name="ray">The ray, starting from the intersection</param>
        /// <param name="scene">The scene to trace</param>
        private Color CalculateRecursiveColor(Intersection intersection, Scene scene, int depth)
        {
            // Ambient light:
            var color = Color.Lerp(Color.Black, intersection.Color * scene.AmbientLightColor, scene.AmbientLightIntensity);

            foreach (Light light in scene.Lights)
            {
                var lightContribution = new Color();
                var towardsLight = (light.Position - intersection.Point).Normalized();
                var lightDistance = Util.Distance(intersection.Point, light.Position);

                // Accumulate diffuse lighting:
                var lightEffectiveness = Vector3.Dot(towardsLight, intersection.Normal);
                if (lightEffectiveness > 0.0f)
                {
                    lightContribution = lightContribution + (intersection.Color * light.GetIntensityAtDistance(lightDistance) * light.Color * lightEffectiveness);
                }

                // Render shadow
                var shadowRay = new Ray(intersection.Point, towardsLight);
                Intersection shadowIntersection;
                if (TryCalculateIntersection(shadowRay, scene, intersection.ObjectHit, out shadowIntersection) && shadowIntersection.Distance < lightDistance)
                {
                    var transparency = shadowIntersection.ObjectHit.Material.Transparency;
                    var lightPassThrough = Util.Lerp(.25f, 1.0f, transparency);
                    lightContribution = Color.Lerp(lightContribution, Color.Zero, 1 - lightPassThrough);
                }

                color += lightContribution;
            }

            if (depth < ReflectionDepth)
            {
                // Reflection ray
                var objectReflectivity = intersection.ObjectHit.Material.Reflectivity;
                if (objectReflectivity > 0.0f)
                {
                    var reflectionRay = GetReflectionRay(intersection.Point, intersection.Normal, intersection.ImpactDirection);
                    Intersection reflectionIntersection;
                    if (TryCalculateIntersection(reflectionRay, scene, intersection.ObjectHit, out reflectionIntersection))
                    {
                        color = Color.Lerp(color, CalculateRecursiveColor(reflectionIntersection, scene, depth + 1), objectReflectivity);
                    }
                }

                // Refraction ray
                var objectRefractivity = intersection.ObjectHit.Material.Refractivity;
                if (objectRefractivity > 0.0f)
                {
                    var refractionRay = GetRefractionRay(intersection.Point, intersection.Normal, intersection.ImpactDirection, objectRefractivity);
                    Intersection refractionIntersection;
                    if (TryCalculateIntersection(refractionRay, scene, intersection.ObjectHit, out refractionIntersection))
                    {
                        var refractedColor = CalculateRecursiveColor(refractionIntersection, scene, depth + 1);
                        color = Color.Lerp(color, refractedColor, 1 - (intersection.ObjectHit.Material.Opacity));
                    }
                }
            }

            color = color.Limited;
            return color;
        }
Beispiel #4
0
 protected override Tuple LocalNormalAt(Tuple localPoint, Intersection hit)
 {
     return(localPoint - Tuple.Point(0, 0, 0));
 }
Beispiel #5
0
        private Color Shade(Intersection isect, Scene scene, int depth)
        {
            var d = isect.Ray.Dir;
            var pos = new Vector(
                                    isect.Dist * isect.Ray.Dir.X + isect.Ray.Start.X,
                                    isect.Dist * isect.Ray.Dir.Y + isect.Ray.Start.Y,
                                    isect.Dist * isect.Ray.Dir.Z + isect.Ray.Start.Z
                                );
            var normal = isect.Thing.Normal(pos);
            var reflectDir = Vector.Minus(d, Vector.Times(2 * Vector.Dot(normal, d), normal));
            // TODO:    whats wrong with this?
            /*var reflectDir = new Vector(
                                        d.X - (2.0f * normal.X * d.X * normal.X),
                                        d.Y - (2.0f * normal.Y * d.Y * normal.Y),
                                        d.Z - (2.0f * normal.Z * d.Z * normal.Z)
                                        );*/

            Color natColor = GetNaturalColor(isect.Thing, pos, normal, reflectDir, scene);
            Color ret = new Color(Color.DefaultColor.R + natColor.R,Color.DefaultColor.R + natColor.G, Color.DefaultColor.R + natColor.B);

            if (depth >= MaxDepth)
            {
                return new Color(ret.R + Color.Grey.R, ret.G + Color.Grey.G, ret.B + Color.Grey.B);
            }

            Color refColor = GetReflectionColor(isect.Thing, new Vector(pos.X + .001f * reflectDir.X, pos.Y + .001f * reflectDir.Y, pos.Z + .001f * reflectDir.Z), normal, reflectDir, scene, depth);

            return new Color(ret.R + refColor.R, ret.G + refColor.G, ret.B + refColor.B);
        }
Beispiel #6
0
        private Intersection ClosestIntersection(Ray ray, Scene scene)
        {
            Intersection closest = new Intersection() { Dist = float.MaxValue, Thing = null, Ray = null };

            for (int i = 0; i < scene.Things.Length; i++)
            {
                var thing = scene.Things[i];

                Intersection intersection = thing.Intersect(ray);

                if (intersection != null && intersection.Dist < closest.Dist)
                {
                    closest = intersection;
                }
            }

            return closest.Thing == null ? null : closest;
        }
Beispiel #7
0
        // Get illumination for lightsource with index i
        private Vector3 CalculateIllumination(Intersection intersect, int i, bool drawDebugLine)
        {
            Ray shadowRay = new Ray();

            shadowRay.origin = intersect.intersectionPoint;

            // Keep an non-normalized directon in case we need to calculate length later
            Vector3 rayDirection = lights[i].pos - intersect.intersectionPoint;

            shadowRay.t = rayDirection.Length();

            // Normalize for calulating intersections
            shadowRay.direction = Vector3.Normalize(rayDirection);

            // Offset the origin by a small margin
            shadowRay.origin += 0.001f * shadowRay.direction;

            //  Check if any primitives intersect with this shadowray
            Intersection lightBlocker = Intersect(shadowRay);

            if (lightBlocker != null)
            {
                // Intersection point is in the shadow, return black.
                if (drawDebugLine)
                {
                    Debugger.DrawDebugLine(
                        shadowRay.origin.X,
                        shadowRay.origin.Z,
                        lightBlocker.intersectionPoint.X,
                        lightBlocker.intersectionPoint.Z,
                        System.Drawing.Color.Orange);
                }

                return(new Vector3(0, 0, 0));
            }

            //shadowRay = new Ray();
            //shadowRay.origin = intersect.intersectionPoint;

            //// Keep an non-normalized directon in case we need to calculate length later
            //rayDirection = lights[i].pos - intersect.intersectionPoint;
            //shadowRay.t = rayDirection.Length();

            //// Normalize for calulating intersections
            //shadowRay.direction = Vector3.Normalize(rayDirection);

            //// Offset the origin by a small margin
            //shadowRay.origin += 0.001f * shadowRay.direction;

            ////  Check if any primitives intersect with this shadowray
            //lightBlocker = Intersect(shadowRay);


            // Intersection point is in the shadow, return black.
            if (drawDebugLine)
            {
                Debugger.DrawDebugLine(
                    shadowRay.origin.X,
                    shadowRay.origin.Z,
                    lights[i].pos.X,
                    lights[i].pos.Z,
                    System.Drawing.Color.Yellow);
            }

            // No intersection happened so we can calculate light color/intensity:
            float dist        = rayDirection.Length();
            float attenuation = 1 / (dist * dist);

            return(lights[0].color * Vector3.Dot(intersect.normal, shadowRay.direction) * attenuation);
        }
Beispiel #8
0
 public override Vector LocalNormalAt(Point local_point, Intersection hit = null) =>
 this.Normal;
Beispiel #9
0
        /// <summary>
        /// Determines whether a given ray intersects with any scene objects (other than excludedObject)
        /// </summary>
        /// <param name="ray">The ray to test</param>
        /// <param name="scene">The scene to test</param>
        /// <param name="excludedObject">An object that is not tested for intersections</param>
        /// <param name="intersection">If the intersection test succeeds, contains the closest intersection</param>
        /// <returns>A value indicating whether or not any scene object intersected with the ray</returns>
        private bool TryCalculateIntersection(Ray ray, Scene scene, DrawableSceneObject excludedObject, out Intersection intersection)
        {
            var closestDistance     = float.PositiveInfinity;
            var closestIntersection = new Intersection();

            foreach (var sceneObject in scene.DrawableObjects)
            {
                Intersection i;
                if (sceneObject != excludedObject && sceneObject.TryCalculateIntersection(ray, out i))
                {
                    if (i.Distance < closestDistance)
                    {
                        closestDistance     = i.Distance;
                        closestIntersection = i;
                    }
                }
            }

            if (closestDistance == float.PositiveInfinity)
            {
                intersection = new Intersection();
                return(false);
            }
            else
            {
                intersection = closestIntersection;
                return(true);
            }
        }
Beispiel #10
0
        /// <summary>
        /// Recursive algorithm base
        /// </summary>
        /// <param name="intersection">The intersection the recursive step started from</param>
        /// <param name="ray">The ray, starting from the intersection</param>
        /// <param name="scene">The scene to trace</param>
        private Color CalculateRecursiveColor(Intersection intersection, Scene scene, int depth)
        {
            // Ambient light:
            var color = Color.Lerp(Color.Black, intersection.Color * scene.AmbientLightColor, scene.AmbientLightIntensity);

            foreach (Light light in scene.Lights)
            {
                var lightContribution = new Color();
                var towardsLight      = (light.Position - intersection.Point).Normalized();
                var lightDistance     = Util.Distance(intersection.Point, light.Position);

                // Accumulate diffuse lighting:
                var lightEffectiveness = VectorMath.DotProduct(towardsLight, intersection.Normal);
                if (lightEffectiveness > 0.0f)
                {
                    lightContribution = lightContribution + (intersection.Color * light.GetIntensityAtDistance(lightDistance) * light.Color * lightEffectiveness);
                }

                // Render shadow
                var          shadowRay = new Ray(intersection.Point, towardsLight);
                Intersection shadowIntersection;
                if (TryCalculateIntersection(shadowRay, scene, intersection.ObjectHit, out shadowIntersection) && shadowIntersection.Distance < lightDistance)
                {
                    var transparency     = shadowIntersection.ObjectHit.Material.Transparency;
                    var lightPassThrough = Util.Lerp(.25f, 1.0f, transparency);
                    lightContribution = Color.Lerp(lightContribution, Color.Zero, 1 - lightPassThrough);
                }

                color += lightContribution;
            }

            if (depth < ReflectionDepth)
            {
                // Reflection ray
                var objectReflectivity = intersection.ObjectHit.Material.Reflectivity;
                if (objectReflectivity > 0.0f)
                {
                    var          reflectionRay = GetReflectionRay(intersection.Point, intersection.Normal, intersection.ImpactDirection);
                    Intersection reflectionIntersection;
                    if (TryCalculateIntersection(reflectionRay, scene, intersection.ObjectHit, out reflectionIntersection))
                    {
                        color = Color.Lerp(color, CalculateRecursiveColor(reflectionIntersection, scene, depth + 1), objectReflectivity);
                    }
                }

                // Refraction ray
                var objectRefractivity = intersection.ObjectHit.Material.Refractivity;
                if (objectRefractivity > 0.0f)
                {
                    var          refractionRay = GetRefractionRay(intersection.Point, intersection.Normal, intersection.ImpactDirection, objectRefractivity);
                    Intersection refractionIntersection;
                    if (TryCalculateIntersection(refractionRay, scene, intersection.ObjectHit, out refractionIntersection))
                    {
                        var refractedColor = CalculateRecursiveColor(refractionIntersection, scene, depth + 1);
                        color = Color.Lerp(color, refractedColor, 1 - (intersection.ObjectHit.Material.Opacity));
                    }
                }
            }

            color = color.Limited;
            return(color);
        }
Beispiel #11
0
        //public Computation(float t, RayObject rayObject,
        //                    Point point, Vector3 eyeV,
        //                    Vector3 normalV, bool inside,
        //                    Vector3 reflectV, float n1,
        //                    float n2)
        //{
        //    this.t = t;
        //    this.rayObject = rayObject;
        //    this.point = point;
        //    this.eyeV = eyeV;
        //    this.normalV = normalV;
        //    this.inside = inside;

        //    overPoint = point + normalV * Utilities.shadowPointEpsilon;

        //    this.reflectV = reflectV;

        //    this.n1 = n1;
        //    this.n2 = n2;

        //}

        public Computation(Intersection i, Ray r, List <Intersection> xs = null)
        {
            this.t         = i.t;
            this.rayObject = i.rayObject;
            this.point     = r.GetPointPosition(i.t);
            this.eyeV      = -r.direction;
            this.normalV   = rayObject.GetNormal(point);

            // Checks if eye vector and normal are pointing in the same direction
            // if dot product is less than zero that point in the same direction.
            if (Vector3.Dot(eyeV, normalV) < 0)
            {
                inside  = true;
                normalV = -normalV;
            }
            else
            {
                inside = false;
            }


            // If a List<Intersection> parameter is not passed into the method
            // create one using i as the only intersection in the list
            if (xs == null)
            {
                xs = new List <Intersection>()
                {
                    i
                }
            }
            ;

            // Transparency Intersections algorithm
            List <RayObject> containers = new List <RayObject>();

            foreach (Intersection intersect in xs)
            {
                // n1
                if (i == intersect)
                {
                    if (containers.Count == 0)
                    {
                        this.n1 = 1.0f;
                    }
                    else
                    {
                        this.n1 = containers.Last <RayObject>().material.RefractIndex;
                    }
                }

                if (containers.Contains(intersect.rayObject))
                {
                    containers.Remove(intersect.rayObject);
                    //Console.WriteLine("Object Removed: " + intersect.rayObject.ToString());
                }
                else
                {
                    containers.Add(intersect.rayObject);
                    //Console.WriteLine("Object Added: " + intersect.rayObject.ToString());
                }
                //Console.WriteLine("List Lenght: " + containers.Count);

                // n2
                if (i == intersect)
                {
                    if (containers.Count == 0)
                    {
                        this.n2 = 1.0f;
                    }
                    else
                    {
                        this.n2 = containers[containers.Count - 1].material.RefractIndex;
                    }
                    break;
                }
            }

            this.reflectV   = Vector3.Reflection(r.direction, this.normalV);
            this.overPoint  = point + normalV * Utilities.OVER_POINT_EPSILON;
            this.underPoint = point - normalV * Utilities.UNDER_POINT_EPSILON;
        }
Beispiel #12
0
 public static IntersectionState Prepare(ref Intersection i, ref Ray r) =>
 Prepare(ref i, ref r, new List <Intersection> {
     i
 });
Beispiel #13
0
 protected override Tuple LocalNormalAt(Tuple p, Intersection hit)
 {
     return(Tuple.Vector(0, 1, 0));
 }