Ejemplo n.º 1
0
        //// ===========================================================================================================
        //// Methods
        //// ===========================================================================================================

        public async Task <BitmapSource> RenderAsync(
            double dpiX,
            double dpiY,
            int maxDegreeOfParallelism = -1,
            IProgress <SceneRenderProgress>?progress = null,
            CancellationToken cancellationToken      = default)
        {
            _progress = progress;
            _bitmap   = new WriteableBitmap(CanvasWidth, CanvasHeight, dpiX, dpiY, PixelFormats.Bgr24, null);

            try
            {
                // Render the scene.
                var    renderProgress = new Progress <RenderProgressStep>(OnRenderProgress);
                var    options        = new CameraRenderOptions(maxDegreeOfParallelism, renderProgress, cancellationToken);
                Canvas canvas         = await Task.Run(() => Render(options), cancellationToken);

                canvas.RenderToWriteableBitmap(_bitmap);
                ReportProgress(100);

                return(_bitmap);
            }
            finally
            {
                _progress = null;
                _bitmap   = null;
            }
        }
        protected override Canvas Render(CameraRenderOptions options)
        {
            var floor = new Plane(material: new Material(new Color(1, 0.9, 0.9)).WithSpecular(0));

            var middle = new Sphere(
                "Middle",
                Matrix4x4.CreateTranslation(-0.5, 1, 0.5),
                new Material(new Color(0.1, 1, 0.5), diffuse: 0.7, specular: 0.3)

                );

            var right = new Sphere(
                "Right",
                Matrix4x4.CreateScaling(0.5, 0.5, 0.5).Translate(1.5, 0.5, -0.5),
                new Material(new Color(0.5, 1, 0.1), diffuse: 0.7, specular: 0.3)

                );

            var left = new Sphere(
                "Left",
                Matrix4x4.CreateScaling(0.33, 0.33, 0.33).Translate(-1.5, 0.33, -0.75),
                new Material(new Color(1, 0.8, 0.1), diffuse: 0.7, specular: 0.3)

                );

            var light = new PointLight(new Point(-10, 10, -10), Colors.White);
            var world = new World(light, floor, middle, right, left);

            var cameraTransform = Matrix4x4.CreateLookAt(new Point(0, 1.5, -5), new Point(0, 1, 0), Vector.UnitY);
            var camera          = new Camera(CanvasWidth, CanvasHeight, Math.PI / 3, cameraTransform);

            Canvas canvas = camera.Render(world, options);

            return(canvas);
        }
        protected override Canvas Render(CameraRenderOptions options)
        {
            // Floor
            var floor = new Plane(
                transform: Matrix4x4.CreateTranslation(0, -NumberExtensions.Epsilon, 0),
                material: new Material(
                    pattern: new CheckerPattern(
                        Colors.Gray,
                        Colors.DarkGray,
                        Matrix4x4.CreateScaling(0.25, 0.25, 0.25)),
                    ambient: 0.2,
                    diffuse: 0.9,
                    specular: 0));

            var pyramid = CreatePyramid();

            pyramid.Material = new Material(Colors.Yellow, ambient: 0.2, diffuse: 0.9, specular: 0);

            // Lights, camera, action.
            var light = new PointLight(new Point(1, 7, -5), Colors.White);
            var world = new World(light, floor, pyramid);

            var cameraTransform = Matrix4x4.CreateLookAt(new Point(0, 3.5, -9), new Point(0, 0.3, 0), Vector.UnitY);
            var camera          = new Camera(CanvasWidth, CanvasHeight, fieldOfView: 0.314, cameraTransform);

            Canvas canvas = camera.Render(world, options);

            return(canvas);
        }
Ejemplo n.º 4
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());
        }
Ejemplo n.º 5
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());
        }
Ejemplo n.º 6
0
        protected override Canvas Render(CameraRenderOptions options)
        {
            // Patterns
            var checkerPattern = new PerturbedPattern(new CheckerPattern(new Color(0.8, 1, 0.8), Colors.Green));

            var stripePattern = new PerturbedPattern(
                new StripePattern(
                    Colors.Blue,
                    new Color(0.8, 0.8, 1),
                    Matrix4x4.CreateScaling(0.25, 0.25, 0.25)
                    .RotateZ(-Math.PI / 4)
                    .RotateY(-Math.PI / 6)
                    .Translate(0.4, 0, 0)));

            var gradientPattern = new PerturbedPattern(
                new RadialGradientPattern(
                    Colors.Green,
                    Colors.Yellow,
                    Matrix4x4.CreateScaling(0.25, 0.25, 0.25).RotateX(-Math.PI / 2)));

            var ringPattern = new PerturbedPattern(
                new RingPattern(
                    Colors.Red,
                    Colors.White,
                    Matrix4x4.CreateScaling(0.15, 0.15, 0.15).RotateX(-Math.PI / 2)));

            // Shapes
            var floor = new Plane(
                "Floor",
                Matrix4x4.CreateRotationY(Math.PI / 4),
                new Material(pattern: checkerPattern, specular: 0));

            var left = new Sphere(
                "Left",
                Matrix4x4.CreateScaling(0.33, 0.33, 0.33).Translate(-2, 0.33, -0.75),
                new Material(pattern: ringPattern, diffuse: 0.7, specular: 0.3));

            var middle = new Sphere(
                "Middle",
                Matrix4x4.CreateTranslation(-0.5, 1, 0.5),
                new Material(pattern: stripePattern, diffuse: 0.7, specular: 0.3));

            var right = new Sphere(
                "Right",
                Matrix4x4.CreateScaling(0.5, 0.5, 0.5).Translate(1.5, 0.5, -0.5),
                new Material(pattern: gradientPattern, diffuse: 0.7, specular: 0.3));

            var light = new PointLight(new Point(-10, 10, -10), Colors.White);
            var world = new World(light, floor, left, middle, right);

            var cameraTransform = Matrix4x4.CreateLookAt(new Point(0, 1.5, -5), new Point(0, 1, 0), Vector.UnitY);
            var camera          = new Camera(CanvasWidth, CanvasHeight, Math.PI / 3, cameraTransform);

            Canvas canvas = camera.Render(world, options);

            return(canvas);
        }
        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());
        }
Ejemplo n.º 8
0
        protected override Canvas Render(CameraRenderOptions options)
        {
            var sphereMaterial = new Material(ambient: 0.2, diffuse: 0.8, specular: 0.3, shininess: 200);
            var wristMaterial  = sphereMaterial.WithColor(new Color(0.1, 1, 1));
            var palmMaterial   = sphereMaterial.WithColor(new Color(0.1, 0.1, 1));
            var thumbMaterial  = palmMaterial;
            var indexMaterial  = sphereMaterial.WithColor(new Color(1, 1, 0.1));
            var middleMaterial = sphereMaterial.WithColor(new Color(0.1, 1, 0.5));
            var ringMaterial   = sphereMaterial.WithColor(new Color(0.1, 1, 0.1));
            var pinkyMaterial  = sphereMaterial.WithColor(new Color(0.1, 0.5, 1));

            var backdrop = new Sphere(
                "Backdrop",
                Matrix4x4.CreateScaling(200, 200, 0.01).Translate(0, 0, 20),
                new Material(Colors.White, ambient: 0, diffuse: 0.5, specular: 0));

            var wrist = new Sphere(
                "Wrist",
                Matrix4x4.CreateScaling(3, 3, 3).Translate(-4, 0, -21).RotateZ(Math.PI / 4),
                wristMaterial);
            var palm   = new Sphere("Palm", Matrix4x4.CreateScaling(4, 3, 3).Translate(0, 0, -15), palmMaterial);
            var thumb  = new Sphere("Thumb", Matrix4x4.CreateScaling(1, 3, 1).Translate(-2, 2, -16), thumbMaterial);
            var index  = new Sphere("Index", Matrix4x4.CreateScaling(3, 0.75, 0.75).Translate(3, 2, -22), indexMaterial);
            var middle = new Sphere(
                "Middle",
                Matrix4x4.CreateScaling(3, 0.75, 0.75).Translate(4, 1, -19),
                middleMaterial);
            var ring  = new Sphere("Ring", Matrix4x4.CreateScaling(3, 0.75, 0.75).Translate(4, 0, -18), ringMaterial);
            var pinky = new Sphere(
                "Pinky",
                Matrix4x4.CreateScaling(2.5, 0.6, 0.6)
                .Translate(1, 0, 0)
                .RotateZ(Math.PI / 10)
                .Translate(3, -1.5, -20),
                pinkyMaterial);

            var light = new PointLight(new Point(0, 0, -100), Colors.White);
            var world = new World(light, backdrop, wrist, palm, thumb, index, middle, ring, pinky);

            var cameraTransform = Matrix4x4.CreateLookAt(new Point(40, 0, -70), new Point(0, 0, -5), Vector.UnitY);
            var camera          = new Camera(CanvasWidth, CanvasHeight, 0.524, cameraTransform);

            Canvas canvas = camera.Render(world, options);

            return(canvas);
        }
Ejemplo n.º 9
0
        protected override Canvas Render(CameraRenderOptions options)
        {
            // Shapes
            var backdrop = new Plane(
                "Backdrop",
                Matrix4x4.CreateRotationX(Math.PI / 2).Translate(0, 0, 100),
                new Material(Colors.White, ambient: 1, diffuse: 0, specular: 0));

            var ufo1 = CreateUfo()
                       .ChangeTransform(Matrix4x4.CreateRotationY(0.1745).RotateX(0.4363).Translate(-2.8, 0, 0))
                       .ChangeMaterial(
                new Material(new Color(0.9, 0.2, 0.4), ambient: 0.2, diffuse: 0.8, specular: 0.7, shininess: 20));

            var ufo2 = CreateUfo()
                       .ChangeTransform(Matrix4x4.CreateRotationY(0.1745))
                       .ChangeMaterial(
                new Material(new Color(0.2, 0.9, 0.6), ambient: 0.2, diffuse: 0.8, specular: 0.7, shininess: 20));

            var ufo3 = CreateUfo()
                       .ChangeTransform(Matrix4x4.CreateRotationY(-0.1745).RotateX(-0.4363).Translate(2.8, 0, 0))
                       .ChangeMaterial(
                new Material(new Color(0.2, 0.3, 1), ambient: 0.2, diffuse: 0.8, specular: 0.7, shininess: 20));

            // Lights
            var light1 = new PointLight(new Point(10_000, 10_000, -10_000), Colors.DarkGray);
            var light2 = new PointLight(new Point(-10_000, 10_000, -10_000), Colors.DarkGray);
            var light3 = new PointLight(new Point(10_000, -10_000, -10_000), Colors.DarkGray);
            var light4 = new PointLight(new Point(-10_000, -10_000, -10_000), Colors.DarkGray);

            // Create the world.
            var world = new World(new[] { light1, light2, light3, light4 }, new[] { backdrop, ufo1, ufo2, ufo3 });

            // Create the camera.
            var cameraTransform = Matrix4x4.CreateLookAt(new Point(0, 0, -9), new Point(0, 0, 0), Vector.UnitY);
            var camera          = new Camera(CanvasWidth, CanvasHeight, fieldOfView: 0.9, cameraTransform);

            Canvas canvas = camera.Render(world, options);

            return(canvas);
        }
Ejemplo n.º 10
0
        protected override Canvas Render(CameraRenderOptions options)
        {
            // Patterns
            var map1         = new ColorMap(new ColorMapEntry(0, Colors.White));
            var floorPattern = new PerlinPattern(map1, transform: Matrix4x4.CreateTranslation(-1000, 0, 0));

            // Shapes
            var floor = new Plane(
                "Floor",
                Matrix4x4.CreateRotationY(Math.PI / 4),
                new Material(pattern: floorPattern, specular: 0));

            var left = new Sphere(
                "Left",
                Matrix4x4.CreateScaling(0.33, 0.33, 0.33).Translate(-2, 0.33, -0.75),
                new Material(pattern: floorPattern, diffuse: 0.7, specular: 0.3));

            var middle = new Sphere(
                "Middle",
                Matrix4x4.CreateTranslation(-0.5, 1, 0.5),
                new Material(pattern: floorPattern, diffuse: 0.7, specular: 0.3));

            var right = new Sphere(
                "Right",
                Matrix4x4.CreateScaling(0.5, 0.5, 0.5).Translate(1.5, 0.5, -0.5),
                new Material(pattern: floorPattern, diffuse: 0.7, specular: 0.3));

            var light = new PointLight(new Point(-10, 10, -10), Colors.White);
            var world = new World(light, floor, left, middle, right);

            var cameraTransform = Matrix4x4.CreateLookAt(new Point(0, 1.5, -5), new Point(0, 1, 0), Vector.UnitY);
            var camera          = new Camera(CanvasWidth, CanvasHeight, Math.PI / 3, cameraTransform);

            Canvas canvas = camera.Render(world, options);

            return(canvas);
        }
Ejemplo n.º 11
0
        protected override Canvas Render(CameraRenderOptions options)
        {
            // Materials
            var wallMaterial = new Material(
                pattern: new StripePattern(
                    new Color(0.45, 0.45, 0.45),
                    new Color(0.55, 0.55, 0.55),
                    Matrix4x4.CreateScaling(0.25, 0.25, 0.25).RotateY(Math.PI / 2)),
                ambient: 0,
                diffuse: 0.4,
                specular: 0,
                reflective: 0.3);

            // Shapes
            var floor = new Plane(
                "Floor",
                Matrix4x4.CreateRotationY(0.31415),
                new Material(
                    pattern: new CheckerPattern(new Color(0.35, 0.35, 0.35), new Color(0.65, 0.65, 0.65)),
                    specular: 0,
                    reflective: 0.4));

            var ceiling = new Plane(
                "Ceiling",
                Matrix4x4.CreateTranslation(0, 5, 0),
                new Material(new Color(0.8, 0.8, 0.8), ambient: 0.3, specular: 0));

            var westWall = new Plane(
                "WestWall",
                Matrix4x4.CreateRotationY(Math.PI / 2).RotateZ(Math.PI / 2).Translate(-5, 0, 0),
                wallMaterial);

            var eastWall = new Plane(
                "EastWall",
                Matrix4x4.CreateRotationY(Math.PI / 2).RotateZ(Math.PI / 2).Translate(5, 0, 0),
                wallMaterial);

            var northWall = new Plane("NorthWall", Matrix4x4.CreateRotationX(Math.PI / 2).Translate(0, 0, 5), wallMaterial);
            var southWall = new Plane("SouthWall", Matrix4x4.CreateRotationX(Math.PI / 2).Translate(0, 0, -5), wallMaterial);

            // Background hexagons
            var backHex1 = new Hexagon(
                "BackHex1",
                Matrix4x4.CreateRotationX(Math.PI / 2).Scale(0.4, 0.4, 0.4).Translate(4.6, 0.5, 1),
                new Material(new Color(0.8, 0.5, 0.3), shininess: 50));

            var backHex2 = new Hexagon(
                "BackHex2",
                Matrix4x4.CreateRotationX(Math.PI / 2).Scale(0.3, 0.3, 0.3).Translate(4.7, 0.4, 0.4),
                new Material(new Color(0.9, 0.4, 0.5), shininess: 50));

            var backHex3 = new Hexagon(
                "BackHex3",
                Matrix4x4.CreateRotationX(Math.PI / 2).Scale(0.5, 0.5, 0.5).Translate(-1, 0.6, 4.5),
                new Material(new Color(0.4, 0.9, 0.6), shininess: 50));

            var backHex4 = new Hexagon(
                "BackHex4",
                Matrix4x4.CreateRotationX(Math.PI / 2).Scale(0.3, 0.3, 0.3).Translate(-1.7, 0.4, 4.7),
                new Material(new Color(0.4, 0.6, 0.9), shininess: 50));

            // Foreground hexagons
            var redHex = new Hexagon(
                "RedHex",
                Matrix4x4.CreateRotationX(-Math.PI / 4).Translate(-0.6, 1.2, 0.6),
                new Material(new Color(1, 0.3, 0.2), specular: 0.4, shininess: 5));

            var blueGlassHex = new Hexagon(
                "BlueGlassHex",
                Matrix4x4.CreateRotationX(-Math.PI / 3)
                .Scale(0.7, 0.7, 0.7)
                .Translate(0.6, 0.8, -0.6)
                .RotateY(Math.PI / 4),
                new Material(
                    new Color(0, 0, 0.2),
                    ambient: 0,
                    diffuse: 0.4,
                    specular: 0.9,
                    shininess: 300,
                    reflective: 0.9,
                    transparency: 0.9,
                    refractiveIndex: 1.5));

            var greenGlassHex = new Hexagon(
                "GreenGlassHex",
                Matrix4x4.CreateScaling(0.5, 0.5, 0.5).Translate(-0.7, 0.6, -0.8),
                new Material(
                    new Color(0, 0.2, 0),
                    ambient: 0,
                    diffuse: 0.4,
                    specular: 0.9,
                    shininess: 300,
                    reflective: 0.9,
                    transparency: 0.9,
                    refractiveIndex: 1.5));

            // Lights, camera, action.
            var light = new PointLight(new Point(-4.9, 4.9, -1), Colors.White);
            var world = new World(
                light,
                floor, ceiling, westWall, eastWall, northWall, southWall,
                backHex1, backHex2, backHex3, backHex4,
                redHex, blueGlassHex, greenGlassHex);

            var cameraTransform = Matrix4x4.CreateLookAt(
                new Point(-2.6, 1.5, -3.9),
                new Point(-0.6, 1, -0.8),
                Vector.UnitY);
            var camera = new Camera(CanvasWidth, CanvasHeight, fieldOfView: 1.152, cameraTransform);

            Canvas canvas = camera.Render(world, options);

            return(canvas);
        }
Ejemplo n.º 12
0
 protected override Canvas Render(CameraRenderOptions options)
 {
Ejemplo n.º 13
0
        protected override Canvas Render(CameraRenderOptions options)
        {
            // Shapes
            var floorCeiling = new Cube(
                "FloorCeiling",
                Matrix4x4.CreateTranslation(0, 1, 0).Scale(20, 7, 20),
                new Material(
                    pattern: new CheckerPattern(
                        Colors.Black,
                        Colors.DarkGray,
                        Matrix4x4.CreateScaling(0.07, 0.07, 0.07)),
                    ambient: 0.25,
                    diffuse: 0.7,
                    specular: 0.9,
                    shininess: 300,
                    reflective: 0.1));

            var walls = new Cube(
                "Walls",
                Matrix4x4.CreateScaling(10, 10, 10),
                new Material(
                    pattern: new CheckerPattern(
                        new Color(0.4863, 0.3765, 0.2941),
                        new Color(0.3725, 0.2902, 0.2275),
                        Matrix4x4.CreateScaling(0.05, 20, 0.05)),
                    ambient: 0.1,
                    diffuse: 0.7,
                    specular: 0.9,
                    shininess: 300,
                    reflective: 0.1));

            var csgUnion = new CsgShape(
                "Union",
                CsgOperation.Union,
                new Cube(
                    "YellowCube",
                    Matrix4x4.CreateTranslation(0, 1.5, 0),
                    new Material(Colors.Yellow, diffuse: 0.7, specular: 0.3)),
                new Sphere(
                    "RedSphere",
                    Matrix4x4.CreateTranslation(0.6, 2, -0.6),
                    new Material(Colors.Red, diffuse: 0.7, specular: 0.9)),
                transform: Matrix4x4.CreateRotationY(-Math.PI / 3).Translate(-4, 0, -2));

            var csgIntersection = new CsgShape(
                "Intersection",
                CsgOperation.Intersection,
                new Cube(
                    "YellowCube",
                    Matrix4x4.CreateTranslation(0, 1.5, 0),
                    new Material(Colors.Yellow, diffuse: 0.7, specular: 0.3)),
                new Sphere(
                    "RedSphere",
                    Matrix4x4.CreateTranslation(0.6, 2, -0.6),
                    new Material(Colors.Red, diffuse: 0.7, specular: 0.9)),
                transform: Matrix4x4.CreateRotationY(-Math.PI / 2).Translate(0, 0, -2));

            var csgDifference = new CsgShape(
                "Difference",
                CsgOperation.Difference,
                new Cube(
                    "YellowCube",
                    Matrix4x4.CreateTranslation(0, 1.5, 0),
                    new Material(Colors.Yellow, diffuse: 0.7, specular: 0.3)),
                new Sphere(
                    "RedSphere",
                    Matrix4x4.CreateTranslation(0.6, 2, -0.6),
                    new Material(Colors.Red, diffuse: 0.7, specular: 0)),
                transform: Matrix4x4.CreateRotationY(-Math.PI / 6).Translate(3, 0, 2));

            // Lights, camera, action.
            var light = new PointLight(new Point(8, 8, -5), Colors.White);
            var world = new World(light, floorCeiling, walls, csgUnion, csgIntersection, csgDifference);

            var cameraTransform = Matrix4x4.CreateLookAt(new Point(8, 6, -8), new Point(0, 3, 0), Vector.UnitY);
            var camera          = new Camera(CanvasWidth, CanvasHeight, fieldOfView: 0.785, cameraTransform);

            Canvas canvas = camera.Render(world, options);

            return(canvas);
        }
        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());
        }
Ejemplo n.º 15
0
        protected override Canvas Render(CameraRenderOptions options)
        {
            var floor = new Sphere(
                "Floor",
                Matrix4x4.CreateScaling(10, 0.01, 10),
                new Material(new Color(1, 0.9, 0.9)).WithSpecular(0));

            var leftWall = new Sphere(
                "LeftWall",
                Matrix4x4.CreateScaling(10, 0.01, 10)
                .RotateX(Math.PI / 2)
                .RotateY(-Math.PI / 4)
                .Translate(0, 0, 5),
                floor.Material

                );

            var rightWall = new Sphere(
                "RightWall",
                Matrix4x4.CreateScaling(10, 0.01, 10)
                .RotateX(Math.PI / 2)
                .RotateY(Math.PI / 4)
                .Translate(0, 0, 5),
                floor.Material

                );

            var middle = new Sphere(
                "Middle",
                Matrix4x4.CreateTranslation(-0.5, 1, 0.5),
                new Material(new Color(0.1, 1, 0.5), diffuse: 0.7, specular: 0.3)

                );

            var right = new Sphere(
                "Right",
                Matrix4x4.CreateScaling(0.5, 0.5, 0.5).Translate(1.5, 0.5, -0.5),
                new Material(new Color(0.5, 1, 0.1), diffuse: 0.7, specular: 0.3)

                );

            var left = new Sphere(
                "Left",
                Matrix4x4.CreateScaling(0.33, 0.33, 0.33).Translate(-1.5, 0.33, -0.75),
                new Material(new Color(1, 0.8, 0.1), diffuse: 0.7, specular: 0.3)

                );

            var light1 = new PointLight(new Point(-10, 10, -10), Colors.White);
            var light2 = new PointLight(new Point(0, 10, -10), Colors.DarkGray);
            var light3 = new PointLight(new Point(10, 10, -10), Colors.DarkGray);

            var world = new World(
                new[] { light1, light2, light3 },
                new[] { floor, leftWall, rightWall, middle, right, left });

            var cameraTransform = Matrix4x4.CreateLookAt(new Point(0, 1.5, -5), new Point(0, 1, 0), Vector.UnitY);
            var camera          = new Camera(CanvasWidth, CanvasHeight, Math.PI / 3, cameraTransform);

            Canvas canvas = camera.Render(world, options);

            return(canvas);
        }
Ejemplo n.º 16
0
        protected override Canvas Render(CameraRenderOptions options)
        {
            // Colors
            var tableLegColor = new Color(0.5529, 0.4235, 0.3255);

            // Shapes
            var floorCeiling = new Cube(
                "FloorCeiling",
                Matrix4x4.CreateTranslation(0, 1, 0).Scale(20, 7, 20),
                new Material(
                    pattern: new CheckerPattern(
                        Colors.Black,
                        Colors.DarkGray,
                        Matrix4x4.CreateScaling(0.07, 0.07, 0.07)),
                    ambient: 0.25,
                    diffuse: 0.7,
                    specular: 0.9,
                    shininess: 300,
                    reflective: 0.1));

            var walls = new Cube(
                "Walls",
                Matrix4x4.CreateScaling(10, 10, 10),
                new Material(
                    pattern: new CheckerPattern(
                        new Color(0.4863, 0.3765, 0.2941),
                        new Color(0.3725, 0.2902, 0.2275),
                        Matrix4x4.CreateScaling(0.05, 20, 0.05)),
                    ambient: 0.1,
                    diffuse: 0.7,
                    specular: 0.9,
                    shininess: 300,
                    reflective: 0.1));

            var tableTop = new Cube(
                "TableTop",
                Matrix4x4.CreateScaling(3, 0.1, 2).Translate(0, 3.1, 0),
                new Material(
                    pattern: new StripePattern(
                        tableLegColor,
                        new Color(0.6588, 0.5098, 0.4000),
                        Matrix4x4.CreateRotationY(0.1).Scale(0.05, 0.05, 0.05)),
                    ambient: 0.1,
                    diffuse: 0.7,
                    specular: 0.9,
                    shininess: 300,
                    reflective: 0.2));

            var leg1 = new Cube(
                "Leg1",
                Matrix4x4.CreateScaling(0.1, 1.5, 0.1).Translate(2.7, 1.5, -1.7),
                new Material(tableLegColor, ambient: 0.2, diffuse: 0.7));

            var leg2 = new Cube(
                "Leg2",
                Matrix4x4.CreateScaling(0.1, 1.5, 0.1).Translate(2.7, 1.5, 1.7),
                new Material(tableLegColor, ambient: 0.2, diffuse: 0.7));

            var leg3 = new Cube(
                "Leg3",
                Matrix4x4.CreateScaling(0.1, 1.5, 0.1).Translate(-2.7, 1.5, -1.7),
                new Material(tableLegColor, ambient: 0.2, diffuse: 0.7));

            var leg4 = new Cube(
                "Leg4",
                Matrix4x4.CreateScaling(0.1, 1.5, 0.1).Translate(-2.7, 1.5, 1.7),
                new Material(tableLegColor, ambient: 0.2, diffuse: 0.7));

            var glassCube = new Cube(
                "GlassCube",
                Matrix4x4.CreateScaling(0.25, 0.25, 0.25).RotateY(0.2).Translate(0, 3.45001, 0),
                new Material(
                    new Color(1, 1, 0.8),
                    ambient: 0,
                    diffuse: 0.3,
                    specular: 0.9,
                    shininess: 300,
                    reflective: 0.7,
                    transparency: 0.7,
                    refractiveIndex: 1.5))
            {
                IsShadowHidden = true
            };

            var littleCube1 = new Cube(
                "LittleCube1",
                Matrix4x4.CreateScaling(0.15, 0.15, 0.15).RotateY(-0.4).Translate(1, 3.35, -0.9),
                new Material(new Color(1, 0.5, 0.5), diffuse: 0.4, reflective: 0.6));

            var littleCube2 = new Cube(
                "LittleCube2",
                Matrix4x4.CreateScaling(0.15, 0.07, 0.15).RotateY(0.4).Translate(-1.5, 3.27, 0.3),
                new Material(new Color(1, 1, 0.5)));

            var littleCube3 = new Cube(
                "LittleCube3",
                Matrix4x4.CreateScaling(0.2, 0.05, 0.05).RotateY(0.4).Translate(0, 3.25, 1),
                new Material(new Color(0.5, 1, 0.5)));

            var littleCube4 = new Cube(
                "LittleCube4",
                Matrix4x4.CreateScaling(0.05, 0.2, 0.05).RotateY(0.8).Translate(-0.6, 3.4, -1),
                new Material(new Color(0.5, 0.5, 1)));

            var littleCube5 = new Cube(
                "LittleCube5",
                Matrix4x4.CreateScaling(0.05, 0.2, 0.05).RotateY(0.8).Translate(2, 3.4, 1),
                new Material(new Color(0.5, 1, 1)));

            var frame1 = new Cube(
                "Frame1",
                Matrix4x4.CreateScaling(0.05, 1, 1).Translate(-10, 4, 1),
                new Material(new Color(0.7098, 0.2471, 0.2196), diffuse: 0.6));

            var frame2 = new Cube(
                "Frame2",
                Matrix4x4.CreateScaling(0.05, 0.4, 0.4).Translate(-10, 3.4, 2.7),
                new Material(new Color(0.2667, 0.2706, 0.6902), diffuse: 0.6));

            var frame3 = new Cube(
                "Frame3",
                Matrix4x4.CreateScaling(0.05, 0.4, 0.4).Translate(-10, 4.6, 2.7),
                new Material(new Color(0.3098, 0.5961, 0.3098), diffuse: 0.6));

            var mirrorFrame = new Cube(
                "MirrorFrame",
                Matrix4x4.CreateScaling(5, 1.5, 0.05).Translate(-2, 3.5, 9.95),
                new Material(new Color(0.3882, 0.2627, 0.1882), diffuse: 0.7));

            var mirror = new Cube(
                "Mirror",
                Matrix4x4.CreateScaling(4.8, 1.4, 0.06).Translate(-2, 3.5, 9.95),
                new Material(Colors.Black, ambient: 0, diffuse: 0, specular: 1, shininess: 300, reflective: 1));

            // Lights, camera, action.
            var light = new PointLight(new Point(0, 6.9, -5), new Color(1, 1, 0.9));
            var world = new World(
                light,
                floorCeiling,
                walls,
                tableTop,
                leg1,
                leg2,
                leg3,
                leg4,
                glassCube,
                littleCube1,
                littleCube2,
                littleCube3,
                littleCube4,
                littleCube5,
                frame1,
                frame2,
                frame3,
                mirrorFrame,
                mirror);

            var cameraTransform = Matrix4x4.CreateLookAt(new Point(8, 6, -8), new Point(0, 3, 0), Vector.UnitY);
            var camera          = new Camera(CanvasWidth, CanvasHeight, fieldOfView: 0.785, cameraTransform);

            Canvas canvas = camera.Render(world, options);

            return(canvas);
        }
Ejemplo n.º 17
0
 protected abstract Canvas Render(CameraRenderOptions options);
Ejemplo n.º 18
0
        protected override Canvas Render(CameraRenderOptions options)
        {
            // Shapes
            var floor = new Plane(material: new Material(
                                      pattern: new CheckerPattern(
                                          Colors.Gray,
                                          Colors.DarkGray,
                                          Matrix4x4.CreateScaling(0.25, 0.25, 0.25).RotateY(0.3)),
                                      ambient: 0.2,
                                      diffuse: 0.9,
                                      specular: 0));

            var blueCylinder = new Cone(
                "BlueCylinder",
                minimumY: 0,
                maximumY: 0.75,
                isClosed: true,
                Matrix4x4.CreateScaling(0.5, 1, 0.5).Translate(-1, 0, 1),
                new Material(new Color(0, 0, 0.6), diffuse: 0.1, specular: 0.9, shininess: 300, reflective: 0.9));

            // Concentric Cylinders
            var outer = new Cone(
                minimumY: 0,
                maximumY: 0.2,
                transform: Matrix4x4.CreateScaling(0.8, 1, 0.8).Translate(1, 0, 0),
                material: new Material(
                    new Color(1, 1, 0.3),
                    ambient: 0.1,
                    diffuse: 0.8,
                    specular: 0.9,
                    shininess: 300));

            var middle = new Cone(
                minimumY: 0,
                maximumY: 0.3,
                transform: Matrix4x4.CreateScaling(0.6, 1, 0.6).Translate(1, 0, 0),
                material: new Material(
                    new Color(1, 0.9, 0.4),
                    ambient: 0.1,
                    diffuse: 0.8,
                    specular: 0.9,
                    shininess: 300));

            var inner = new Cone(
                minimumY: 0,
                maximumY: 0.4,
                transform: Matrix4x4.CreateScaling(0.4, 1, 0.4).Translate(1, 0, 0),
                material: new Material(
                    new Color(1, 0.8, 0.5),
                    ambient: 0.1,
                    diffuse: 0.8,
                    specular: 0.9,
                    shininess: 300));

            var solidInner = new Cone(
                minimumY: 0,
                maximumY: 0.5,
                isClosed: true,
                transform: Matrix4x4.CreateScaling(0.2, 1, 0.2).Translate(1, 0, 0),
                material: new Material(
                    new Color(1, 0.7, 0.6),
                    ambient: 0.1,
                    diffuse: 0.8,
                    specular: 0.9,
                    shininess: 300));

            // Decorative Cylinders
            var red = new Cone(
                minimumY: 0,
                maximumY: 0.3,
                isClosed: true,
                transform: Matrix4x4.CreateScaling(0.05, 1, 0.05).Translate(0, 0, -0.75),
                material: new Material(Colors.Red, ambient: 0.1, diffuse: 0.9, specular: 0.9, shininess: 300));

            var yellow = new Cone(
                minimumY: 0,
                maximumY: 0.3,
                isClosed: true,
                transform: Matrix4x4.CreateScaling(0.05, 1, 0.05)
                .Translate(0, 0, 1.5)
                .RotateY(-0.15)
                .Translate(0, 0, -2.25),
                material: new Material(Colors.Yellow, ambient: 0.1, diffuse: 0.9, specular: 0.9, shininess: 300));

            var green = new Cone(
                minimumY: 0,
                maximumY: 0.3,
                isClosed: true,
                transform: Matrix4x4.CreateScaling(0.05, 1, 0.05)
                .Translate(0, 0, 1.5)
                .RotateY(-0.3)
                .Translate(0, 0, -2.25),
                material: new Material(Colors.Green, ambient: 0.1, diffuse: 0.9, specular: 0.9, shininess: 300));

            var cyan = new Cone(
                minimumY: 0,
                maximumY: 0.3,
                isClosed: true,
                transform: Matrix4x4.CreateScaling(0.05, 1, 0.05)
                .Translate(0, 0, 1.5)
                .RotateY(-0.45)
                .Translate(0, 0, -2.25),
                material: new Material(Colors.Cyan, ambient: 0.1, diffuse: 0.9, specular: 0.9, shininess: 300));

            var glass = new Cone(
                minimumY: 0.0001,
                maximumY: 0.5,
                isClosed: true,
                transform: Matrix4x4.CreateScaling(0.33, 1, 0.33).Translate(0, 0, -1.5),
                material: new Material(
                    new Color(0.25, 0, 0),
                    diffuse: 0.1,
                    specular: 0.9,
                    shininess: 300,
                    reflective: 0.9,
                    transparency: 0.9,
                    refractiveIndex: 1.5));

            // Lights, camera, action.
            var light = new PointLight(new Point(1, 6.9, -4.9), Colors.White);
            var world = new World(light, floor, blueCylinder,
                                  outer, middle, inner, solidInner,
                                  red, yellow, green, cyan, glass);

            var cameraTransform = Matrix4x4.CreateLookAt(new Point(8, 3.5, -9), new Point(0, 0.3, 0), Vector.UnitY);
            var camera          = new Camera(CanvasWidth, CanvasHeight, fieldOfView: 0.314, cameraTransform);

            Canvas canvas = camera.Render(world, options);

            return(canvas);
        }