Example #1
0
        //test
        public static Bitmap newImage(int width, int height, List<Sphere> l_sphere)
        {
            Bitmap image = new Bitmap(width, height);

            l_sphere.Sort();
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    Ray r = new Ray(new Point(x, y, -2000), new Point(0f, 0f, 1), 1);
                    Color c = Color.White;
                    float dis = -r.Position.z;
                    Sphere currentSphere =  r.Intersection(l_sphere, ref dis);
                    image.SetPixel(x, y, Color.Black);
                    Point inter = r.Position + dis * r.Direction;
                    Point normal = inter - new Point(currentSphere.x, currentSphere.y, currentSphere.z);
                    float temp = normal * normal;
                    if (temp != 0 && dis != -r.Position.z)
                    {
                        temp = 1.0f / (float)Math.Sqrt(temp);
                        normal = temp * normal;
                        if(normal.z == -r.Direction.z)
                            Console.WriteLine("normal");
                        image.SetPixel(x, y, Color.FromArgb(((int)(currentSphere.color.R * (currentSphere.z - inter.z)) / currentSphere.rayon), (int)((currentSphere.color.G * (currentSphere.z - inter.z)) / currentSphere.rayon), (int)((currentSphere.color.B * (currentSphere.z - inter.z)) / currentSphere.rayon)));
                    }
                }
            }
            return image;
        }
Example #2
0
        public double? Intersect(Ray ray)
        {
            var dist = ray.Start - Position;

            var a = Vector3D.DotProduct(ray.Direction, ray.Direction);
            var b = 2*Vector3D.DotProduct(dist, ray.Direction);
            var c = Vector3D.DotProduct(dist, dist) - (Radius * Radius);

            var discriminant = b*b - 4*a*c;

            if(discriminant < 0)
                return null;

            var t1 = (-b + Math.Sqrt(discriminant))/2*a;
            var t2 = (-b - Math.Sqrt(discriminant))/2*a;

            if (t1 < 0.5 && t2 < 0.5)
                return null;

            if (t1 < 0.5)
                t1 = Double.MaxValue;

            if (t2 < 0.5)
                t2 = Double.MaxValue;

            return Math.Min(t1, t2);
        }
Example #3
0
File: Scene.cs Project: tgy/CSharp
        public Bitmap Render()
        {
            Bitmap bitmap = new Bitmap(Camera.Width, Camera.Height);

            if (Objects3D.Count < 1)
                return bitmap;

            for (int x = 0; x < Camera.Width; x++)
                for (int y = 0; y < Camera.Height; y++)
                {
                    Ray ray = new Ray(new Vector3D(x, y, 0),
                                        new Vector3D(x - Camera.D.X, y - Camera.D.Y,
                                                    -Camera.D.Z), 1);

                    Vector3D intersection = null;
                    Object3D selectedObject = null;

                    foreach (var object3D in Objects3D)
                    {
                        Vector3D objectIntersection = SelectIntersection(object3D.GetIntersections(ray));

                        if (objectIntersection == null)
                            continue;

                        if (selectedObject == null || objectIntersection.Z < intersection.Z)
                        {
                            selectedObject = object3D;
                            intersection = objectIntersection;
                        }
                    }

                    if (intersection != null)
                    {
                        double cosAngle = Math.Abs(ReflectedRayAngleCos(ray, selectedObject.GetNormal(intersection)));

                        cosAngle = Math.Pow(cosAngle, LightIntensity + 1);

                        int r = (int) (selectedObject.Color.R*cosAngle*ray.Intensity);
                        int g = (int) (selectedObject.Color.G*cosAngle*ray.Intensity);
                        int b = (int) (selectedObject.Color.B*cosAngle*ray.Intensity);

                        if (Grain && x%2 == 0 && y%2 == 0)
                        {
                            r += 20;
                            g += 20;
                            b += 20;
                        }

                        r = r < 0 ? 0 : r > 255 ? 255 : r;
                        g = g < 0 ? 0 : g > 255 ? 255 : g;
                        b = b < 0 ? 0 : b > 255 ? 255 : b;

                        bitmap.SetPixel(x, y, Color.FromArgb(r, g, b));
                    }
                }

            return bitmap;
        }
Example #4
0
        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();
        }
Example #5
0
        public override double find_intersection(Ray ray)
        {
            double a = ray.direction.dot(normal);

            if (a == 0)
            {
                return -1;
            }
            double b = normal.dot((ray.origin - (normal * distance)));
            double n = -1 * b / a;
            return n;
        }
Example #6
0
        public override Intersection Intersect(Ray ray)
        {
            float denom = Norm.X * ray.Dir.X + Norm.Y * ray.Dir.Y + Norm.Z * ray.Dir.Z;
            if (denom > 0) return null;

            return new Intersection()
            {
                Thing = this,
                Ray = ray,
                Dist = (Norm.X * ray.Start.X + Norm.Y * ray.Start.Y + Norm.Z * ray.Start.Z + Offset) / (-denom)
            };
        }
Example #7
0
        private RealColor? GetColorForRay(Ray viewRay, int iteration = 1)
        {
            var materialColor = new RealColor();

            var intersection = Scene.Objects
                .Select(o => new {Obj = o, Dist = o.Intersect(viewRay)})
                .Where(o => o.Dist != null)
                .OrderBy(f => f.Dist)
                .FirstOrDefault();

            if (intersection != null)
            {
                var start = viewRay.Start + (intersection.Dist.Value*viewRay.Direction);
                var normal = start - intersection.Obj.Position;
                normal.Normalize();

                foreach (var light in Scene.Lights)
                {
                    var lightRay = Ray.FromStartAndEndPoints(start, light.Position);

                    if (Scene.Objects.Any(o => o.Intersect(lightRay) != null))
                        continue;

                    if (Vector3D.DotProduct(normal, lightRay.Direction) < 0)
                        continue;

                    var lambert = Vector3D.DotProduct(lightRay.Direction, normal);

                    materialColor += lambert * light.Color * intersection.Obj.Material.Diffuse;

                }

                if (iteration > 10 || intersection.Obj.Material.ReflectionCoefficient <= 0)
                    return materialColor;

                var reflectionAngle = 2.0f * (Vector3D.DotProduct(viewRay.Direction, normal));
                var reflectionRay = new Ray(start, viewRay.Direction - reflectionAngle * normal);

                var reflectedColor = GetColorForRay(reflectionRay, iteration + 1);

                if (reflectedColor == null)
                    return materialColor;

                return materialColor +
                       reflectedColor*intersection.Obj.Material.ReflectionCoefficient;
            }

            //return null;
            return new RealColor(Background);
        }
Example #8
0
        public override float IntersectDistance(Ray ray)
        {
            float denom = Norm.X * ray.Dir.X + Norm.Y * ray.Dir.Y + Norm.Z * ray.Dir.Z;
            if (denom > 0) return float.MaxValue;

            // TODO:    is correct? this is never called.
            return (Norm.X * ray.Start.X + Norm.Y * ray.Start.Y + Norm.Z * ray.Start.Z + Offset);

            /*return new Intersection()
            {
                Thing = this,
                Ray = ray,
                Dist = (Norm.X * ray.Start.X + Norm.Y * ray.Start.Y + Norm.Z * ray.Start.Z + Offset) / (-denom)
            };*/
        }
        /*
        Taken from:  https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
        Haven't taken the time to understand it. Hope it works.
        */
        public override bool Intersects(Ray ray, ref Vector3D intPoint)
        {
            Vector3D e1, e2;  //Edge1, Edge2
            Vector3D P, Q, T;
            double det, inv_det, u, v;
            double t;

            //Find vectors for two edges sharing V1
            e1 = Vector3D.Subtract(_p2, _p1);
            e2 = Vector3D.Subtract(_p3, _p1);
            //Begin calculating determinant - also used to calculate u parameter
            P = Vector3D.CrossProduct(ray.Direction, e2);
            //if determinant is near zero, ray lies in plane of triangle
            det = Vector3D.DotProduct(e1, P);
            //NOT CULLING
            if (det == 0) return false;
            inv_det = 1.0d / det;

            //calculate distance from V1 to ray origin
            T = Vector3D.Subtract(ray.Source, _p1);

            //Calculate u parameter and test bound
            u = Vector3D.DotProduct(T, P) * inv_det;
            //The intersection lies outside of the triangle
            if (u < 0.0d || u > 1.0d) return false;

            //Prepare to test v parameter
            Q = Vector3D.CrossProduct(T, e1);

            //Calculate V parameter and test bound
            v = Vector3D.DotProduct(ray.Direction, Q) * inv_det;
            //The intersection lies outside of the triangle
            if (v < 0.0d || u + v > 1.0d) return false;

            t = Vector3D.DotProduct(e2, Q) * inv_det;

            if (t > 0)
            { //ray intersection
                intPoint = ray.Source + ray.Direction * t;
                return true;
            }

            // No hit, no win
            return false;
        }
        override public bool Intersects(Ray ray, ref Vector3D intPoint)
        {

            // Intersection formula from http://www.cl.cam.ac.uk/teaching/1999/AGraphHCI/SMAG/node2.html
            // t = (N * ( Q - E )) / (E - D)
            Vector3D E = ray.Source;
            Vector3D D = ray.Direction;
            Vector3D NegN = -m_Normal;
            if (Vector3D.DotProduct(m_Normal, D) != 0)
            {
                double t = (Vector3D.DotProduct(m_Normal, (Vector3D.Subtract(m_Point, E)))) / (Vector3D.DotProduct(m_Normal, D));
                if (t >= 0)
                {
                    intPoint = E + (D * t);
                    return true;
                }
            }

            return false;
        }
Example #11
0
 public override double find_intersection(Ray ray)
 {
     double b = (2 * (ray.origin.x - center.x) * ray.direction.x) + (2 * (ray.origin.y - center.y) * ray.direction.y) + (2 * (ray.origin.z - center.z) * ray.direction.z);
     double c = Math.Pow((ray.origin.x - center.x), 2) + Math.Pow((ray.origin.y - center.y), 2) + Math.Pow((ray.origin.z - center.z), 2) - Math.Pow(radius, 2);
     double discriminant = Math.Pow(b, 2) - 4 * c;
     if (discriminant > 0)
     {
         double root = ((-1 * b - Math.Sqrt(discriminant)) / 2);
         if (root > 0)
         {
             return root;
         }
         else
         {
             return ((-b + Math.Sqrt(discriminant)) / 2);
         }
     }
     else
     {
         return -1;
     }
 }
        private void GetColor(HitInfo info, Light lt, ColorAccumulator ca, int count)
        {
            Vector3D lightNormal = info.hitPoint - lt.Location;
            lightNormal.Normalize();

            if (InShadow(info, lt, lightNormal))
            {
                return;
            }

            double lambert = Vector3D.DotProduct(lightNormal, info.normal);
            if (lambert <= 0)
            {
                int r, g, b;
                r = b = g = 0;

                int r2 = 0;
                int g2 = 0;
                int b2 = 0;

                info.hitObj.GetColor(info.hitPoint, ref r, ref g, ref b);
                if (info.hitObj.Material != null && info.hitObj.Material is SolidColor)
                {
                    double phongTerm = Math.Pow(lambert, 20) * (info.hitObj.Material as SolidColor).Phong * 2;
                    r2 = (int)(lt.Color.R * phongTerm);
                    g2 = (int)(lt.Color.G * phongTerm);
                    b2 = (int)(lt.Color.B * phongTerm);
                    double reflet = 2.0f * (Vector3D.DotProduct(info.normal, info.ray.Direction));
                    Vector3D dir = info.ray.Direction - info.normal * reflet;
                    Ray reflect = new Ray(info.hitPoint + dir, dir);
                    ColorAccumulator rca = CastRay(reflect, ++count);
                    if (rca != null)
                    {
                        ca.accumR = ca.accumR + rca.accumR;
                        ca.accumG = ca.accumG + rca.accumG;
                        ca.accumB = ca.accumB + rca.accumB;
                    }
                }
                ca.accumR += (int)((lt.Color.R * r * -lambert) / 255) + r2;
                ca.accumG += (int)((lt.Color.G * g * -lambert) / 255) + g2;
                ca.accumB += (int)((lt.Color.B * b * -lambert) / 255) + b2;
            }
        }
Example #13
0
        /// <summary>
        /// This is the main RayTrace controller algorithm, the core of the RayTracer
        /// recursive method setup
        /// this does the actual tracing of the ray and determines the color of each pixel
        /// supports:
        /// - ambient lighting
        /// - diffuse lighting
        /// - Gloss lighting
        /// - shadows
        /// - reflections
        /// </summary>
        /// <param name="info"></param>
        /// <param name="ray"></param>
        /// <param name="scene"></param>
        /// <param name="depth"></param>
        /// <returns></returns>
        private Color RayTrace(IntersectInfo info, Ray ray, Scene scene, int depth)
        {
            // calculate ambient light
            Color  color     = info.Color * scene.Background.Ambience;
            double shininess = Math.Pow(10, info.Element.Material.Gloss + 1);

            foreach (Light light in scene.Lights)
            {
                // calculate diffuse lighting
                Vector v = (light.Position - info.Position).Normalize();

                if (RenderDiffuse)
                {
                    double L = v.Dot(info.Normal);
                    if (L > 0.0f)
                    {
                        color += info.Color * light.Color * L;
                    }
                }


                // this is the max depth of raytracing.
                // increasing depth will calculate more accurate color, however it will
                // also take longer (exponentially)
                if (depth < 3)
                {
                    // calculate reflection ray
                    if (RenderReflection && info.Element.Material.Reflection > 0)
                    {
                        Ray           reflectionray = GetReflectionRay(info.Position, info.Normal, ray.Direction);
                        IntersectInfo refl          = TestIntersection(reflectionray, scene, info.Element);
                        if (refl.IsHit && refl.Distance > 0)
                        {
                            // recursive call, this makes reflections expensive
                            refl.Color = RayTrace(refl, reflectionray, scene, depth + 1);
                        }
                        else // does not reflect an object, then reflect background color
                        {
                            refl.Color = scene.Background.Color;
                        }
                        color = color.Blend(refl.Color, info.Element.Material.Reflection);
                    }

                    //calculate refraction ray
                    if (RenderRefraction && info.Element.Material.Transparency > 0)
                    {
                        Ray           refractionray = GetRefractionRay(info.Position, info.Normal, ray.Direction, info.Element.Material.Refraction);
                        IntersectInfo refr          = info.Element.Intersect(refractionray);
                        if (refr.IsHit)
                        {
                            //refractionray = new Ray(refr.Position, ray.Direction);
                            refractionray = GetRefractionRay(refr.Position, refr.Normal, refractionray.Direction, refr.Element.Material.Refraction);
                            refr          = TestIntersection(refractionray, scene, info.Element);
                            if (refr.IsHit && refr.Distance > 0)
                            {
                                // recursive call, this makes refractions expensive
                                refr.Color = RayTrace(refr, refractionray, scene, depth + 1);
                            }
                            else
                            {
                                refr.Color = scene.Background.Color;
                            }
                        }
                        else
                        {
                            refr.Color = scene.Background.Color;
                        }
                        color = color.Blend(refr.Color, info.Element.Material.Transparency);
                    }
                }


                IntersectInfo shadow = new IntersectInfo();
                if (RenderShadow)
                {
                    // calculate shadow, create ray from intersection point to light
                    Ray shadowray = new Ray(info.Position, v);

                    // find any element in between intersection point and light
                    shadow = TestIntersection(shadowray, scene, info.Element);
                    if (shadow.IsHit && shadow.Element != info.Element)
                    {
                        // only cast shadow if the found interesection is another
                        // element than the current element
                        color *= 0.5 + 0.5 * Math.Pow(shadow.Element.Material.Transparency, 0.5); // Math.Pow(.5, shadow.HitCount);
                    }
                }

                // only show highlights if it is not in the shadow of another object
                if (RenderHighlights && !shadow.IsHit && info.Element.Material.Gloss > 0)
                {
                    // only show Gloss light if it is not in a shadow of another element.
                    // calculate Gloss lighting (Phong)
                    Vector Lv = (info.Element.Position - light.Position).Normalize();
                    Vector E  = (scene.Camera.Position - info.Element.Position).Normalize();
                    Vector H  = (E - Lv).Normalize();

                    double Glossweight = 0.0;
                    Glossweight = Math.Pow(Math.Max(info.Normal.Dot(H), 0), shininess);
                    color      += light.Color * (Glossweight);
                }
            }

            // normalize the color
            color.Limit();
            return(color);
        }
Example #14
0
 public IEnumerable<Intersection> Intersect(Ray r)
 {
     return from thing in Things
            select thing.Intersect(r);
 }
Example #15
0
        public override float IntersectDistance(Ray ray)
        {
            float eox = Center.X - ray.Start.X;
            float eoy = Center.Y - ray.Start.Y;
            float eoz = Center.Z - ray.Start.Z;
            float v = eox * ray.Dir.X + eoy * ray.Dir.Y + eoz * ray.Dir.Z;

            if (v < 0)
            {
                return float.MaxValue;
            }

            float disc = Radius2 - ((eox * eox + eoy * eoy + eoz * eoz) - v * v);

            if (disc < 0)
            {
                return float.MaxValue;
            }

            return v - disc;
        }
Example #16
0
        /// <summary>
        /// this is the main entrypoint for rendering a scene. this method is responsible for correctly rendering
        /// the graphics device (in this case a bitmap).
        /// Note that apart from the raytracing, painting on a graphics device is rather slow
        /// </summary>
        /// <param name="g">the graphics to render on</param>
        /// <param name="viewport">basically determines the size of the bitmap to render on</param>
        /// <param name="scene">the scene to render.</param>
        public void RayTraceScene(Graphics g, Rectangle viewport, Scene scene)
        {
            int maxsamples = (int)AntiAliasing;


            g.FillRectangle(Brushes.Black, viewport);

            //Color[] scanline1;
            //Color[] scanline2 = null;
            //Color[] scanline3 = null;

            Color[,] buffer = new Color[viewport.Width + 2, viewport.Height + 2];

            for (int y = 0; y < viewport.Height + 2; y++)
            {
                DateTime timestart = DateTime.Now;
                //// used for anti-aliasing
                //scanline1 = scanline2;
                //scanline2 = scanline3;
                //scanline3 = new Color[viewport.Width + 2];

                for (int x = 0; x < viewport.Width + 2; x++)
                {
                    double yp = y * 1.0f / viewport.Height * 2 - 1;
                    double xp = x * 1.0f / viewport.Width * 2 - 1;

                    Ray ray = scene.Camera.GetRay(xp, yp);

                    // this will trigger the raytracing algorithm
                    buffer[x, y] = CalculateColor(ray, scene);

                    if ((x > 1) && (y > 1))
                    {
                        if (AntiAliasing != AntiAliasing.None)
                        {
                            Color avg = (buffer[x - 2, y - 2] + buffer[x - 1, y - 2] + buffer[x, y - 2] +
                                         buffer[x - 2, y - 1] + buffer[x - 1, y - 1] + buffer[x, y - 1] +
                                         buffer[x - 2, y] + buffer[x - 1, y] + buffer[x, y]) / 9;

                            if (AntiAliasing == AntiAliasing.Quick)
                            {
                                // this basically implements a simple mean filter
                                // it quick but not very accurate
                                buffer[x - 1, y - 1] = avg;
                            }
                            else
                            {                                                  // use a more accurate antialasing method (MonteCarlo implementation)
                                // this will fire multiple rays per pixel
                                if (avg.Distance(buffer[x - 1, y - 1]) > 0.18) // 0.18 is a treshold for detailed aliasing
                                {
                                    for (int i = 0; i < maxsamples; i++)
                                    {
                                        // get some 'random' samples
                                        double rx = Math.Sign(i % 4 - 1.5) * (IntNoise(x + y * viewport.Width * maxsamples * 2 + i) + 1) / 4;     // interval <-0.5, 0.5>
                                        double ry = Math.Sign(i % 2 - 0.5) * (IntNoise(x + y * viewport.Width * maxsamples * 2 + 1 + i) + 1) / 4; // interval <-0.5, 0.5>

                                        xp = (x - 1 + rx) * 1.0f / viewport.Width * 2 - 1;
                                        yp = (y - 1 + ry) * 1.0f / viewport.Height * 2 - 1;

                                        ray = scene.Camera.GetRay(xp, yp);
                                        // execute even more ray traces, this makes detailed anti-aliasing expensive
                                        buffer[x - 1, y - 1] += CalculateColor(ray, scene);
                                    }
                                    buffer[x - 1, y - 1] /= (maxsamples + 1);
                                }
                            }
                        }

                        // this is the slow part of the painting algorithm, it can be greatly speed up
                        // by directly accessing the bitmap data
                        Brush br = new SolidBrush(buffer[x - 1, y - 1].ToArgb());
                        g.FillRectangle(br, viewport.Left + x - 2, viewport.Top + y - 2, 1, 1);
                        br.Dispose();
                    }
                }

                // update progress after every scanline
                if (RenderUpdate != null)
                {
                    double progress = (y) / (double)(viewport.Height);
                    double duration = DateTime.Now.Subtract(timestart).TotalMilliseconds;

                    double ETA = duration / progress - duration;
                    RenderUpdate.Invoke((int)progress * 100, duration, ETA, y - 1);
                }
            }
        }
Example #17
0
 /// <summary>
 /// Distance squared or float.MaxValue if no hit.
 /// </summary>
 /// <param name="ray"></param>
 /// <returns></returns>
 public abstract float IntersectDistance(Ray ray);
Example #18
0
        public override Intersection Intersect(Ray ray)
        {
            float eox = Center.X - ray.Start.X;
            float eoy = Center.Y - ray.Start.Y;
            float eoz = Center.Z - ray.Start.Z;
            float v = eox * ray.Dir.X + eoy * ray.Dir.Y + eoz * ray.Dir.Z;

            if (v < 0)
            {
                return null;
            }

            float disc = Radius2 - ((eox * eox + eoy * eoy + eoz * eoz) - v * v);

            if (disc < 0)
            {
                return null;
            }

            float dist = (v - Sqrt(disc));

            return new Intersection()
            {
                Thing = this,
                Ray = ray,
                Dist = dist
            };
        }
Example #19
0
        public static Bitmap run_raytracer(LinkedList<Object> objects, LinkedList<LightSource> lights, Camera c, Size size)
        {
            Console.WriteLine("Daniel Bolink's Ray Tracer");

            //image size
            int width = size.Width;
            int height = size.Height;

            // Create Camera
            //Camera c = new Camera(new Position(0, 0, -10), new Position(0,0,0));

            //create colors
            Color BGColor = new Color(0, 0, 0);
            //Color BLACK = new Color(0, 0, 0);
            //Color WHITE = new Color(255, 255, 255);
            //Color GREEN = new Color(0, 255, 0);
            //Color YELLOW = new Color(255, 255, 0);
            //Color ORANGE = new Color(255, 0, 255);
            //Color RED = new Color(200, 0, 0);
            //Color BLUE = new Color(0, 0, 255);
            //create Objects in frame

            //red plane at below 10 units
            //Object p1 = new Plane(new Vector(0, 1, 0), -1, RED);
            //blue sphere 10 units ahead radis 0.5
            //Object s1 = new Sphere(1, new Position(0, 0, 0), BLACK);
            //Object s2 = new Sphere(1, new Position(2, 0, 0), ORANGE);

            //add Objects to list
            //objects.AddLast(s1);
            //objects.AddLast(p1);
            //objects.AddLast(s2);

            //add Light Sources
            //LightSource l1 = new LightSource(new Position(20, 5, 10), WHITE);
            //LightSource l2 = new LightSource(new Position(-20, 5, 10), BLUE);

            //add lightsources to linked list
            //lights.AddLast(l1);
            //lights.AddLast(l2);

            // Create Pixels
            Color[,] pixels = new Color[width, height];

            //ray tracing algorithm
            for(int x = 0; x < width; x++)
            {
                for (int y = 0; y<height; y++)
                {
                    double xamnt = (x + 0.5) / width;
                    double yamnt = ((height - y) + 0.5) / height;

                    Vector ray_direction = (c.direction + (c.right * (xamnt-0.5) + (c.down * (yamnt - 0.5)))).normalize();

                    Ray ray = new Ray(c.position, ray_direction);

                    LinkedList<ObjectPair> intersection_objects = new LinkedList<ObjectPair>();
                    foreach(Object o in objects)
                    {
                        double val = o.find_intersection(ray);
                        if (val > 0)
                        {
                            intersection_objects.AddLast(new ObjectPair(o, val));
                        }
                        //Console.WriteLine(val);
                    }
                    //Console.WriteLine(intersection_objects.Count);
                    if(intersection_objects.Count == 0)
                    {
                        pixels[x, y] = BGColor;
                    }
                    else
                    {
                        ObjectPair winner = new ObjectPair(null, -1);
                        foreach (ObjectPair o in intersection_objects)
                        {
                            if (winner.val == -1)
                            {
                                winner = o;
                            }
                            else if(winner.val > o.val && o.val >= 0)
                            {
                                winner = o;
                            }
                        }
                        if(winner.val > 0)
                        {
                            Color final_color = winner.obj.color;
                            Position intersection_point = ray.origin + (ray.direction * (winner.val * 0.999));
                            foreach (LightSource l in lights)
                            {
                                Boolean shadowed = false;
                                Vector light_direction = new Vector(l.origin, intersection_point).normalize();
                                //Vector light_direction = new Vector(intersection_point, l.origin).normalize();
                                Ray shadow_ray = new Ray(intersection_point, light_direction);
                                foreach(Object o in objects)
                                {
                                    double obj_intersection = o.find_intersection(shadow_ray);
                                    if(obj_intersection > 0)
                                    {
                                        shadowed = true;
                                        break;
                                    }
                                }

                                if (!shadowed)
                                {

                                    Vector Winner_obj_normal = winner.obj.getNormalAt(intersection_point);
                                    double diffuse_coeffient = (shadow_ray.direction.normalize().dot(Winner_obj_normal));
                                    Vector reflection_direction = shadow_ray.direction - (2 * (shadow_ray.direction.dot(Winner_obj_normal)/Winner_obj_normal.magnitude()*Winner_obj_normal));
                                    Ray reflection = new Ray(intersection_point, reflection_direction);

                                    double specular_coefficient = reflection.direction.dot(ray.direction);
                                    final_color += l.color * 0.15;
                                    if(diffuse_coeffient > 0)
                                    {
                                        final_color += l.color * diffuse_coeffient * 0.15;
                                    }
                                    if(specular_coefficient > 0)
                                    {
                                        final_color += l.color * Math.Pow(specular_coefficient, 1000);
                                    }

                                }
                            }
                            pixels[x, y] = final_color.clip();
                        }
                        else
                        {
                            pixels[x, y] = BGColor;
                        }
                    }
                }
            }

            //create image
            Bitmap bmp = CreateImg(pixels);
            //Process photoViewer = Process.Start("RayTracer.png");
            //prompt for exit
            //Console.WriteLine("Press any key to exit.");
            //Console.ReadKey();
            return bmp;
        }
Example #20
0
 public abstract Intersection Intersect(Ray ray);
Example #21
0
        public Bitmap RayTraceRows(Scene scene, Rectangle viewport, int startRow, int numberOfRowsToTrace)
        {
            int maxsamples = (int)AntiAliasing;

            Color[,] buffer = new Color[viewport.Width + 2, numberOfRowsToTrace + 2];
            Bitmap image = new Bitmap(viewport.Width, numberOfRowsToTrace);

            for (int y = startRow; y < (startRow + numberOfRowsToTrace) + 2; y++)
            {
                for (int x = 0; x < viewport.Width + 2; x++)
                {
                    double yp = y * 1.0f / viewport.Height * 2 - 1;
                    double xp = x * 1.0f / viewport.Width * 2 - 1;

                    Ray ray = scene.Camera.GetRay(xp, yp);

                    // this will trigger the raytracing algorithm
                    buffer[x, y - startRow] = CalculateColor(ray, scene);

                    // if current line is at least 2 lines into the scan
                    if ((x > 1) && (y > startRow + 1))
                    {
                        if (AntiAliasing != AntiAliasing.None)
                        {
                            Color avg = (buffer[x - 2, y - startRow - 2] + buffer[x - 1, y - startRow - 2] + buffer[x, y - startRow - 2] +
                                         buffer[x - 2, y - startRow - 1] + buffer[x - 1, y - startRow - 1] + buffer[x, y - startRow - 1] +
                                         buffer[x - 2, y - startRow] + buffer[x - 1, y - startRow] + buffer[x, y - startRow]) / 9;

                            if (AntiAliasing == AntiAliasing.Quick)
                            {
                                // this basically implements a simple mean filter
                                // it quick but not very accurate
                                buffer[x - 1, y - startRow - 1] = avg;
                            }
                            else
                            {                                                             // use a more accurate antialasing method (MonteCarlo implementation)
                                // this will fire multiple rays per pixel
                                if (avg.Distance(buffer[x - 1, y - startRow - 1]) > 0.18) // 0.18 is a treshold for detailed aliasing
                                {
                                    for (int i = 0; i < maxsamples; i++)
                                    {
                                        // get some 'random' samples
                                        double rx = Math.Sign(i % 4 - 1.5) * (IntNoise(x + y * viewport.Width * maxsamples * 2 + i) + 1) / 4;     // interval <-0.5, 0.5>
                                        double ry = Math.Sign(i % 2 - 0.5) * (IntNoise(x + y * viewport.Width * maxsamples * 2 + 1 + i) + 1) / 4; // interval <-0.5, 0.5>

                                        xp = (x - 1 + rx) * 1.0f / viewport.Width * 2 - 1;
                                        yp = (y - 1 + ry) * 1.0f / viewport.Height * 2 - 1;

                                        ray = scene.Camera.GetRay(xp, yp);
                                        // execute even more ray traces, this makes detailed anti-aliasing expensive
                                        buffer[x - 1, y - startRow - 1] += CalculateColor(ray, scene);
                                    }
                                    buffer[x - 1, y - startRow - 1] /= (maxsamples + 1);
                                }
                            }
                        }

                        image.SetPixel(x - 2, y - startRow - 2, buffer[x - 1, y - startRow - 1].ToArgb());
                    }
                }
                System.Windows.Forms.Application.DoEvents();
            }

            return(image);
        }
Example #22
0
File: Scene.cs Project: tgy/CSharp
 public static double ReflectedRayAngleCos(Ray ray, Vector3D intersectionNormale)
 {
     double cos = Vector3D.Scalar(ray.Direction, intersectionNormale)/(ray.Direction.Norm()*intersectionNormale.Norm());
     return Math.Pow(-Math.Log(cos + 1), 2);
 }
Example #23
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;
        }
        private ColorAccumulator CastRay(Ray ray, int count)
        {
            if (count > RayDepth)
            {
                return null;
            }

            ColorAccumulator ca = null;
            HitInfo info = FindHitObject(ray);

            if (info.hitObj != null)
            {
                ca = CalculateLighting(info, count);
                ca.Clamp();
            }
            else
            {
                ca = new ColorAccumulator(BackColor.R, BackColor.G, BackColor.B);
            }

            return ca;
        }
Example #25
0
 public virtual double find_intersection(Ray ray)
 {
     Console.WriteLine("This shouldnt be here");
     return 0;
 }
 private HitInfo FindHitObject(Ray ray, Geometry originator, HitMode mode)
 {
     Vector3D intPoint = new Vector3D(double.MaxValue, double.MaxValue, double.MaxValue);
     HitInfo info = new HitInfo(null, intPoint, ray);
     double dist = double.MaxValue;
     foreach (Geometry geom in Scene.Geoms)
     {
         if (geom != originator && geom.Intersects(ray, ref intPoint))
         {
             double distToObj = Vector3D.Subtract(ray.Source, intPoint).Length;
             if (distToObj < dist)
             {
                 info.hitPoint = intPoint;
                 dist = distToObj;
                 info.hitObj = geom;
                 if (mode == HitMode.Any)
                 {
                     break;
                 }
             }
         }
     }
     return info;
 }
 private HitInfo FindHitObject(Ray ray) => FindHitObject(ray, null, HitMode.Closest);
Example #28
0
 public virtual List<Vector3D> GetIntersections(Ray ray)
 {
     return null;
 }
 private bool InShadow(HitInfo info, Light lt, Vector3D lightNormal)
 {
     Ray shadowRay = new Ray(lt.Location, lightNormal);
     HitInfo shadinfo = FindHitObject(shadowRay, info.hitObj, HitMode.Closest);
     if (shadinfo.hitObj != null && Vector3D.Subtract(lt.Location, info.hitPoint).Length > Vector3D.Subtract(lt.Location, shadinfo.hitPoint).Length)
     {
         return true;
     }
     return false;
 }
Example #30
0
 private Color TraceRayAgainstScene(Ray ray, Scene scene)
 {
     Intersection intersection;
     if (TryCalculateIntersection(ray, scene, null, out intersection))
     {
         return CalculateRecursiveColor(intersection, scene, 0);
     }
     else
     {
         return scene.BackgroundColor;
     }
 }
 public HitInfo(Geometry hitObj, Vector3D hitPoint, Ray ray)
 {
     this.hitObj = hitObj;
     this.hitPoint = hitPoint;
     this.ray = ray;
 }
Example #32
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;
            }
        }
 public Color CaculateColour(Ray ray, Scene scene)
 {
     throw new NotImplementedException();
 }