public void Writing_pixels_to_a_canvas()
        {
            var canvas = new MutableCanvas(10, 20);

            canvas.SetPixel(2, 3, Colors.Red);
            canvas.GetPixel(2, 3).Should().Be(Colors.Red);
        }
예제 #2
0
        //// ===========================================================================================================
        //// Methods
        //// ===========================================================================================================

        protected override Canvas Render(CameraRenderOptions options)
        {
            var start      = new Point(0, 1, 0);
            var velocity   = new Vector(1, 1.8, 0).Normalize() * 11.25;
            var cannonball = new Projectile(start, velocity);

            // gravity is -0.1 unit/tick and wind is -0.01 unit/tick
            var gravity     = new Vector(0, -0.1, 0);
            var wind        = new Vector(-0.01, 0, 0);
            var environment = new Environment(gravity, wind);

            var       color           = Colors.Magenta;
            const int pixelBorderSize = 2;

            var canvas = new MutableCanvas(CanvasWidth, CanvasHeight);

            while (cannonball.Position.Y > 0)
            {
                cannonball = Tick(environment, cannonball);
                int pointX = (int)Math.Round(cannonball.Position.X);
                int pointY = (int)Math.Round(canvas.Height - cannonball.Position.Y);
                canvas.FillRect(
                    top: pointY - pixelBorderSize,
                    left: pointX - pixelBorderSize,
                    bottom: pointY + pixelBorderSize,
                    right: pointX + pixelBorderSize,
                    color);
            }

            return(canvas.ToImmutable());
        }
예제 #3
0
        protected override Canvas Render(CameraRenderOptions options)
        {
            var canvas = new MutableCanvas(CanvasWidth, CanvasHeight);

            int    centerX     = canvas.Width / 2;
            int    centerY     = canvas.Height / 2;
            double clockRadius = Math.Min(canvas.Width * (3d / 8), canvas.Height * (3d / 8));

            var       color           = Colors.Cyan;
            const int pixelBorderSize = 4;

            // The clock is oriented along the y axis, which means when looking at it face-on you're looking
            // towards the negative y axis and the clock face sits on the x-z plane.
            var          twelve        = new Point(0, 0, 1);
            const double rotationAngle = (2 * Math.PI) / 12;

            for (int hour = 0; hour < 12; hour++)
            {
                // Rotate the twelve point around the y axis.
                // Scale by the clock radius.
                // Translate to the center of the canvas.
                var   transform = Matrix4x4.CreateRotationY(hour * rotationAngle);
                Point hourPoint = transform * twelve;
                int   x         = centerX + (int)Math.Round(hourPoint.X * clockRadius);
                int   y         = centerY - (int)Math.Round(hourPoint.Z * clockRadius);
                canvas.FillRect(
                    top: y - pixelBorderSize,
                    left: x - pixelBorderSize,
                    bottom: y + pixelBorderSize,
                    right: x + pixelBorderSize,
                    color);
            }

            return(canvas.ToImmutable());
        }
        protected override Canvas Render(CameraRenderOptions options)
        {
            var canvas = new MutableCanvas(CanvasWidth, CanvasHeight);

            var sphere = new Sphere();

            var          rayOrigin = new Point(0, 0, -5);
            const double wallZ     = 10;
            const double wallSize  = 7.0;

            double       pixelSize    = wallSize / canvas.Width;
            const double halfWallSize = wallSize / 2;
            double       totalPixels  = canvas.Width * canvas.Height;

            // For each row of pixels in the canvas...
            for (int y = 0; y < canvas.Height; y++)
            {
                // Compute the world y coordinate (top = +half, bottom = -half).
                double worldY = halfWallSize - (pixelSize * y);

                // For each pixel in the row...
                for (int x = 0; x < canvas.Width; x++)
                {
                    // See if we should stop.
                    if (options.CancellationToken.IsCancellationRequested)
                    {
                        return(canvas.ToImmutable());
                    }

                    // Compute the world x coordinate (left = -half, right = +half).
                    double worldX = -halfWallSize + (pixelSize * x);

                    // Describe the point on the wall that the ray will target.
                    var position = new Point(worldX, worldY, wallZ);

                    // Cast the ray into the scene to see what it hits.
                    var ray           = new Ray(rayOrigin, (position - rayOrigin).Normalize());
                    var intersections = sphere.Intersect(ray);

                    if (intersections.Hit != null)
                    {
                        canvas.SetPixel(x, y, Colors.Red);
                    }
                }

                // Report the progress.
                double pixelsRendered  = (y * CanvasWidth) + CanvasWidth;
                int    percentComplete = (int)Math.Round((pixelsRendered / totalPixels) * 100.0);
                options.Progress?.Report(new RenderProgressStep(percentComplete, y, canvas.GetRow(y)));
            }

            return(canvas.ToImmutable());
        }
        public void Creating_a_canvas()
        {
            var canvas = new MutableCanvas(10, 20);

            canvas.Width.Should().Be(10);
            canvas.Height.Should().Be(20);

            for (int y = 0; y < 20; y++)
            {
                for (int x = 0; x < 10; x++)
                {
                    canvas.GetPixel(x, y).Should().Be(Colors.Black);
                }
            }
        }
        protected override Canvas Render(CameraRenderOptions options)
        {
            var canvas = new MutableCanvas(CanvasWidth, CanvasHeight);

            var sphere        = new Sphere(material: new Material(new Color(1, 0.2, 1)));
            var lightPosition = new Point(-10, 10, -10);
            var lightColor    = Colors.White;
            var light         = new PointLight(lightPosition, lightColor);

            var          rayOrigin = new Point(0, 0, -5);
            const int    wallZ     = 10;
            const double wallSize  = 7.0;

            double       pixelSize    = wallSize / canvas.Width;
            const double halfWallSize = wallSize / 2;
            double       totalPixels  = canvas.Width * canvas.Height;

            // For each row of pixels in the canvas...
            for (int y = 0; y < canvas.Height; y++)
            {
                // Compute the world y coordinate (top = +half, bottom = -half).
                double worldY = halfWallSize - (pixelSize * y);

                // For each pixel in the row...
                for (int x = 0; x < canvas.Width; x++)
                {
                    // See if we should stop.
                    if (options.CancellationToken.IsCancellationRequested)
                    {
                        return(canvas.ToImmutable());
                    }

                    // Compute the world x coordinate (left = -half, right = +half).
                    double worldX = -halfWallSize + (pixelSize * x);

                    // Describe the point on the wall that the ray will target.
                    var position = new Point(worldX, worldY, wallZ);

                    // Cast the ray into the scene to see what it hits.
                    var ray = new Ray(rayOrigin, (position - rayOrigin).Normalize());
                    IntersectionList intersections = sphere.Intersect(ray);
                    Intersection?    hit           = intersections.Hit;

                    if (hit != null)
                    {
                        Point  point  = ray.PositionAt(hit.T);
                        Vector normal = hit.Shape.NormalAt(point);
                        Vector eye    = ray.Direction.Negate();
                        Color  color  = hit.Shape.Material.CalculateLighting(hit.Shape, light, point, eye, normal, false);
                        canvas.SetPixel(x, y, color);
                    }
                }

                // Report the progress.
                double pixelsRendered  = (y * CanvasWidth) + CanvasWidth;
                int    percentComplete = (int)Math.Round((pixelsRendered / totalPixels) * 100.0);
                options.Progress?.Report(new RenderProgressStep(percentComplete, y, canvas.GetRow(y)));
            }

            return(canvas.ToImmutable());
        }