Пример #1
0
 public Tracer(Scene s)
 {
     Width = 640;
     Height = 480;
     Background = Color.Black;
     Scene = s;
 }
Пример #2
0
        public MainWindow()
        {
            scene = Scene.TwoPlanes;
            this.ReflectionDepth = 5;
            this.FieldOfView = 120;
            scene.Camera.FieldOfView = this.FieldOfView;
            this.MultiThreadedRendering = true;
            this.DrawLinesAsync = true;

            InitializeComponent();
            InitializeKeyListeners();
            InitializeSceneOptions();
            this.SizeToContent = System.Windows.SizeToContent.Manual;
            this.Width = 640;
            this.Height = 480;

            Task.Run(() =>
                {
                    Task.Delay(100).Wait();
                    this.InvokeOnApplicationDispatcher(() =>
                        {
                            DrawSceneLinesMultiThreaded();
                        });
                });
        }
Пример #3
0
        private RayTracer.Scene CreateScene()
        {
            RayTracer.Scene scene = new RayTracer.Scene();

            scene.SetLight(this.light);
            scene.SetCamera(this.camera);
            scene.allObjects = this.objects.Values.ToList();
            return(scene);
        }
Пример #4
0
        private void MenuItem_Save_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.SaveFileDialog saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();

            saveFileDialog1.Filter = "|*.xml";
            saveFileDialog1.Title  = "Save database";
            saveFileDialog1.ShowDialog();

            // If the file name is not an empty string open it for saving.
            if (saveFileDialog1.FileName != "")
            {
                RayTracer.Scene scene = CreateScene();
                RayTracer.Database.DatabaseHandler.Save(scene, saveFileDialog1.FileName);
            }
        }
Пример #5
0
        // Camera = new Camera(new Vector3(0, 0, -5), new Vector3(0, 0, 1));
        public Image TraceRay(Viewport viewport, Camera camera, Scene scene)
        {
            var image = new Image(viewport);
            Color[,] colours;

            for (int y = 0; y < viewport.Height; y++)
            {
                for (int x = 0; x < viewport.Width; x++)
                {
                    Ray ray = camera.GetRay(x, y, viewport);

                }
            }

            throw new NotImplementedException();
        }
Пример #6
0
        private void renderButton_Click(object sender, RoutedEventArgs e)
        {
            Button button = (Button)sender;

            if ((string)button.Content == "Render")
            {
                ts = new CancellationTokenSource();
                CancellationToken ct = ts.Token;
                Task.Factory.StartNew(() =>
                {
                    RayTracer.Scene scene = CreateScene();
                    if (addFloor)
                    {
                        RayTracer.Floor floor = new RayTracer.Floor(1, new RayTracer.Point(-10, 0, -10), new RayTracer.Point(10, 0, 10));
                        floor.SetProperties(0.6f, 0.4f, 0);
                        floor.SetColors(new RayTracer.Color(0, 0, 0), new RayTracer.Color(1, 1, 1));
                        scene.allObjects.Add(floor);
                    }
                    RayTracer.Renderer renderer = new RayTracer.Renderer(scene, scene.allObjects);
                    scene.width  = RenderWidth;
                    scene.height = RenderHeight;
                    renderer.ct  = ct;
                    Console.WriteLine("Raytracing started.");
                    int time = Environment.TickCount;
                    RayTracer.RenderWindow window = renderer.Render();
                    if (ct.IsCancellationRequested)
                    {
                        return;
                    }
                    time = -time + Environment.TickCount;
                    Console.WriteLine("Raytracing finished.");
                    window.ShowImage();
                    Console.WriteLine("Intersection calculating time: \t" + scene.intersectionCalculationCount + "\nRender time: \t\t" + time + "ms");
                    window.ShowDialog();
                }, ct);
                button.Content = "Cancel";
            }
            else
            {
                // Can't wait anymore => cancel this task
                ts.Cancel();
                button.Content = "Render";
            }
        }
        private void loadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "JSON Scene|*.json";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    sc = Scene.Load(ofd.FileName);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error loading scene", MessageBoxButtons.OK);
                    return;
                }

                tsslblScene.Text = Path.GetFileName(ofd.FileName);
                pnlControls.Enabled = true;

            }
        }
Пример #8
0
        private void SetupScene(int width, int height)
        {
            //Vector3D bunnyCenter = loadedPlyFile.GetScanAsSpheres().GetAxisAlignedBoundingBox().Center;

            scene            = new RayTracer.Scene();
            scene.camera     = new RayTracer.Camera(width, height, MathHelper.DegreesToRadians(40));
            scene.background = new RayTracer.Background(new RGBA_Floats(0.5, .5, .5), 0.4);

            //AddBoxAndSheresBooleanTest();
            //AddBoxAndBoxBooleanTest();
#if false
            renderCollection.Add(new BoxShape(new Vector3(), new Vector3(1, 1, 1),
                                              new SolidMaterial(new RGBA_Floats(.9, .2, .1), .01, 0.0, 2.0)));
            renderCollection.Add(new BoxShape(new Vector3(.5, .5, .5), new Vector3(1.5, 1.5, 1.5),
                                              new SolidMaterial(new RGBA_Floats(.9, .2, .1), .01, 0.0, 2.0)));
#endif
            //renderCollection.Add(new CylinderShape(.25, 1, new SolidMaterial(RGBA_Floats.Cyan, 0, 0, 0)));

            //AddSphereAndBox();
            //AddAxisMarker();
            //AddCubeOfShperes();

            renderCollection.Add(MakerGearXCariage());

            allObjects         = BoundingVolumeHierarchy.CreateNewHierachy(renderCollection);
            trackBallTransform = new Transform(allObjects);
            //allObjects = root;
            scene.shapes.Add(trackBallTransform);

            //AddAFloor();

            //add two lights for better lighting effects
            scene.lights.Add(new Light(new Vector3(50, -10, 100), new RGBA_Floats(0.8, 0.8, 0.8)));
            scene.lights.Add(new Light(new Vector3(-30, -150, 50), new RGBA_Floats(0.8, 0.8, 0.8)));

            OrientCamera();
        }
Пример #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;
            }
        }
Пример #10
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;
     }
 }
Пример #11
0
        /// <summary>
        /// Renders the given scene, providing a callback for each individual line rendered. Each line is rendered on a separate thread.
        /// </summary>
        /// <param name="width">The width of the rendered image</param>
        /// <param name="width">The height of the rendered image</param>
        /// <param name="scene">The scene to render</param>
        /// <param name="callback">The delegate invoked when a thread completes rendering a line</param>
        public void RenderSceneLinesThreaded(Scene scene, int width, int height, LineFinishedHandler callback)
        {
            if (width == -1 || height == -1)
            {
                width = renderSize.Width;
                height = renderSize.Height;
            }
            else
            {
                renderSize = new Size(width, height);
            }

            var before = DateTime.UtcNow;
            List<Task> tasks = new List<Task>();

            for (int yCounter = height - 1; yCounter >= 0; yCounter--)
            {
                var y = yCounter;
                Color[] colors = new Color[width];
                Task.Run(() =>
                {
                    for (int xCounter = 0; xCounter < width; xCounter++)
                    {
                        var x = xCounter;
                        var viewPortX = ((2 * x) / (float)width) - 1;
                        var viewPortY = ((2 * y) / (float)height) - 1;
                        var color = TraceRayAgainstScene(GetRay(viewPortX, viewPortY), scene);
                        colors[x] = color;
                    }
                    callback(y, colors);
                });
            }

            var after = DateTime.UtcNow;
            System.Diagnostics.Debug.WriteLine("Total render time: " + (after - before).TotalMilliseconds + " ms");
        }
Пример #12
0
 private void Form1_Load(object sender, EventArgs e)
 {
     Scene = new Scene(new Camera(pictureBox1.Width, pictureBox1.Height, -10000));
     Scene.LightIntensity = trackBar1.Value;
 }
Пример #13
0
 public Color CaculateColour(Ray ray, Scene scene)
 {
     throw new NotImplementedException();
 }
Пример #14
0
 private double TestRay(Ray ray, Scene scene)
 {
     var isects = Intersections(ray, scene);
     ISect isect = isects.FirstOrDefault();
     if (isect == null)
         return 0;
     return isect.Dist;
 }
Пример #15
0
 private IEnumerable<ISect> Intersections(Ray ray, Scene scene)
 {
     return scene.Things
                 .Select(obj => obj.Intersect(ray))
                 .Where(inter => inter != null)
                 .OrderBy(inter => inter.Dist);
 }
Пример #16
0
        private Colour GetNaturalColor(Thing thing, Vector3 pos, Vector3 norm, Vector3 rd, Scene scene)
        {
            Colour ret = new Colour(0, 0, 0);

            foreach (LightSource light in scene.Lights)
            {
                Vector3 ldis       = light.Pos - pos;
                Vector3 livec      = ldis.Normalized();
                double  neatIsect  = TestRay(new Ray(pos, livec), scene);
                bool    isInShadow = !((neatIsect > ldis.Length()) || (neatIsect == 0));
                if (!isInShadow)
                {
                    double illum    = livec.DotProduct(norm);
                    Colour lcolor   = illum > 0 ? illum * light.Color : new Colour(0, 0, 0);
                    double specular = livec.DotProduct(rd.Normalized());
                    Colour scolor   = specular > 0 ? Math.Pow(specular, thing.Surface.Roughness) * light.Color : new Colour(0, 0, 0);
                    ret = ret + (thing.Surface.Diffuse(pos) * lcolor) + (thing.Surface.Specular(pos) * scolor);
                }
            }
            return(ret);
        }
Пример #17
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);
                }
            }
        }
Пример #18
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);
        }
Пример #19
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);
        }
Пример #20
0
 private Colour GetReflectionColor(Thing thing, Vector3 pos, Vector3 norm, Vector3 rd, Scene scene, int depth)
 {
     return(thing.Surface.Reflect(pos) * TraceRay(new Ray(pos, rd), scene, depth + 1));
 }
Пример #21
0
 private Color Shade(ISect isect, Scene scene, int depth)
 {
     var d = isect.Ray.Dir;
     var pos = Vector.Plus(Vector.Times(isect.Dist, isect.Ray.Dir), isect.Ray.Start);
     var normal = isect.Thing.Normal(pos);
     var reflectDir = Vector.Minus(d, Vector.Times(2 * Vector.Dot(normal, d), normal));
     Color ret = Color.DefaultColor;
     ret = Color.Plus(ret, GetNaturalColor(isect.Thing, pos, normal, reflectDir, scene));
     if (depth >= MaxDepth) {
         return Color.Plus(ret, Color.Make(.5, .5, .5));
     }
     return Color.Plus(ret, GetReflectionColor(isect.Thing, Vector.Plus(pos, Vector.Times(.001, reflectDir)), normal, reflectDir, scene, depth));
 }
Пример #22
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;
        }
Пример #23
0
 private Color TraceRay(Ray ray, Scene scene, int depth)
 {
     var isects = Intersections(ray, scene);
     ISect isect = isects.FirstOrDefault();
     if (isect == null)
         return Color.Background;
     return Shade(isect, scene, depth);
 }
Пример #24
0
        private Color GetNaturalColor(SceneObject thing, Vector pos, Vector norm, Vector rd, Scene scene)
        {
            Color ret = new Color(Color.DefaultColor.R, Color.DefaultColor.G, Color.DefaultColor.B);
            Vector rdNormalized = Vector.Norm(rd);

            for (int i = 0; i < scene.Lights.Length; i++)
            {
                Light light = scene.Lights[i];

                float vx = light.Pos.X - pos.X;
                float vy = light.Pos.Y - pos.Y;
                float vz = light.Pos.Z - pos.Z;

                float sqrLength, invLength;

                sqrLength = vx * vx + vy * vy + vz * vz;
                invLength = SceneObject.InvSqrt(sqrLength);

                Vector livec = new Vector(vx * invLength, vy * invLength, vz * invLength);

                float neatIsect = TestRay(new Ray() { Start = pos, Dir = livec }, scene);

                bool isInShadow = !((neatIsect == 0) || (neatIsect > vx * vx + vy * vy + vz * vz));

                if (!isInShadow)
                {
                    float illum = livec.X * norm.X + livec.Y * norm.Y + livec.Z * norm.Z;
                    float specular = livec.X * rdNormalized.X + livec.Y * rdNormalized.Y + livec.Z * rdNormalized.Z;

                    Color lcolor = illum > 0 ? Color.Times(illum, light.Color) : Color.Background;

                    Color scolor = specular > 0 ? Color.Times((float)Math.Pow(specular, thing.Surface.Roughness), light.Color) : Color.Background;

                    var diffuseSurfaceColor = thing.Surface.Diffuse(pos);
                    var specularSurfaceColor = thing.Surface.Specular(pos);

                    ret.R += diffuseSurfaceColor.R * lcolor.R + specularSurfaceColor.R * scolor.R;
                    ret.G += diffuseSurfaceColor.G * lcolor.G + specularSurfaceColor.G * scolor.G;
                    ret.B += diffuseSurfaceColor.B * lcolor.B + specularSurfaceColor.B * scolor.B;

                }
            }
            return ret;
        }
Пример #25
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);
        }
Пример #26
0
        private float TestRay(Ray ray, Scene scene)
        {
            float d = float.MaxValue;

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

                float intersectionDistance = thing.IntersectDistance(ray);

                if (intersectionDistance < d)
                {
                    d = intersectionDistance;
                }
            }

            return d == float.MaxValue ? 0 : d;
        }
Пример #27
0
        private void SetupScene(int width, int height)
        {
            //Vector3D bunnyCenter = loadedPlyFile.GetScanAsSpheres().GetAxisAlignedBoundingBox().Center;

            scene = new RayTracer.Scene();
            scene.camera = new RayTracer.Camera(width, height, MathHelper.DegreesToRadians(40));
            scene.background = new RayTracer.Background(new RGBA_Floats(0.5, .5, .5), 0.4);
            
            //AddBoxAndSheresBooleanTest();
            //AddBoxAndBoxBooleanTest();
#if false
            renderCollection.Add(new BoxShape(new Vector3(), new Vector3(1, 1, 1),
                               new SolidMaterial(new RGBA_Floats(.9, .2, .1), .01, 0.0, 2.0)));
            renderCollection.Add(new BoxShape(new Vector3(.5,.5,.5), new Vector3(1.5, 1.5, 1.5),
                               new SolidMaterial(new RGBA_Floats(.9, .2, .1), .01, 0.0, 2.0)));
#endif
            //renderCollection.Add(new CylinderShape(.25, 1, new SolidMaterial(RGBA_Floats.Cyan, 0, 0, 0)));

            //AddSphereAndBox();
            //AddAxisMarker();
            //AddCubeOfShperes();

            renderCollection.Add(MakerGearXCariage());

            allObjects = BoundingVolumeHierarchy.CreateNewHierachy(renderCollection);
            trackBallTransform = new Transform(allObjects);
            //allObjects = root;
            scene.shapes.Add(trackBallTransform);

            //AddAFloor();

            //add two lights for better lighting effects
            scene.lights.Add(new Light(new Vector3(50, -10, 100), new RGBA_Floats(0.8, 0.8, 0.8)));
            scene.lights.Add(new Light(new Vector3(-30, -150, 50), new RGBA_Floats(0.8, 0.8, 0.8)));

            OrientCamera();
        }
Пример #28
0
        private Color TraceRay(Ray ray, Scene scene, int depth)
        {
            var i = ClosestIntersection(ray, scene);

            if (i == null)
            {
                return Color.Background;
            }

            return Shade(i, scene, depth);
        }
Пример #29
0
        /// <summary>
        /// Renders the given scene to a bitmap, using one thread per line of pixels in the image.
        /// </summary>
        /// <param name="scene">The scene to render</param>
        /// <returns>A bitmap of the rendered scene.</returns>
        public void RenderSceneToBitmapThreaded(Scene scene, RenderBuffer renderBuffer, int width = -1, int height = -1)
        {
            if (width == -1 || height == -1)
            {
                width = renderSize.Width;
                height = renderSize.Height;
            }
            else
            {
                renderSize = new Size(width, height);
            }

            var before = DateTime.UtcNow;

            List<Task> tasks = new List<Task>();

            for (int yCounter = height - 1; yCounter >= 0; yCounter--)
            {
                var y = yCounter;
                var task = Task.Run(() =>
                    {
                        for (int xCounter = 0; xCounter < width; xCounter++)
                        {
                            var x = xCounter;
                            var viewPortX = ((2 * x) / (float)width) - 1;
                            var viewPortY = ((2 * y) / (float)height) - 1;
                            var color = TraceRayAgainstScene(GetRay(viewPortX, viewPortY), scene);
                            renderBuffer.SetColor(x, height - y - 1, ref color);
                        }
                    });

                tasks.Add(task);
            }

            Task.WhenAll(tasks).Wait();
            var after = DateTime.UtcNow;
            System.Diagnostics.Debug.WriteLine("Total render time: " + (after - before).TotalMilliseconds + " ms");
        }
Пример #30
0
        internal unsafe void Render(Scene scene)
        {
            // TODO:    use more here? need to be height % processorCount == 0.
            //int processorCount = Environment.ProcessorCount;
            int processorCount = 12;
            ScanlineTask[] scanLineTasks = new ScanlineTask[processorCount];
            int numRowsPerTask = screenHeight / processorCount;
            CountdownEvent countEvent = new CountdownEvent(processorCount);
            int pitch = numRowsPerTask * screenWidth * 4;
            int currentY = 0;
            int offset = 0;

            for (int i = 0; i < processorCount; i++)
            {
                scanLineTasks[i] = new ScanlineTask(i == processorCount - 1, screenWidth, numRowsPerTask, currentY, scanlines + offset, countEvent, (x, y) => TraceRay(new Ray()
                {
                    Start = scene.Camera.Pos,
                    Dir = GetPoint(x, y, scene.Camera)
                }, scene, 0)
                );

                currentY += numRowsPerTask;
                offset += pitch;
            }

            for (int i = 0; i < processorCount; i++)
            {
                scanLineTasks[i].Start();
            }

            //Stopwatch t = Stopwatch.StartNew();
            countEvent.Wait();
            //t.Stop();
            //Console.WriteLine("wait " + t.ElapsedMilliseconds);
        }
Пример #31
0
        /// <summary>
        /// Renders the given scene in a background thread. Uses a single thread for rendering.
        /// </summary>
        /// <param name="scene">The scene to render</param>
        /// <returns>A bitmap of the rendered scene.</returns>
        public async Task<Bitmap> RenderSceneToBitmap(Scene scene, int width = -1, int height = -1)
        {
            if (width == -1 || height == -1)
            {
                width = renderSize.Width;
                height = renderSize.Height;
            }
            else
            {
                renderSize = new Size(width, height);
            }

            var before = DateTime.UtcNow;

            Bitmap bitmap = new Bitmap(width, height);

            var task = Task.Run(() =>
                {

                    for (int x = 0; x < width; x++)
                    {
                        for (int y = 0; y < height; y++)
                        {
                            var viewPortX = ((2 * x) / (float)width) - 1;
                            var viewPortY = ((2 * y) / (float)height) - 1;
                            var color = TraceRayAgainstScene(GetRay(viewPortX, viewPortY), scene);
                            bitmap.SetPixel(x, height - y - 1, color);
                        }
                    }
                });

            await task;

            var after = DateTime.UtcNow;
            System.Diagnostics.Debug.WriteLine("Total render time: " + (after - before).TotalMilliseconds + " ms");
            return bitmap;
        }
Пример #32
0
 internal void Render(Scene scene)
 {
     for (int y = 0; y < screenHeight; y++)
     {
         for (int x = 0; x < screenWidth; x++)
         {
             Color color = TraceRay(new Ray() { Start = scene.Camera.Pos, Dir = GetPoint(x, y, scene.Camera) }, scene, 0);
             setPixel(x, y, color.ToDrawingColor());
         }
     }
 }
Пример #33
0
        /// <summary>
        /// Renders the given scene, providing a callback for each individual line rendered. Uses a single background thread.
        /// </summary>
        /// <param name="width">The width of the rendered image</param>
        /// <param name="height">The height of the rendered image</param>
        /// <param name="scene">The scene to render</param>
        /// <param name="callback">The delegate invoked when a thread completes rendering a line</param>
        public void RenderSceneLines(Scene scene, int width, int height, LineFinishedHandler callback)
        {
            if (width == -1 || height == -1)
            {
                width = renderSize.Width;
                height = renderSize.Height;
            }
            else
            {
                renderSize = new Size(width, height);
            }

            var before = DateTime.UtcNow;

            Task.Run(() => // Even single-threaded method should run in the background to avoid freezing UI.
                {
                    for (int y = height - 1; y >= 0; y--)
                    {
                        var colors = new Color[width];
                        for (int x = 0; x < width; x++)
                        {
                            var viewPortX = ((2 * x) / (float)width) - 1;
                            var viewPortY = ((2 * y) / (float)height) - 1;
                            var color = TraceRayAgainstScene(GetRay(viewPortX, viewPortY), scene);
                            colors[x] = color;
                        }
                        callback(y, colors);
                    }
                });
            var after = DateTime.UtcNow;
            System.Diagnostics.Debug.WriteLine("Total render time: " + (after - before).TotalMilliseconds + " ms");
        }
Пример #34
0
 private Color GetNaturalColor(SceneObject thing, Vector pos, Vector norm, Vector rd, Scene scene)
 {
     Color ret = Color.Make(0, 0, 0);
     foreach (Light light in scene.Lights) {
         Vector ldis = Vector.Minus(light.Pos, pos);
         Vector livec = Vector.Norm(ldis);
         double neatIsect = TestRay(new Ray() { Start = pos, Dir = livec }, scene);
         bool isInShadow = !((neatIsect > Vector.Mag(ldis)) || (neatIsect == 0));
         if (!isInShadow) {
             double illum = Vector.Dot(livec, norm);
             Color lcolor = illum > 0 ? Color.Times(illum, light.Color) : Color.Make(0, 0, 0);
             double specular = Vector.Dot(livec, Vector.Norm(rd));
             Color scolor = specular > 0 ? Color.Times(Math.Pow(specular, thing.Surface.Roughness), light.Color) : Color.Make(0, 0, 0);
             ret = Color.Plus(ret, Color.Plus(Color.Times(thing.Surface.Diffuse(pos), lcolor),
                                              Color.Times(thing.Surface.Specular(pos), scolor)));
         }
     }
     return ret;
 }
Пример #35
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;
        }
Пример #36
0
 private Color GetReflectionColor(SceneObject thing, Vector pos, Vector norm, Vector rd, Scene scene, int depth)
 {
     return Color.Times(thing.Surface.Reflect(pos), TraceRay(new Ray() { Start = pos, Dir = rd }, scene, depth + 1));
 }
Пример #37
0
        /// <summary>
        /// Renders the given scene to a bitmap, using one thread per line of pixels in the image.
        /// </summary>
        /// <param name="scene">The scene to render</param>
        /// <returns>A bitmap of the rendered scene.</returns>
        public async Task<Bitmap> RenderSceneToBitmapThreaded(Scene scene, int width = -1, int height = -1)
        {
            if (width == -1 || height == -1)
            {
                width = renderSize.Width;
                height = renderSize.Height;
            }
            else
            {
                renderSize = new Size(width, height);
            }

            var before = DateTime.UtcNow;
            Bitmap bitmap = new Bitmap(width, height);

            List<Task> tasks = new List<Task>();

            Color[,] colors = new Color[width, height];

            for (int xCounter = 0; xCounter < width; xCounter++)
            {
                var x = xCounter;
                var task = Task.Run(() =>
                    {
                        for (int yCounter = 0; yCounter < height; yCounter++)
                        {
                            var y = yCounter;
                            var viewPortX = ((2 * x) / (float)width) - 1;
                            var viewPortY = ((2 * y) / (float)height) - 1;
                            var color = TraceRayAgainstScene(GetRay(viewPortX, viewPortY), scene);
                            colors[x, y] = color;
                        }
                    });

                tasks.Add(task);
            }

            await Task.WhenAll(tasks);

            // Copy all pixel data into bitmap.
            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    bitmap.SetPixel(x, height - y - 1, colors[x, y]);
                }
            }

            var after = DateTime.UtcNow;
            System.Diagnostics.Debug.WriteLine("Total render time: " + (after - before).TotalMilliseconds + " ms");
            return bitmap;
        }
Пример #38
0
 private void OnSceneButtonClicked(Scene scene)
 {
     this.scene = scene;
     this.scene.Camera.FieldOfView = this.FieldOfView;
     this.scene.Camera.ReflectionDepth = this.ReflectionDepth;
 }